rouge 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -207,31 +207,26 @@ module Rouge
207
207
  structure-object symbol synonym-stream t two-way-stream vector
208
208
  )
209
209
 
210
- def stream_tokens(*a, &b)
211
- super(*a) do |tok, val|
212
- case tok
213
- when Token['Name.Variable']
214
- if BUILTIN_FUNCTIONS.include? val
215
- yield Token['Name.Builtin'], val
216
- elsif SPECIAL_FORMS.include? val
217
- yield Token['Keyword'], val
218
- elsif MACROS.include? val
219
- yield Token['Name.Builtin'], val
220
- elsif LAMBDA_LIST_KEYWORDS.include? val
221
- yield Token['Keyword'], val
222
- elsif DECLARATIONS.include? val
223
- yield Token['Keyword'], val
224
- elsif BUILTIN_TYPES.include? val
225
- yield Token['Keyword.Type'], val
226
- elsif BUILTIN_CLASSES.include? val
227
- yield Token['Name.Class'], val
228
- else
229
- yield tok, val
230
- end
231
- else
232
- yield tok, val
233
- end
210
+ postprocess 'Name.Variable' do |tok, val|
211
+ tok = if BUILTIN_FUNCTIONS.include? val
212
+ 'Name.Builtin'
213
+ elsif SPECIAL_FORMS.include? val
214
+ 'Keyword'
215
+ elsif MACROS.include? val
216
+ 'Name.Builtin'
217
+ elsif LAMBDA_LIST_KEYWORDS.include? val
218
+ 'Keyword'
219
+ elsif DECLARATIONS.include? val
220
+ 'Keyword'
221
+ elsif BUILTIN_TYPES.include? val
222
+ 'Keyword.Type'
223
+ elsif BUILTIN_CLASSES.include? val
224
+ 'Name.Class'
225
+ else
226
+ 'Name.Variable'
234
227
  end
228
+
229
+ token tok, val
235
230
  end
236
231
 
237
232
  nonmacro = /\\.|[a-zA-Z0-9!$%&*+-\/<=>?@\[\]^_{}~]/
@@ -1,6 +1,6 @@
1
1
  module Rouge
2
2
  module Lexers
3
- class ERB < RegexLexer
3
+ class ERB < TemplateLexer
4
4
  tag 'erb'
5
5
  aliases 'eruby', 'rhtml'
6
6
 
@@ -11,19 +11,13 @@ module Rouge
11
11
  end
12
12
 
13
13
  def initialize(opts={})
14
- @parent = opts.delete(:parent) || 'html'
15
- if @parent.is_a? String
16
- lexer_class = Lexer.find(@parent)
17
- @parent = lexer_class.new(opts)
18
- end
19
-
20
14
  @ruby_lexer = Ruby.new(opts)
21
15
 
22
16
  super(opts)
23
17
  end
24
18
 
25
19
  start do
26
- @parent.reset!
20
+ parent.reset!
27
21
  @ruby_lexer.reset!
28
22
  end
29
23
 
@@ -36,7 +30,7 @@ module Rouge
36
30
  rule open, 'Comment.Preproc', :ruby
37
31
 
38
32
  rule /.+?(?=#{open})|.+/m do
39
- delegate @parent
33
+ delegate parent
40
34
  end
41
35
  end
42
36
 
@@ -0,0 +1,300 @@
1
+ module Rouge
2
+ module Lexers
3
+ class Factor < RegexLexer
4
+ tag 'factor'
5
+ filenames '*.factor'
6
+ mimetypes 'text/x-factor'
7
+
8
+ def self.analyze_text(text)
9
+ return 1 if text.shebang? 'factor'
10
+ end
11
+
12
+ def self.builtins
13
+ @builtins ||= {}.tap do |builtins|
14
+ builtins[:kernel] = Set.new %w(
15
+ or 2bi 2tri while wrapper nip 4dip wrapper? bi*
16
+ callstack>array both? hashcode die dupd callstack
17
+ callstack? 3dup tri@ pick curry build ?execute 3bi prepose
18
+ >boolean if clone eq? tri* ? = swapd 2over 2keep 3keep clear
19
+ 2dup when not tuple? dup 2bi* 2tri* call tri-curry object bi@
20
+ do unless* if* loop bi-curry* drop when* assert= retainstack
21
+ assert? -rot execute 2bi@ 2tri@ boa with either? 3drop bi
22
+ curry? datastack until 3dip over 3curry tri-curry* tri-curry@
23
+ swap and 2nip throw bi-curry (clone) hashcode* compose 2dip if
24
+ 3tri unless compose? tuple keep 2curry equal? assert tri 2drop
25
+ most <wrapper> boolean? identity-hashcode identity-tuple?
26
+ null new dip bi-curry@ rot xor identity-tuple boolean
27
+ )
28
+
29
+ builtins[:assocs] = Set.new %w(
30
+ ?at assoc? assoc-clone-like assoc= delete-at* assoc-partition
31
+ extract-keys new-assoc value? assoc-size map>assoc push-at
32
+ assoc-like key? assoc-intersect assoc-refine update
33
+ assoc-union assoc-combine at* assoc-empty? at+ set-at
34
+ assoc-all? assoc-subset? assoc-hashcode change-at assoc-each
35
+ assoc-diff zip values value-at rename-at inc-at enum? at cache
36
+ assoc>map <enum> assoc assoc-map enum value-at* assoc-map-as
37
+ >alist assoc-filter-as clear-assoc assoc-stack maybe-set-at
38
+ substitute assoc-filter 2cache delete-at assoc-find keys
39
+ assoc-any? unzip
40
+ )
41
+
42
+ builtins[:combinators] = Set.new %w(
43
+ case execute-effect no-cond no-case? 3cleave>quot 2cleave
44
+ cond>quot wrong-values? no-cond? cleave>quot no-case case>quot
45
+ 3cleave wrong-values to-fixed-point alist>quot case-find
46
+ cond cleave call-effect 2cleave>quot recursive-hashcode
47
+ linear-case-quot spread spread>quot
48
+ )
49
+
50
+ builtins[:math] = Set.new %w(
51
+ number= if-zero next-power-of-2 each-integer ?1+
52
+ fp-special? imaginary-part unless-zero float>bits number?
53
+ fp-infinity? bignum? fp-snan? denominator fp-bitwise= *
54
+ + power-of-2? - u>= / >= bitand log2-expects-positive <
55
+ log2 > integer? number bits>double 2/ zero? (find-integer)
56
+ bits>float float? shift ratio? even? ratio fp-sign bitnot
57
+ >fixnum complex? /i /f byte-array>bignum when-zero sgn >bignum
58
+ next-float u< u> mod recip rational find-last-integer >float
59
+ (all-integers?) 2^ times integer fixnum? neg fixnum sq bignum
60
+ (each-integer) bit? fp-qnan? find-integer complex <fp-nan>
61
+ real double>bits bitor rem fp-nan-payload all-integers?
62
+ real-part log2-expects-positive? prev-float align unordered?
63
+ float fp-nan? abs bitxor u<= odd? <= /mod rational? >integer
64
+ real? numerator
65
+ )
66
+
67
+ builtins[:sequences] = Set.new %w(
68
+ member-eq? append assert-sequence= find-last-from
69
+ trim-head-slice clone-like 3sequence assert-sequence? map-as
70
+ last-index-from reversed index-from cut* pad-tail
71
+ remove-eq! concat-as but-last snip trim-tail nths
72
+ nth 2selector sequence slice? <slice> partition
73
+ remove-nth tail-slice empty? tail* if-empty
74
+ find-from virtual-sequence? member? set-length
75
+ drop-prefix unclip unclip-last-slice iota map-sum
76
+ bounds-error? sequence-hashcode-step selector-for
77
+ accumulate-as map start midpoint@ (accumulate) rest-slice
78
+ prepend fourth sift accumulate! new-sequence follow map! like
79
+ first4 1sequence reverse slice unless-empty padding virtual@
80
+ repetition? set-last index 4sequence max-length set-second
81
+ immutable-sequence first2 first3 replicate-as reduce-index
82
+ unclip-slice supremum suffix! insert-nth trim-tail-slice
83
+ tail 3append short count suffix concat flip filter sum
84
+ immutable? reverse! 2sequence map-integers delete-all start*
85
+ indices snip-slice check-slice sequence? head map-find
86
+ filter! append-as reduce sequence= halves collapse-slice
87
+ interleave 2map filter-as binary-reduce slice-error? product
88
+ bounds-check? bounds-check harvest immutable virtual-exemplar
89
+ find produce remove pad-head last replicate set-fourth
90
+ remove-eq shorten reversed? map-find-last 3map-as
91
+ 2unclip-slice shorter? 3map find-last head-slice pop* 2map-as
92
+ tail-slice* but-last-slice 2map-reduce iota? collector-for
93
+ accumulate each selector append! new-resizable cut-slice
94
+ each-index head-slice* 2reverse-each sequence-hashcode
95
+ pop set-nth ?nth <flat-slice> second join when-empty
96
+ collector immutable-sequence? <reversed> all? 3append-as
97
+ virtual-sequence subseq? remove-nth! push-either new-like
98
+ length last-index push-if 2all? lengthen assert-sequence
99
+ copy map-reduce move third first 3each tail? set-first prefix
100
+ bounds-error any? <repetition> trim-slice exchange surround
101
+ 2reduce cut change-nth min-length set-third produce-as
102
+ push-all head? delete-slice rest sum-lengths 2each head*
103
+ infimum remove! glue slice-error subseq trim replace-slice
104
+ push repetition map-index trim-head unclip-last mismatch
105
+ )
106
+
107
+ builtins[:namespaces] = Set.new %w(
108
+ global +@ change set-namestack change-global init-namespaces
109
+ on off set-global namespace set with-scope bind with-variable
110
+ inc dec counter initialize namestack get get-global make-assoc
111
+ )
112
+
113
+ builtins[:arrays] = Set.new %w(
114
+ <array> 2array 3array pair >array 1array 4array pair?
115
+ array resize-array array?
116
+ )
117
+
118
+ builtins[:io] = Set.new %w(
119
+ +character+ bad-seek-type? readln each-morsel
120
+ stream-seek read print with-output-stream contents
121
+ write1 stream-write1 stream-copy stream-element-type
122
+ with-input-stream stream-print stream-read stream-contents
123
+ stream-tell tell-output bl seek-output bad-seek-type nl
124
+ stream-nl write flush stream-lines +byte+ stream-flush
125
+ read1 seek-absolute? stream-read1 lines stream-readln
126
+ stream-read-until each-line seek-end with-output-stream*
127
+ seek-absolute with-streams seek-input seek-relative?
128
+ input-stream stream-write read-partial seek-end?
129
+ seek-relative error-stream read-until with-input-stream*
130
+ with-streams* tell-input each-block output-stream
131
+ stream-read-partial each-stream-block each-stream-line
132
+ )
133
+
134
+ builtins[:strings] = Set.new %w(
135
+ resize-string >string <string> 1string string string?
136
+ )
137
+
138
+ builtins[:vectors] = Set.new %w(
139
+ with-return restarts return-continuation with-datastack
140
+ recover rethrow-restarts <restart> ifcc set-catchstack
141
+ >continuation< cleanup ignore-errors restart?
142
+ compute-restarts attempt-all-error error-thread
143
+ continue <continuation> attempt-all-error? condition?
144
+ <condition> throw-restarts error catchstack continue-with
145
+ thread-error-hook continuation rethrow callcc1
146
+ error-continuation callcc0 attempt-all condition
147
+ continuation? restart return
148
+ )
149
+
150
+ builtins[:continuations] = Set.new %w(
151
+ with-return restarts return-continuation with-datastack
152
+ recover rethrow-restarts <restart> ifcc set-catchstack
153
+ >continuation< cleanup ignore-errors restart?
154
+ compute-restarts attempt-all-error error-thread
155
+ continue <continuation> attempt-all-error? condition?
156
+ <condition> throw-restarts error catchstack continue-with
157
+ thread-error-hook continuation rethrow callcc1
158
+ error-continuation callcc0 attempt-all condition
159
+ continuation? restart return
160
+ )
161
+ end
162
+ end
163
+
164
+ state :root do
165
+ rule /\s+/m, 'Text'
166
+
167
+ rule /(:|::|MACRO:|MEMO:|GENERIC:|HELP:)(\s+)(\S+)/m do
168
+ group 'Keyword'; group 'Text'
169
+ group 'Name.Function'
170
+ end
171
+
172
+ rule /(M:|HOOK:|GENERIC#)(\s+)(\S+)(\s+)(\S+)/m do
173
+ group 'Keyword'; group 'Text'
174
+ group 'Name.Class'; group 'Text'
175
+ group 'Name.Function'
176
+ end
177
+
178
+ rule /\((?=\s)/, 'Name.Function', :stack_effect
179
+ rule /;(?=\s)/, 'Keyword'
180
+
181
+ rule /(USING:)((?:\s|\\\s)+)/m do
182
+ group 'Keyword.Namespace'; group 'Text'
183
+ push :import
184
+ end
185
+
186
+ rule /(IN:|USE:|UNUSE:|QUALIFIED:|QUALIFIED-WITH:)(\s+)(\S+)/m do
187
+ group 'Keyword.Namespace'; group 'Text'; group 'Name.Namespace'
188
+ end
189
+
190
+ rule /(FROM:|EXCLUDE:)(\s+)(\S+)(\s+)(=>)/m do
191
+ group 'Keyword.Namespace'; group 'Text'
192
+ group 'Name.Namespace'; group 'Text'
193
+ group 'Punctuation'
194
+ end
195
+
196
+ rule /(?:ALIAS|DEFER|FORGET|POSTPONE):/, 'Keyword.Namespace'
197
+
198
+ rule /(TUPLE:)(\s+)(\S+)(\s+)(<)(\s+)(\S+)/m do
199
+ group 'Keyword'; group 'Text'
200
+ group 'Name.Class'; group 'Text'
201
+ group 'Punctuation'; group 'Text'
202
+ group 'Name.Class'
203
+ push :slots
204
+ end
205
+
206
+ rule /(TUPLE:)(\s+)(\S+)/m do
207
+ group 'Keyword'; group 'Text'; group 'Name.Class'
208
+ push :slots
209
+ end
210
+
211
+ rule /(UNION:|INTERSECTION:)(\s+)(\S+)/m do
212
+ group 'Keyword'; group 'Text'; group 'Name.Class'
213
+ end
214
+
215
+ rule /(PREDICATE:)(\s+)(\S+)(\s+)(<)(\s+)(\S+)/m do
216
+ group 'Keyword'; group 'Text'
217
+ group 'Name.Class'; group 'Text'
218
+ group 'Punctuation'; group 'Text'
219
+ group 'Name.Class'
220
+ end
221
+
222
+ rule /(C:)(\s+)(\S+)(\s+)(\S+)/m do
223
+ group 'Keyword'; group 'Text'
224
+ group 'Name.Function'; group 'Text'
225
+ group 'Name.Class'
226
+ end
227
+
228
+ rule %r(
229
+ (INSTANCE|SLOT|MIXIN|SINGLETONS?|CONSTANT|SYMBOLS?|ERROR|SYNTAX
230
+ |ALIEN|TYPEDEF|FUNCTION|STRUCT):
231
+ )x, 'Keyword'
232
+
233
+ rule /(?:<PRIVATE|PRIVATE>)/, 'Keyword.Namespace'
234
+
235
+ rule /(MAIN:)(\s+)(\S+)/ do
236
+ group 'Keyword.Namespace'; group 'Text'; group 'Name.Function'
237
+ end
238
+
239
+ # strings
240
+ rule /"""\s+.*?\s+"""/, 'Literal.String'
241
+ rule /"(\\.|[^\\])*?"/, 'Literal.String'
242
+ rule /(CHAR:)(\s+)(\\[\\abfnrstv]*|\S)(?=\s)/, 'Literal.String.Char'
243
+
244
+ # comments
245
+ rule /!\s+.*$/, 'Comment'
246
+ rule /#!\s+.*$/, 'Comment'
247
+
248
+ # booleans
249
+ rule /[tf](?=\s)/, 'Name.Constant'
250
+
251
+ # numbers
252
+ rule /-?\d+\.\d+(?=\s)/, 'Literal.Number.Float'
253
+ rule /-?\d+(?=\s)/, 'Literal.Number.Integer'
254
+
255
+ rule /HEX:\s+[a-fA-F\d]+(?=\s)/m, 'Literal.Number.Hex'
256
+ rule /BIN:\s+[01]+(?=\s)/, 'Literal.Number.Bin'
257
+ rule /OCT:\s+[0-7]+(?=\s)/, 'Literal.Number.Oct'
258
+
259
+ rule %r([-+/*=<>^](?=\s)), 'Operator'
260
+
261
+ rule /(?:deprecated|final|foldable|flushable|inline|recursive)(?=\s)/,
262
+ 'Keyword'
263
+
264
+ # words, to be postprocessed for builtins and things
265
+ rule /\S+/, 'Postprocess.Word'
266
+ end
267
+
268
+ state :stack_effect do
269
+ rule /\s+/, 'Text'
270
+ rule /\(/, 'Name.Function', :stack_effect
271
+ rule /\)/, 'Name.Function', :pop!
272
+
273
+ rule /--/, 'Name.Function'
274
+ rule /\S+/, 'Name.Variable'
275
+ end
276
+
277
+ state :slots do
278
+ rule /\s+/, 'Text'
279
+ rule /;(?=\s)/, 'Keyword', :pop!
280
+ rule /\S+/, 'Name.Variable'
281
+ end
282
+
283
+ state :import do
284
+ rule /;(?=\s)/, 'Keyword', :pop!
285
+ rule /\s+/, 'Text'
286
+ rule /\S+/, 'Name.Namespace'
287
+ end
288
+
289
+ postprocess 'Postprocess.Word' do |tok, val|
290
+ tok = if self.class.builtins.values.any? { |b| b.include? val }
291
+ 'Name.Builtin'
292
+ else
293
+ 'Name'
294
+ end
295
+
296
+ token tok, val
297
+ end
298
+ end
299
+ end
300
+ end
@@ -0,0 +1,238 @@
1
+ module Rouge
2
+ module Lexers
3
+ class Haml < RegexLexer
4
+ tag 'haml'
5
+ aliases 'HAML'
6
+
7
+ filenames '*.haml'
8
+ mimetypes 'text/x-haml'
9
+
10
+ def self.analyze_text(text)
11
+ return 0.1 if text.start_with? '!!!'
12
+ end
13
+
14
+ # option :filters is a hash of filter name to lexer of how
15
+ # various filters should be highlighted. By default, :javascript
16
+ # and :stylesheet are supported.
17
+ def initialize(opts={})
18
+ (opts.delete(:filters) || {}).each do |name, lexer|
19
+ unless lexer.respond_to? :lex
20
+ lexer = Lexer.find(lexer) or raise "unknown lexer: #{lexer}"
21
+ lexer = lexer.new(options)
22
+ end
23
+
24
+ self.filters[name.to_s] = lexer
25
+ end
26
+
27
+ super(opts)
28
+ end
29
+
30
+ def ruby
31
+ @ruby ||= Ruby.new(options)
32
+ end
33
+
34
+ def html
35
+ @html ||= HTML.new(options)
36
+ end
37
+
38
+ def filters
39
+ @filters ||= {
40
+ 'javascript' => Javascript.new(options),
41
+ 'css' => CSS.new(options),
42
+ 'ruby' => ruby,
43
+ 'erb' => ERB.new(options),
44
+ # TODO
45
+ # 'sass' => Sass.new(options),
46
+ # 'textile' => Textile.new(options),
47
+ # 'markdown' => Markdown.new(options),
48
+ # 'maruku' => Maruku.new(options),
49
+ }
50
+ end
51
+
52
+ start { ruby.reset!; html.reset! }
53
+
54
+ # push a state for the next indented block
55
+ def starts_block(block_state)
56
+ @block_state = block_state
57
+ @block_indentation = @last_indentation || ''
58
+ debug { " haml: starts_block #{block_state.inspect}" }
59
+ debug { " haml: block_indentation: #{@block_indentation.inspect}" }
60
+ end
61
+
62
+ def indentation(indent_str)
63
+ debug { " haml: indentation #{indent_str.inspect}" }
64
+ debug { " haml: block_indentation: #{@block_indentation.inspect}" }
65
+ @last_indentation = indent_str
66
+
67
+ # if it's an indent and we know where to go next,
68
+ # push that state. otherwise, push content and
69
+ # clear the block state.
70
+ if (@block_state &&
71
+ indent_str.start_with?(@block_indentation) &&
72
+ indent_str != @block_indentation
73
+ )
74
+ push @block_state
75
+ else
76
+ @block_state = @block_indentation = nil
77
+ push :content
78
+ end
79
+ end
80
+
81
+ identifier = /[\w:-]+/
82
+ ruby_var = /[a-z]\w*/
83
+
84
+ # Haml can include " |\n" anywhere,
85
+ # which is ignored and used to wrap long lines.
86
+ # To accomodate this, use this custom faux dot instead.
87
+ dot = /[ ]\|\n(?=.*[ ]\|)|./
88
+
89
+ # In certain places, a comma at the end of the line
90
+ # allows line wrapping as well.
91
+ comma_dot = /,\s*\n|#{dot}/
92
+
93
+ state :root do
94
+ rule /\s*\n/, 'Text'
95
+ rule(/\s*/) { |m| token 'Text'; indentation(m[0]) }
96
+ end
97
+
98
+ state :content do
99
+ mixin :css
100
+ rule(/%#{identifier}/) { token 'Name.Tag'; pop!; push :tag }
101
+ rule /!!!#{dot}*\n/, 'Name.Namespace', :pop!
102
+ rule %r(
103
+ (/) (\[#{dot}*?\]) (#{dot}*\n)
104
+ )x do
105
+ group 'Comment'; group 'Comment.Special'; group 'Comment'
106
+ pop!
107
+ end
108
+
109
+ rule %r(/#{dot}*\n) do
110
+ token 'Comment'
111
+ pop!
112
+ starts_block :html_comment_block
113
+ end
114
+
115
+ rule /-##{dot}*\n/ do
116
+ token 'Comment'
117
+ pop!
118
+ starts_block :haml_comment_block
119
+ end
120
+
121
+ rule /-/ do
122
+ token 'Punctuation'
123
+ reset_stack
124
+ push :ruby_line
125
+ end
126
+
127
+ # filters
128
+ rule /:(#{dot}*)\n/ do |m|
129
+ token 'Name.Decorator'
130
+ pop!
131
+ starts_block :filter_block
132
+
133
+ filter_name = m[1].strip
134
+
135
+ @filter_lexer = self.filters[filter_name]
136
+ @filter_lexer.reset! unless @filter_lexer.nil?
137
+
138
+ debug { " haml: filter #{filter_name.inspect} #{@filter_lexer.inspect}" }
139
+ end
140
+
141
+ mixin :eval_or_plain
142
+ end
143
+
144
+ state :css do
145
+ rule(/\.#{identifier}/) { token 'Name.Class'; pop!; push :tag }
146
+ rule(/##{identifier}/) { token 'Name.Function'; pop!; push :tag }
147
+ end
148
+
149
+ state :tag do
150
+ mixin :css
151
+ rule(/\{#{comma_dot}*?\}/) { delegate ruby }
152
+ rule(/\[#{dot}*?\]/) { delegate ruby }
153
+ rule /\(/, 'Punctuation', :html_attributes
154
+ rule /\s*\n/, 'Text', :pop!
155
+
156
+ # whitespace chompers
157
+ rule /[<>]{1,2}(?=[ \t=])/, 'Punctuation'
158
+
159
+ mixin :eval_or_plain
160
+ end
161
+
162
+ state :plain do
163
+ rule(/([^#\n]|#[^{\n]|(\\\\)*\\#\{)+/) { delegate html }
164
+ mixin :interpolation
165
+ rule(/\n/) { token 'Text'; reset_stack }
166
+ end
167
+
168
+ state :eval_or_plain do
169
+ rule /[&!]?==/, 'Punctuation', :plain
170
+ rule /[&!]?[=!]/ do
171
+ token 'Punctuation'
172
+ reset_stack
173
+ push :ruby_line
174
+ end
175
+
176
+ rule(//) { push :plain }
177
+ end
178
+
179
+ state :ruby_line do
180
+ rule /\n/, 'Text', :pop!
181
+ rule(/,[ \t]*\n/) { delegate ruby }
182
+ rule /[ ]\|[ \t]*\n/, 'Literal.String.Escape'
183
+ rule(/.*?(?=(,$| \|)?[ \t]*$)/) { delegate ruby }
184
+ end
185
+
186
+ state :html_attributes do
187
+ rule /\s+/, 'Text'
188
+ rule /#{identifier}\s*=/, 'Name.Attribute', :html_attribute_value
189
+ rule identifier, 'Name.Attribute'
190
+ rule /\)/, 'Text', :pop!
191
+ end
192
+
193
+ state :html_attribute_value do
194
+ rule /\s+/, 'Text'
195
+ rule ruby_var, 'Name.Variable', :pop!
196
+ rule /@#{ruby_var}/, 'Name.Variable.Instance', :pop!
197
+ rule /\$#{ruby_var}/, 'Name.Variable.Global', :pop!
198
+ rule /'(\\\\|\\'|[^'\n])*'/, 'Literal.String', :pop!
199
+ rule /"(\\\\|\\"|[^"\n])*"/, 'Literal.String', :pop!
200
+ end
201
+
202
+ state :html_comment_block do
203
+ rule /#{dot}+/, 'Comment'
204
+ mixin :indented_block
205
+ end
206
+
207
+ state :haml_comment_block do
208
+ rule /#{dot}+/, 'Comment.Preproc'
209
+ mixin :indented_block
210
+ end
211
+
212
+ state :filter_block do
213
+ rule /([^#\n]|#[^{\n]|(\\\\)*\\#\{)+/ do
214
+ if @filter_lexer
215
+ delegate @filter_lexer
216
+ else
217
+ token 'Name.Decorator'
218
+ end
219
+ end
220
+
221
+ mixin :interpolation
222
+ mixin :indented_block
223
+ end
224
+
225
+ state :interpolation do
226
+ rule /(#\{)(#{dot}*?)(\})/ do |m|
227
+ token 'Literal.String.Interpol', m[1]
228
+ delegate ruby, m[2]
229
+ token 'Literal.String.Interpol', m[3]
230
+ end
231
+ end
232
+
233
+ state :indented_block do
234
+ rule(/\n/) { token 'Text'; reset_stack }
235
+ end
236
+ end
237
+ end
238
+ end