ruby_parser-legacy 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ruby_parser-legacy might be problematic. Click here for more details.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +1 -0
- data.tar.gz.sig +1 -0
- data/.autotest +26 -0
- data/History.rdoc +6 -0
- data/Manifest.txt +19 -0
- data/README.rdoc +54 -0
- data/Rakefile +49 -0
- data/lib/ruby_parser/legacy.rb +5 -0
- data/lib/ruby_parser/legacy/ruby18_parser.rb +5794 -0
- data/lib/ruby_parser/legacy/ruby18_parser.y +1909 -0
- data/lib/ruby_parser/legacy/ruby19_parser.rb +6186 -0
- data/lib/ruby_parser/legacy/ruby19_parser.y +2117 -0
- data/lib/ruby_parser/legacy/ruby_lexer.rb +1412 -0
- data/lib/ruby_parser/legacy/ruby_lexer.rex +179 -0
- data/lib/ruby_parser/legacy/ruby_lexer.rex.rb +323 -0
- data/lib/ruby_parser/legacy/ruby_parser.rb +30 -0
- data/lib/ruby_parser/legacy/ruby_parser_extras.rb +1388 -0
- data/test/ruby_parser/test_legacy.rb +8 -0
- data/test/ruby_parser/test_ruby_lexer.rb +2984 -0
- data/test/ruby_parser/test_ruby_parser.rb +3951 -0
- data/test/ruby_parser/test_ruby_parser_extras.rb +226 -0
- metadata +181 -0
- metadata.gz.sig +0 -0
@@ -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
|