ruby_parser-legacy 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby_parser-legacy might be problematic. Click here for more details.

@@ -0,0 +1,179 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # lexical scanner definition for ruby
4
+
5
+ class RubyParser::Legacy::RubyLexer
6
+
7
+ macro
8
+
9
+ IDENT /^#{IDENT_CHAR}+/o
10
+
11
+ ESC /\\((?>[0-7]{1,3}|x[0-9a-fA-F]{1,2}|M-[^\\]|(C-|c)[^\\]|u[0-9a-fA-F]+|u\{[0-9a-fA-F]+\}|[^0-7xMCc]))/
12
+ SIMPLE_STRING /((#{ESC}|\#(#{ESC}|[^\{\#\@\$\"\\])|[^\"\\\#])*)/o
13
+ SSTRING /((\\.|[^\'])*)/
14
+
15
+ INT_DEC /[+]?(?:(?:[1-9][\d_]*|0)(?!\.\d)(ri|r|i)?\b|0d[0-9_]+)(ri|r|i)?/i
16
+ INT_HEX /[+]?0x[a-f0-9_]+(ri|r|i)?/i
17
+ INT_BIN /[+]?0b[01_]+(ri|r|i)?/i
18
+ INT_OCT /[+]?0o?[0-7_]+(ri|r|i)?|0o(ri|r|i)?/i
19
+ FLOAT /[+]?\d[\d_]*\.[\d_]+(e[+-]?[\d_]+)?(?:(ri|r|i)\b)?|[+]?[\d_]+e[+-]?[\d_]+(?:(ri|r|i)\b)?/i
20
+ INT_DEC2 /[+]?\d[0-9_]*(?![e])((ri|r|i)\b)?/i
21
+
22
+ NUM_BAD /[+]?0[xbd]\b/i
23
+ INT_OCT_BAD /[+]?0o?[0-7_]*[89]/i
24
+ FLOAT_BAD /[+]?\d[\d_]*_(e|\.)/i
25
+
26
+ start
27
+
28
+ return process_string if lex_strterm
29
+
30
+ self.cmd_state = self.command_start
31
+ self.command_start = false
32
+ self.space_seen = false # TODO: rename token_seen?
33
+ self.last_state = lex_state
34
+
35
+ rule
36
+
37
+ # [:state] pattern [actions]
38
+
39
+ # \s - \n + \v
40
+ /[\ \t\r\f\v]/ { self.space_seen = true; next }
41
+
42
+ /\n|\#/ process_newline_or_comment
43
+
44
+ /[\]\)\}]/ process_brace_close
45
+
46
+ : /\!/
47
+ | in_arg_state? /\!\@/ { result :expr_arg, :tUBANG, "!@" }
48
+ | /\![=~]?/ { result :arg_state, TOKENS[text], text }
49
+
50
+ : /\./
51
+ | /\.\.\.?/ { result :expr_beg, TOKENS[text], text }
52
+ | /\.\d/ { rb_compile_error "no .<digit> floating literal anymore put 0 before dot" }
53
+ | /\./ { self.lex_state = :expr_beg; result :expr_dot, :tDOT, "." }
54
+
55
+ /\(/ process_paren
56
+
57
+ # TODO: :expr_beg|:expr_label
58
+ /\,/ { result :expr_beg, TOKENS[text], text }
59
+
60
+ : /=/
61
+ | /\=\=\=|\=\=|\=~|\=>|\=(?!begin\b)/ { result arg_state, TOKENS[text], text }
62
+ | bol? /\=begin(?=\s)/ process_begin
63
+ | /\=(?=begin\b)/ { result arg_state, TOKENS[text], text }
64
+
65
+ ruby22_label? /\"#{SIMPLE_STRING}\":/o process_label
66
+ /\"(#{SIMPLE_STRING})\"/o { result :expr_end, :tSTRING, text[1..-2].gsub(ESC) { unescape $1 } }
67
+ /\"/ { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
68
+
69
+ /\@\@?\d/ { rb_compile_error "`#{text}` is not allowed as a variable name" }
70
+ /\@\@?#{IDENT_CHAR}+/o process_ivar
71
+
72
+ : /:/
73
+ | not_end? /:([a-zA-Z_]#{IDENT_CHAR}*(?:[?]|[!](?!=)|=(?==>)|=(?![=>]))?)/o process_symbol
74
+ | not_end? /\:\"(#{SIMPLE_STRING})\"/o process_symbol
75
+ | not_end? /\:\'(#{SSTRING})\'/o process_symbol
76
+ | /\:\:/ process_colon2
77
+ | /\:/ process_colon1
78
+
79
+ /->/ { result :expr_endfn, :tLAMBDA, nil }
80
+
81
+ /[+-]/ process_plus_minus
82
+
83
+ : /[+\d]/
84
+ | /#{NUM_BAD}/o { rb_compile_error "Invalid numeric format" }
85
+ | /#{INT_DEC}/o { int_with_base 10 }
86
+ | /#{INT_HEX}/o { int_with_base 16 }
87
+ | /#{INT_BIN}/o { int_with_base 2 }
88
+ | /#{INT_OCT_BAD}/o { rb_compile_error "Illegal octal digit." }
89
+ | /#{INT_OCT}/o { int_with_base 8 }
90
+ | /#{FLOAT_BAD}/o { rb_compile_error "Trailing '_' in number." }
91
+ | /#{FLOAT}/o process_float
92
+ | /#{INT_DEC2}/o { int_with_base 10 }
93
+ | /[0-9]/ { rb_compile_error "Bad number format" }
94
+
95
+ /\[/ process_square_bracket
96
+
97
+ was_label? /\'#{SSTRING}\':?/o process_label_or_string
98
+
99
+ : /\|/
100
+ | /\|\|\=/ { result :expr_beg, :tOP_ASGN, "||" }
101
+ | /\|\|/ { result :expr_beg, :tOROP, "||" }
102
+ | /\|\=/ { result :expr_beg, :tOP_ASGN, "|" }
103
+ | /\|/ { result :arg_state, :tPIPE, "|" }
104
+
105
+ /\{/ process_brace_open
106
+
107
+ : /\*/
108
+ | /\*\*=/ { result :expr_beg, :tOP_ASGN, "**" }
109
+ | /\*\*/ { result(:arg_state, space_vs_beginning(:tDSTAR, :tDSTAR, :tPOW), "**") }
110
+ | /\*\=/ { result(:expr_beg, :tOP_ASGN, "*") }
111
+ | /\*/ { result(:arg_state, space_vs_beginning(:tSTAR, :tSTAR, :tSTAR2), "*") }
112
+
113
+ # TODO: fix result+process_lchevron to set command_start = true
114
+ : /</
115
+ | /\<\=\>/ { result :arg_state, :tCMP, "<=>" }
116
+ | /\<\=/ { result :arg_state, :tLEQ, "<=" }
117
+ | /\<\<\=/ { result :expr_beg, :tOP_ASGN, "<<" }
118
+ | /\<\</ process_lchevron
119
+ | /\</ { result :arg_state, :tLT, "<" }
120
+
121
+ : />/
122
+ | /\>\=/ { result :arg_state, :tGEQ, ">=" }
123
+ | /\>\>=/ { result :expr_beg, :tOP_ASGN, ">>" }
124
+ | /\>\>/ { result :arg_state, :tRSHFT, ">>" }
125
+ | /\>/ { result :arg_state, :tGT, ">" }
126
+
127
+ : /\`/
128
+ | expr_fname? /\`/ { result(:expr_end, :tBACK_REF2, "`") }
129
+ | expr_dot? /\`/ { result((cmd_state ? :expr_cmdarg : :expr_arg), :tBACK_REF2, "`") }
130
+ | /\`/ { string STR_XQUOTE, '`'; result(nil, :tXSTRING_BEG, "`") }
131
+
132
+ /\?/ process_questionmark
133
+
134
+ : /&/
135
+ | /\&\&\=/ { result(:expr_beg, :tOP_ASGN, "&&") }
136
+ | /\&\&/ { result(:expr_beg, :tANDOP, "&&") }
137
+ | /\&\=/ { result(:expr_beg, :tOP_ASGN, "&" ) }
138
+ | /\&\./ { result(:expr_dot, :tLONELY, "&.") }
139
+ | /\&/ process_amper
140
+
141
+ /\// process_slash
142
+
143
+ : /\^/
144
+ | /\^=/ { result(:expr_beg, :tOP_ASGN, "^") }
145
+ | /\^/ { result(:arg_state, :tCARET, "^") }
146
+
147
+ /\;/ { self.command_start = true; result(:expr_beg, :tSEMI, ";") }
148
+
149
+ : /~/
150
+ | in_arg_state? /\~@/ { result(:arg_state, :tTILDE, "~") }
151
+ | /\~/ { result(:arg_state, :tTILDE, "~") }
152
+
153
+ : /\\/
154
+ | /\\\r?\n/ { self.lineno += 1; self.space_seen = true; next }
155
+ | /\\/ { rb_compile_error "bare backslash only allowed before newline" }
156
+
157
+ /\%/ process_percent
158
+
159
+ : /\$/
160
+ | /\$_\w+/ process_gvar
161
+ | /\$_/ process_gvar
162
+ | /\$[~*$?!@\/\\;,.=:<>\"]|\$-\w?/ process_gvar
163
+ | in_fname? /\$([\&\`\'\+])/ process_gvar
164
+ | /\$([\&\`\'\+])/ process_backref
165
+ | in_fname? /\$([1-9]\d*)/ process_gvar
166
+ | /\$([1-9]\d*)/ process_nthref
167
+ | /\$0/ process_gvar
168
+ | /\$\W|\$\z/ process_gvar_oddity
169
+ | /\$\w+/ process_gvar
170
+
171
+ /\_/ process_underscore
172
+
173
+ /#{IDENT}/o process_token
174
+
175
+ /\004|\032|\000|\Z/ { [RubyLexer::EOF, RubyLexer::EOF] }
176
+
177
+ /./ { rb_compile_error "Invalid char #{text.inspect} in expression" }
178
+
179
+ end
@@ -0,0 +1,323 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # This file is automatically generated. Do not modify it.
4
+ # Generated by: oedipus_lex version 2.5.0.
5
+ # Source: lib/ruby_parser/legacy/ruby_lexer.rex
6
+ #++
7
+
8
+ #
9
+ # lexical scanner definition for ruby
10
+
11
+ class RubyParser::Legacy::RubyLexer
12
+ require 'strscan'
13
+
14
+ IDENT = /^#{IDENT_CHAR}+/o
15
+ ESC = /\\((?>[0-7]{1,3}|x[0-9a-fA-F]{1,2}|M-[^\\]|(C-|c)[^\\]|u[0-9a-fA-F]+|u\{[0-9a-fA-F]+\}|[^0-7xMCc]))/
16
+ SIMPLE_STRING = /((#{ESC}|\#(#{ESC}|[^\{\#\@\$\"\\])|[^\"\\\#])*)/o
17
+ SSTRING = /((\\.|[^\'])*)/
18
+ INT_DEC = /[+]?(?:(?:[1-9][\d_]*|0)(?!\.\d)(ri|r|i)?\b|0d[0-9_]+)(ri|r|i)?/i
19
+ INT_HEX = /[+]?0x[a-f0-9_]+(ri|r|i)?/i
20
+ INT_BIN = /[+]?0b[01_]+(ri|r|i)?/i
21
+ INT_OCT = /[+]?0o?[0-7_]+(ri|r|i)?|0o(ri|r|i)?/i
22
+ FLOAT = /[+]?\d[\d_]*\.[\d_]+(e[+-]?[\d_]+)?(?:(ri|r|i)\b)?|[+]?[\d_]+e[+-]?[\d_]+(?:(ri|r|i)\b)?/i
23
+ INT_DEC2 = /[+]?\d[0-9_]*(?![e])((ri|r|i)\b)?/i
24
+ NUM_BAD = /[+]?0[xbd]\b/i
25
+ INT_OCT_BAD = /[+]?0o?[0-7_]*[89]/i
26
+ FLOAT_BAD = /[+]?\d[\d_]*_(e|\.)/i
27
+
28
+ class LexerError < StandardError ; end
29
+ class ScanError < LexerError ; end
30
+
31
+ attr_accessor :filename
32
+ attr_accessor :ss
33
+ attr_accessor :state
34
+
35
+ alias :match :ss
36
+
37
+ def matches
38
+ m = (1..9).map { |i| ss[i] }
39
+ m.pop until m[-1] or m.empty?
40
+ m
41
+ end
42
+
43
+ def action
44
+ yield
45
+ end
46
+
47
+ def scanner_class
48
+ StringScanner
49
+ end unless instance_methods(false).map(&:to_s).include?("scanner_class")
50
+
51
+ def parse str
52
+ self.ss = scanner_class.new str
53
+ self.state ||= nil
54
+
55
+ do_parse
56
+ end
57
+
58
+ def parse_file path
59
+ self.filename = path
60
+ open path do |f|
61
+ parse f.read
62
+ end
63
+ end
64
+
65
+ def location
66
+ [
67
+ (filename || "<input>"),
68
+ ].compact.join(":")
69
+ end
70
+
71
+ def next_token
72
+ return process_string if lex_strterm
73
+ self.cmd_state = self.command_start
74
+ self.command_start = false
75
+ self.space_seen = false # TODO: rename token_seen?
76
+ self.last_state = lex_state
77
+
78
+ token = nil
79
+
80
+ until ss.eos? or token do
81
+ token =
82
+ case state
83
+ when nil then
84
+ case
85
+ when ss.skip(/[\ \t\r\f\v]/) then
86
+ action { self.space_seen = true; next }
87
+ when text = ss.scan(/\n|\#/) then
88
+ process_newline_or_comment text
89
+ when text = ss.scan(/[\]\)\}]/) then
90
+ process_brace_close text
91
+ when ss.match?(/\!/) then
92
+ case
93
+ when in_arg_state? && (ss.skip(/\!\@/)) then
94
+ action { result :expr_arg, :tUBANG, "!@" }
95
+ when text = ss.scan(/\![=~]?/) then
96
+ action { result :arg_state, TOKENS[text], text }
97
+ end # group /\!/
98
+ when ss.match?(/\./) then
99
+ case
100
+ when text = ss.scan(/\.\.\.?/) then
101
+ action { result :expr_beg, TOKENS[text], text }
102
+ when ss.skip(/\.\d/) then
103
+ action { rb_compile_error "no .<digit> floating literal anymore put 0 before dot" }
104
+ when ss.skip(/\./) then
105
+ action { self.lex_state = :expr_beg; result :expr_dot, :tDOT, "." }
106
+ end # group /\./
107
+ when text = ss.scan(/\(/) then
108
+ process_paren text
109
+ when text = ss.scan(/\,/) then
110
+ action { result :expr_beg, TOKENS[text], text }
111
+ when ss.match?(/=/) then
112
+ case
113
+ when text = ss.scan(/\=\=\=|\=\=|\=~|\=>|\=(?!begin\b)/) then
114
+ action { result arg_state, TOKENS[text], text }
115
+ when bol? && (text = ss.scan(/\=begin(?=\s)/)) then
116
+ process_begin text
117
+ when text = ss.scan(/\=(?=begin\b)/) then
118
+ action { result arg_state, TOKENS[text], text }
119
+ end # group /=/
120
+ when ruby22_label? && (text = ss.scan(/\"#{SIMPLE_STRING}\":/o)) then
121
+ process_label text
122
+ when text = ss.scan(/\"(#{SIMPLE_STRING})\"/o) then
123
+ action { result :expr_end, :tSTRING, text[1..-2].gsub(ESC) { unescape $1 } }
124
+ when text = ss.scan(/\"/) then
125
+ action { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
126
+ when text = ss.scan(/\@\@?\d/) then
127
+ action { rb_compile_error "`#{text}` is not allowed as a variable name" }
128
+ when text = ss.scan(/\@\@?#{IDENT_CHAR}+/o) then
129
+ process_ivar text
130
+ when ss.match?(/:/) then
131
+ case
132
+ when not_end? && (text = ss.scan(/:([a-zA-Z_]#{IDENT_CHAR}*(?:[?]|[!](?!=)|=(?==>)|=(?![=>]))?)/o)) then
133
+ process_symbol text
134
+ when not_end? && (text = ss.scan(/\:\"(#{SIMPLE_STRING})\"/o)) then
135
+ process_symbol text
136
+ when not_end? && (text = ss.scan(/\:\'(#{SSTRING})\'/o)) then
137
+ process_symbol text
138
+ when text = ss.scan(/\:\:/) then
139
+ process_colon2 text
140
+ when text = ss.scan(/\:/) then
141
+ process_colon1 text
142
+ end # group /:/
143
+ when ss.skip(/->/) then
144
+ action { result :expr_endfn, :tLAMBDA, nil }
145
+ when text = ss.scan(/[+-]/) then
146
+ process_plus_minus text
147
+ when ss.match?(/[+\d]/) then
148
+ case
149
+ when ss.skip(/#{NUM_BAD}/o) then
150
+ action { rb_compile_error "Invalid numeric format" }
151
+ when ss.skip(/#{INT_DEC}/o) then
152
+ action { int_with_base 10 }
153
+ when ss.skip(/#{INT_HEX}/o) then
154
+ action { int_with_base 16 }
155
+ when ss.skip(/#{INT_BIN}/o) then
156
+ action { int_with_base 2 }
157
+ when ss.skip(/#{INT_OCT_BAD}/o) then
158
+ action { rb_compile_error "Illegal octal digit." }
159
+ when ss.skip(/#{INT_OCT}/o) then
160
+ action { int_with_base 8 }
161
+ when ss.skip(/#{FLOAT_BAD}/o) then
162
+ action { rb_compile_error "Trailing '_' in number." }
163
+ when text = ss.scan(/#{FLOAT}/o) then
164
+ process_float text
165
+ when ss.skip(/#{INT_DEC2}/o) then
166
+ action { int_with_base 10 }
167
+ when ss.skip(/[0-9]/) then
168
+ action { rb_compile_error "Bad number format" }
169
+ end # group /[+\d]/
170
+ when text = ss.scan(/\[/) then
171
+ process_square_bracket text
172
+ when was_label? && (text = ss.scan(/\'#{SSTRING}\':?/o)) then
173
+ process_label_or_string text
174
+ when ss.match?(/\|/) then
175
+ case
176
+ when ss.skip(/\|\|\=/) then
177
+ action { result :expr_beg, :tOP_ASGN, "||" }
178
+ when ss.skip(/\|\|/) then
179
+ action { result :expr_beg, :tOROP, "||" }
180
+ when ss.skip(/\|\=/) then
181
+ action { result :expr_beg, :tOP_ASGN, "|" }
182
+ when ss.skip(/\|/) then
183
+ action { result :arg_state, :tPIPE, "|" }
184
+ end # group /\|/
185
+ when text = ss.scan(/\{/) then
186
+ process_brace_open text
187
+ when ss.match?(/\*/) then
188
+ case
189
+ when ss.skip(/\*\*=/) then
190
+ action { result :expr_beg, :tOP_ASGN, "**" }
191
+ when ss.skip(/\*\*/) then
192
+ action { result(:arg_state, space_vs_beginning(:tDSTAR, :tDSTAR, :tPOW), "**") }
193
+ when ss.skip(/\*\=/) then
194
+ action { result(:expr_beg, :tOP_ASGN, "*") }
195
+ when ss.skip(/\*/) then
196
+ action { result(:arg_state, space_vs_beginning(:tSTAR, :tSTAR, :tSTAR2), "*") }
197
+ end # group /\*/
198
+ when ss.match?(/</) then
199
+ case
200
+ when ss.skip(/\<\=\>/) then
201
+ action { result :arg_state, :tCMP, "<=>" }
202
+ when ss.skip(/\<\=/) then
203
+ action { result :arg_state, :tLEQ, "<=" }
204
+ when ss.skip(/\<\<\=/) then
205
+ action { result :expr_beg, :tOP_ASGN, "<<" }
206
+ when text = ss.scan(/\<\</) then
207
+ process_lchevron text
208
+ when ss.skip(/\</) then
209
+ action { result :arg_state, :tLT, "<" }
210
+ end # group /</
211
+ when ss.match?(/>/) then
212
+ case
213
+ when ss.skip(/\>\=/) then
214
+ action { result :arg_state, :tGEQ, ">=" }
215
+ when ss.skip(/\>\>=/) then
216
+ action { result :expr_beg, :tOP_ASGN, ">>" }
217
+ when ss.skip(/\>\>/) then
218
+ action { result :arg_state, :tRSHFT, ">>" }
219
+ when ss.skip(/\>/) then
220
+ action { result :arg_state, :tGT, ">" }
221
+ end # group />/
222
+ when ss.match?(/\`/) then
223
+ case
224
+ when expr_fname? && (ss.skip(/\`/)) then
225
+ action { result(:expr_end, :tBACK_REF2, "`") }
226
+ when expr_dot? && (ss.skip(/\`/)) then
227
+ action { result((cmd_state ? :expr_cmdarg : :expr_arg), :tBACK_REF2, "`") }
228
+ when ss.skip(/\`/) then
229
+ action { string STR_XQUOTE, '`'; result(nil, :tXSTRING_BEG, "`") }
230
+ end # group /\`/
231
+ when text = ss.scan(/\?/) then
232
+ process_questionmark text
233
+ when ss.match?(/&/) then
234
+ case
235
+ when ss.skip(/\&\&\=/) then
236
+ action { result(:expr_beg, :tOP_ASGN, "&&") }
237
+ when ss.skip(/\&\&/) then
238
+ action { result(:expr_beg, :tANDOP, "&&") }
239
+ when ss.skip(/\&\=/) then
240
+ action { result(:expr_beg, :tOP_ASGN, "&" ) }
241
+ when ss.skip(/\&\./) then
242
+ action { result(:expr_dot, :tLONELY, "&.") }
243
+ when text = ss.scan(/\&/) then
244
+ process_amper text
245
+ end # group /&/
246
+ when text = ss.scan(/\//) then
247
+ process_slash text
248
+ when ss.match?(/\^/) then
249
+ case
250
+ when ss.skip(/\^=/) then
251
+ action { result(:expr_beg, :tOP_ASGN, "^") }
252
+ when ss.skip(/\^/) then
253
+ action { result(:arg_state, :tCARET, "^") }
254
+ end # group /\^/
255
+ when ss.skip(/\;/) then
256
+ action { self.command_start = true; result(:expr_beg, :tSEMI, ";") }
257
+ when ss.match?(/~/) then
258
+ case
259
+ when in_arg_state? && (ss.skip(/\~@/)) then
260
+ action { result(:arg_state, :tTILDE, "~") }
261
+ when ss.skip(/\~/) then
262
+ action { result(:arg_state, :tTILDE, "~") }
263
+ end # group /~/
264
+ when ss.match?(/\\/) then
265
+ case
266
+ when ss.skip(/\\\r?\n/) then
267
+ action { self.lineno += 1; self.space_seen = true; next }
268
+ when ss.skip(/\\/) then
269
+ action { rb_compile_error "bare backslash only allowed before newline" }
270
+ end # group /\\/
271
+ when text = ss.scan(/\%/) then
272
+ process_percent text
273
+ when ss.match?(/\$/) then
274
+ case
275
+ when text = ss.scan(/\$_\w+/) then
276
+ process_gvar text
277
+ when text = ss.scan(/\$_/) then
278
+ process_gvar text
279
+ when text = ss.scan(/\$[~*$?!@\/\\;,.=:<>\"]|\$-\w?/) then
280
+ process_gvar text
281
+ when in_fname? && (text = ss.scan(/\$([\&\`\'\+])/)) then
282
+ process_gvar text
283
+ when text = ss.scan(/\$([\&\`\'\+])/) then
284
+ process_backref text
285
+ when in_fname? && (text = ss.scan(/\$([1-9]\d*)/)) then
286
+ process_gvar text
287
+ when text = ss.scan(/\$([1-9]\d*)/) then
288
+ process_nthref text
289
+ when text = ss.scan(/\$0/) then
290
+ process_gvar text
291
+ when text = ss.scan(/\$\W|\$\z/) then
292
+ process_gvar_oddity text
293
+ when text = ss.scan(/\$\w+/) then
294
+ process_gvar text
295
+ end # group /\$/
296
+ when text = ss.scan(/\_/) then
297
+ process_underscore text
298
+ when text = ss.scan(/#{IDENT}/o) then
299
+ process_token text
300
+ when ss.skip(/\004|\032|\000|\Z/) then
301
+ action { [RubyLexer::EOF, RubyLexer::EOF] }
302
+ when text = ss.scan(/./) then
303
+ action { rb_compile_error "Invalid char #{text.inspect} in expression" }
304
+ else
305
+ text = ss.string[ss.pos .. -1]
306
+ raise ScanError, "can not match (#{state.inspect}) at #{location}: '#{text}'"
307
+ end
308
+ else
309
+ raise ScanError, "undefined state at #{location}: '#{state}'"
310
+ end # token = case state
311
+
312
+ next unless token # allow functions to trigger redo w/ nil
313
+ end # while
314
+
315
+ raise LexerError, "bad lexical result at #{location}: #{token.inspect}" unless
316
+ token.nil? || (Array === token && token.size >= 2)
317
+
318
+ # auto-switch state
319
+ self.state = token.last if token && token.first == :state
320
+
321
+ token
322
+ end # def next_token
323
+ end # class