ruby_parser 3.13.0 → 3.15.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,9 +6,9 @@ class RubyLexer
6
6
 
7
7
  macro
8
8
 
9
- IDENT /^#{IDENT_CHAR}+/o
9
+ IDENT_CHAR /[a-zA-Z0-9_[:^ascii:]]/
10
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]))/
11
+ ESC /\\((?>[0-7]{1,3}|x\h{1,2}|M-[^\\]|(C-|c)[^\\]|u\h{1,4}|u\{\h+(?:\s+\h+)*\}|[^0-7xMCc]))/
12
12
  SIMPLE_STRING /((#{ESC}|\#(#{ESC}|[^\{\#\@\$\"\\])|[^\"\\\#])*)/o
13
13
  SSTRING /((\\.|[^\'])*)/
14
14
 
@@ -44,18 +44,17 @@ rule
44
44
  /[\]\)\}]/ process_brace_close
45
45
 
46
46
  : /\!/
47
- | in_arg_state? /\!\@/ { result :expr_arg, :tUBANG, "!@" }
47
+ | is_after_operator? /\!\@/ { result EXPR_ARG, :tUBANG, "!@" }
48
48
  | /\![=~]?/ { result :arg_state, TOKENS[text], text }
49
49
 
50
50
  : /\./
51
- | /\.\.\.?/ { result :expr_beg, TOKENS[text], text }
51
+ | /\.\.\.?/ { result EXPR_BEG, TOKENS[text], text }
52
52
  | /\.\d/ { rb_compile_error "no .<digit> floating literal anymore put 0 before dot" }
53
- | /\./ { self.lex_state = :expr_beg; result :expr_dot, :tDOT, "." }
53
+ | /\./ { self.lex_state = EXPR_BEG; result EXPR_DOT, :tDOT, "." }
54
54
 
55
55
  /\(/ process_paren
56
56
 
57
- # TODO: :expr_beg|:expr_label
58
- /\,/ { result :expr_beg, TOKENS[text], text }
57
+ /\,/ { result EXPR_PAR, TOKENS[text], text }
59
58
 
60
59
  : /=/
61
60
  | /\=\=\=|\=\=|\=~|\=>|\=(?!begin\b)/ { result arg_state, TOKENS[text], text }
@@ -63,7 +62,7 @@ rule
63
62
  | /\=(?=begin\b)/ { result arg_state, TOKENS[text], text }
64
63
 
65
64
  ruby22_label? /\"#{SIMPLE_STRING}\":/o process_label
66
- /\"(#{SIMPLE_STRING})\"/o { result :expr_end, :tSTRING, text[1..-2].gsub(ESC) { unescape $1 } }
65
+ /\"(#{SIMPLE_STRING})\"/o process_simple_string
67
66
  /\"/ { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
68
67
 
69
68
  /\@\@?\d/ { rb_compile_error "`#{text}` is not allowed as a variable name" }
@@ -76,7 +75,7 @@ ruby22_label? /\"#{SIMPLE_STRING}\":/o process_label
76
75
  | /\:\:/ process_colon2
77
76
  | /\:/ process_colon1
78
77
 
79
- /->/ { result :expr_endfn, :tLAMBDA, nil }
78
+ /->/ { result EXPR_ENDFN, :tLAMBDA, nil }
80
79
 
81
80
  /[+-]/ process_plus_minus
82
81
 
@@ -97,57 +96,57 @@ ruby22_label? /\"#{SIMPLE_STRING}\":/o process_label
97
96
  was_label? /\'#{SSTRING}\':?/o process_label_or_string
98
97
 
99
98
  : /\|/
100
- | /\|\|\=/ { result :expr_beg, :tOP_ASGN, "||" }
101
- | /\|\|/ { result :expr_beg, :tOROP, "||" }
102
- | /\|\=/ { result :expr_beg, :tOP_ASGN, "|" }
103
- | /\|/ { result :arg_state, :tPIPE, "|" }
99
+ | /\|\|\=/ { result EXPR_BEG, :tOP_ASGN, "||" }
100
+ | /\|\|/ { result EXPR_BEG, :tOROP, "||" }
101
+ | /\|\=/ { result EXPR_BEG, :tOP_ASGN, "|" }
102
+ | /\|/ { state = is_after_operator? ? EXPR_ARG : EXPR_PAR; result state, :tPIPE, "|" }
104
103
 
105
104
  /\{/ process_brace_open
106
105
 
107
106
  : /\*/
108
- | /\*\*=/ { result :expr_beg, :tOP_ASGN, "**" }
107
+ | /\*\*=/ { result EXPR_BEG, :tOP_ASGN, "**" }
109
108
  | /\*\*/ { result(:arg_state, space_vs_beginning(:tDSTAR, :tDSTAR, :tPOW), "**") }
110
- | /\*\=/ { result(:expr_beg, :tOP_ASGN, "*") }
109
+ | /\*\=/ { result(EXPR_BEG, :tOP_ASGN, "*") }
111
110
  | /\*/ { result(:arg_state, space_vs_beginning(:tSTAR, :tSTAR, :tSTAR2), "*") }
112
111
 
113
112
  # TODO: fix result+process_lchevron to set command_start = true
114
113
  : /</
115
114
  | /\<\=\>/ { result :arg_state, :tCMP, "<=>" }
116
115
  | /\<\=/ { result :arg_state, :tLEQ, "<=" }
117
- | /\<\<\=/ { result :expr_beg, :tOP_ASGN, "<<" }
116
+ | /\<\<\=/ { result EXPR_BEG, :tOP_ASGN, "<<" }
118
117
  | /\<\</ process_lchevron
119
118
  | /\</ { result :arg_state, :tLT, "<" }
120
119
 
121
120
  : />/
122
121
  | /\>\=/ { result :arg_state, :tGEQ, ">=" }
123
- | /\>\>=/ { result :expr_beg, :tOP_ASGN, ">>" }
122
+ | /\>\>=/ { result EXPR_BEG, :tOP_ASGN, ">>" }
124
123
  | /\>\>/ { result :arg_state, :tRSHFT, ">>" }
125
124
  | /\>/ { result :arg_state, :tGT, ">" }
126
125
 
127
126
  : /\`/
128
- | expr_fname? /\`/ { result(:expr_end, :tBACK_REF2, "`") }
129
- | expr_dot? /\`/ { result((cmd_state ? :expr_cmdarg : :expr_arg), :tBACK_REF2, "`") }
127
+ | expr_fname? /\`/ { result(EXPR_END, :tBACK_REF2, "`") }
128
+ | expr_dot? /\`/ { result((cmd_state ? EXPR_CMDARG : EXPR_ARG), :tBACK_REF2, "`") }
130
129
  | /\`/ { string STR_XQUOTE, '`'; result(nil, :tXSTRING_BEG, "`") }
131
130
 
132
131
  /\?/ process_questionmark
133
132
 
134
133
  : /&/
135
- | /\&\&\=/ { result(:expr_beg, :tOP_ASGN, "&&") }
136
- | /\&\&/ { result(:expr_beg, :tANDOP, "&&") }
137
- | /\&\=/ { result(:expr_beg, :tOP_ASGN, "&" ) }
138
- | /\&\./ { result(:expr_dot, :tLONELY, "&.") }
134
+ | /\&\&\=/ { result(EXPR_BEG, :tOP_ASGN, "&&") }
135
+ | /\&\&/ { result(EXPR_BEG, :tANDOP, "&&") }
136
+ | /\&\=/ { result(EXPR_BEG, :tOP_ASGN, "&" ) }
137
+ | /\&\./ { result(EXPR_DOT, :tLONELY, "&.") }
139
138
  | /\&/ process_amper
140
139
 
141
140
  /\// process_slash
142
141
 
143
142
  : /\^/
144
- | /\^=/ { result(:expr_beg, :tOP_ASGN, "^") }
143
+ | /\^=/ { result(EXPR_BEG, :tOP_ASGN, "^") }
145
144
  | /\^/ { result(:arg_state, :tCARET, "^") }
146
145
 
147
- /\;/ { self.command_start = true; result(:expr_beg, :tSEMI, ";") }
146
+ /\;/ { self.command_start = true; result(EXPR_BEG, :tSEMI, ";") }
148
147
 
149
148
  : /~/
150
- | in_arg_state? /\~@/ { result(:arg_state, :tTILDE, "~") }
149
+ | is_after_operator? /\~@/ { result(:arg_state, :tTILDE, "~") }
151
150
  | /\~/ { result(:arg_state, :tTILDE, "~") }
152
151
 
153
152
  : /\\/
@@ -165,12 +164,12 @@ was_label? /\'#{SSTRING}\':?/o process_label_or_string
165
164
  | in_fname? /\$([1-9]\d*)/ process_gvar
166
165
  | /\$([1-9]\d*)/ process_nthref
167
166
  | /\$0/ process_gvar
167
+ | /\$#{IDENT_CHAR}+/ process_gvar
168
168
  | /\$\W|\$\z/ process_gvar_oddity
169
- | /\$\w+/ process_gvar
170
169
 
171
170
  /\_/ process_underscore
172
171
 
173
- /#{IDENT}/o process_token
172
+ /#{IDENT_CHAR}+/o process_token
174
173
 
175
174
  /\004|\032|\000|\Z/ { [RubyLexer::EOF, RubyLexer::EOF] }
176
175
 
@@ -1,18 +1,23 @@
1
1
  # encoding: UTF-8
2
2
  #--
3
3
  # This file is automatically generated. Do not modify it.
4
- # Generated by: oedipus_lex version 2.5.0.
4
+ # Generated by: oedipus_lex version 2.5.2.
5
5
  # Source: lib/ruby_lexer.rex
6
6
  #++
7
7
 
8
8
  #
9
9
  # lexical scanner definition for ruby
10
10
 
11
+
12
+ ##
13
+ # The generated lexer RubyLexer
14
+
11
15
  class RubyLexer
12
16
  require 'strscan'
13
17
 
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]))/
18
+ # :stopdoc:
19
+ IDENT_CHAR = /[a-zA-Z0-9_[:^ascii:]]/
20
+ ESC = /\\((?>[0-7]{1,3}|x\h{1,2}|M-[^\\]|(C-|c)[^\\]|u\h{1,4}|u\{\h+(?:\s+\h+)*\}|[^0-7xMCc]))/
16
21
  SIMPLE_STRING = /((#{ESC}|\#(#{ESC}|[^\{\#\@\$\"\\])|[^\"\\\#])*)/o
17
22
  SSTRING = /((\\.|[^\'])*)/
18
23
  INT_DEC = /[+]?(?:(?:[1-9][\d_]*|0)(?!\.\d)(ri|r|i)?\b|0d[0-9_]+)(ri|r|i)?/i
@@ -24,30 +29,56 @@ class RubyLexer
24
29
  NUM_BAD = /[+]?0[xbd]\b/i
25
30
  INT_OCT_BAD = /[+]?0o?[0-7_]*[89]/i
26
31
  FLOAT_BAD = /[+]?\d[\d_]*_(e|\.)/i
27
-
32
+ # :startdoc:
33
+ # :stopdoc:
28
34
  class LexerError < StandardError ; end
29
35
  class ScanError < LexerError ; end
36
+ # :startdoc:
37
+
38
+ ##
39
+ # The file name / path
30
40
 
31
41
  attr_accessor :filename
42
+
43
+ ##
44
+ # The StringScanner for this lexer.
45
+
32
46
  attr_accessor :ss
47
+
48
+ ##
49
+ # The current lexical state.
50
+
33
51
  attr_accessor :state
34
52
 
35
53
  alias :match :ss
36
54
 
55
+ ##
56
+ # The match groups for the current scan.
57
+
37
58
  def matches
38
59
  m = (1..9).map { |i| ss[i] }
39
60
  m.pop until m[-1] or m.empty?
40
61
  m
41
62
  end
42
63
 
64
+ ##
65
+ # Yields on the current action.
66
+
43
67
  def action
44
68
  yield
45
69
  end
46
70
 
71
+
72
+ ##
73
+ # The current scanner class. Must be overridden in subclasses.
74
+
47
75
  def scanner_class
48
76
  StringScanner
49
77
  end unless instance_methods(false).map(&:to_s).include?("scanner_class")
50
78
 
79
+ ##
80
+ # Parse the given string.
81
+
51
82
  def parse str
52
83
  self.ss = scanner_class.new str
53
84
  self.state ||= nil
@@ -55,6 +86,9 @@ class RubyLexer
55
86
  do_parse
56
87
  end
57
88
 
89
+ ##
90
+ # Read in and parse the file at +path+.
91
+
58
92
  def parse_file path
59
93
  self.filename = path
60
94
  open path do |f|
@@ -62,12 +96,18 @@ class RubyLexer
62
96
  end
63
97
  end
64
98
 
99
+ ##
100
+ # The current location in the parse.
101
+
65
102
  def location
66
103
  [
67
104
  (filename || "<input>"),
68
105
  ].compact.join(":")
69
106
  end
70
107
 
108
+ ##
109
+ # Lex the next token.
110
+
71
111
  def next_token
72
112
  return process_string if lex_strterm
73
113
  self.cmd_state = self.command_start
@@ -90,24 +130,24 @@ class RubyLexer
90
130
  process_brace_close text
91
131
  when ss.match?(/\!/) then
92
132
  case
93
- when in_arg_state? && (ss.skip(/\!\@/)) then
94
- action { result :expr_arg, :tUBANG, "!@" }
133
+ when is_after_operator? && (ss.skip(/\!\@/)) then
134
+ action { result EXPR_ARG, :tUBANG, "!@" }
95
135
  when text = ss.scan(/\![=~]?/) then
96
136
  action { result :arg_state, TOKENS[text], text }
97
137
  end # group /\!/
98
138
  when ss.match?(/\./) then
99
139
  case
100
140
  when text = ss.scan(/\.\.\.?/) then
101
- action { result :expr_beg, TOKENS[text], text }
141
+ action { result EXPR_BEG, TOKENS[text], text }
102
142
  when ss.skip(/\.\d/) then
103
143
  action { rb_compile_error "no .<digit> floating literal anymore put 0 before dot" }
104
144
  when ss.skip(/\./) then
105
- action { self.lex_state = :expr_beg; result :expr_dot, :tDOT, "." }
145
+ action { self.lex_state = EXPR_BEG; result EXPR_DOT, :tDOT, "." }
106
146
  end # group /\./
107
147
  when text = ss.scan(/\(/) then
108
148
  process_paren text
109
149
  when text = ss.scan(/\,/) then
110
- action { result :expr_beg, TOKENS[text], text }
150
+ action { result EXPR_PAR, TOKENS[text], text }
111
151
  when ss.match?(/=/) then
112
152
  case
113
153
  when text = ss.scan(/\=\=\=|\=\=|\=~|\=>|\=(?!begin\b)/) then
@@ -120,7 +160,7 @@ class RubyLexer
120
160
  when ruby22_label? && (text = ss.scan(/\"#{SIMPLE_STRING}\":/o)) then
121
161
  process_label text
122
162
  when text = ss.scan(/\"(#{SIMPLE_STRING})\"/o) then
123
- action { result :expr_end, :tSTRING, text[1..-2].gsub(ESC) { unescape $1 } }
163
+ process_simple_string text
124
164
  when text = ss.scan(/\"/) then
125
165
  action { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
126
166
  when text = ss.scan(/\@\@?\d/) then
@@ -141,7 +181,7 @@ class RubyLexer
141
181
  process_colon1 text
142
182
  end # group /:/
143
183
  when ss.skip(/->/) then
144
- action { result :expr_endfn, :tLAMBDA, nil }
184
+ action { result EXPR_ENDFN, :tLAMBDA, nil }
145
185
  when text = ss.scan(/[+-]/) then
146
186
  process_plus_minus text
147
187
  when ss.match?(/[+\d]/) then
@@ -174,24 +214,24 @@ class RubyLexer
174
214
  when ss.match?(/\|/) then
175
215
  case
176
216
  when ss.skip(/\|\|\=/) then
177
- action { result :expr_beg, :tOP_ASGN, "||" }
217
+ action { result EXPR_BEG, :tOP_ASGN, "||" }
178
218
  when ss.skip(/\|\|/) then
179
- action { result :expr_beg, :tOROP, "||" }
219
+ action { result EXPR_BEG, :tOROP, "||" }
180
220
  when ss.skip(/\|\=/) then
181
- action { result :expr_beg, :tOP_ASGN, "|" }
221
+ action { result EXPR_BEG, :tOP_ASGN, "|" }
182
222
  when ss.skip(/\|/) then
183
- action { result :arg_state, :tPIPE, "|" }
223
+ action { state = is_after_operator? ? EXPR_ARG : EXPR_PAR; result state, :tPIPE, "|" }
184
224
  end # group /\|/
185
225
  when text = ss.scan(/\{/) then
186
226
  process_brace_open text
187
227
  when ss.match?(/\*/) then
188
228
  case
189
229
  when ss.skip(/\*\*=/) then
190
- action { result :expr_beg, :tOP_ASGN, "**" }
230
+ action { result EXPR_BEG, :tOP_ASGN, "**" }
191
231
  when ss.skip(/\*\*/) then
192
232
  action { result(:arg_state, space_vs_beginning(:tDSTAR, :tDSTAR, :tPOW), "**") }
193
233
  when ss.skip(/\*\=/) then
194
- action { result(:expr_beg, :tOP_ASGN, "*") }
234
+ action { result(EXPR_BEG, :tOP_ASGN, "*") }
195
235
  when ss.skip(/\*/) then
196
236
  action { result(:arg_state, space_vs_beginning(:tSTAR, :tSTAR, :tSTAR2), "*") }
197
237
  end # group /\*/
@@ -202,7 +242,7 @@ class RubyLexer
202
242
  when ss.skip(/\<\=/) then
203
243
  action { result :arg_state, :tLEQ, "<=" }
204
244
  when ss.skip(/\<\<\=/) then
205
- action { result :expr_beg, :tOP_ASGN, "<<" }
245
+ action { result EXPR_BEG, :tOP_ASGN, "<<" }
206
246
  when text = ss.scan(/\<\</) then
207
247
  process_lchevron text
208
248
  when ss.skip(/\</) then
@@ -213,7 +253,7 @@ class RubyLexer
213
253
  when ss.skip(/\>\=/) then
214
254
  action { result :arg_state, :tGEQ, ">=" }
215
255
  when ss.skip(/\>\>=/) then
216
- action { result :expr_beg, :tOP_ASGN, ">>" }
256
+ action { result EXPR_BEG, :tOP_ASGN, ">>" }
217
257
  when ss.skip(/\>\>/) then
218
258
  action { result :arg_state, :tRSHFT, ">>" }
219
259
  when ss.skip(/\>/) then
@@ -222,9 +262,9 @@ class RubyLexer
222
262
  when ss.match?(/\`/) then
223
263
  case
224
264
  when expr_fname? && (ss.skip(/\`/)) then
225
- action { result(:expr_end, :tBACK_REF2, "`") }
265
+ action { result(EXPR_END, :tBACK_REF2, "`") }
226
266
  when expr_dot? && (ss.skip(/\`/)) then
227
- action { result((cmd_state ? :expr_cmdarg : :expr_arg), :tBACK_REF2, "`") }
267
+ action { result((cmd_state ? EXPR_CMDARG : EXPR_ARG), :tBACK_REF2, "`") }
228
268
  when ss.skip(/\`/) then
229
269
  action { string STR_XQUOTE, '`'; result(nil, :tXSTRING_BEG, "`") }
230
270
  end # group /\`/
@@ -233,13 +273,13 @@ class RubyLexer
233
273
  when ss.match?(/&/) then
234
274
  case
235
275
  when ss.skip(/\&\&\=/) then
236
- action { result(:expr_beg, :tOP_ASGN, "&&") }
276
+ action { result(EXPR_BEG, :tOP_ASGN, "&&") }
237
277
  when ss.skip(/\&\&/) then
238
- action { result(:expr_beg, :tANDOP, "&&") }
278
+ action { result(EXPR_BEG, :tANDOP, "&&") }
239
279
  when ss.skip(/\&\=/) then
240
- action { result(:expr_beg, :tOP_ASGN, "&" ) }
280
+ action { result(EXPR_BEG, :tOP_ASGN, "&" ) }
241
281
  when ss.skip(/\&\./) then
242
- action { result(:expr_dot, :tLONELY, "&.") }
282
+ action { result(EXPR_DOT, :tLONELY, "&.") }
243
283
  when text = ss.scan(/\&/) then
244
284
  process_amper text
245
285
  end # group /&/
@@ -248,15 +288,15 @@ class RubyLexer
248
288
  when ss.match?(/\^/) then
249
289
  case
250
290
  when ss.skip(/\^=/) then
251
- action { result(:expr_beg, :tOP_ASGN, "^") }
291
+ action { result(EXPR_BEG, :tOP_ASGN, "^") }
252
292
  when ss.skip(/\^/) then
253
293
  action { result(:arg_state, :tCARET, "^") }
254
294
  end # group /\^/
255
295
  when ss.skip(/\;/) then
256
- action { self.command_start = true; result(:expr_beg, :tSEMI, ";") }
296
+ action { self.command_start = true; result(EXPR_BEG, :tSEMI, ";") }
257
297
  when ss.match?(/~/) then
258
298
  case
259
- when in_arg_state? && (ss.skip(/\~@/)) then
299
+ when is_after_operator? && (ss.skip(/\~@/)) then
260
300
  action { result(:arg_state, :tTILDE, "~") }
261
301
  when ss.skip(/\~/) then
262
302
  action { result(:arg_state, :tTILDE, "~") }
@@ -288,14 +328,14 @@ class RubyLexer
288
328
  process_nthref text
289
329
  when text = ss.scan(/\$0/) then
290
330
  process_gvar text
331
+ when text = ss.scan(/\$#{IDENT_CHAR}+/) then
332
+ process_gvar text
291
333
  when text = ss.scan(/\$\W|\$\z/) then
292
334
  process_gvar_oddity text
293
- when text = ss.scan(/\$\w+/) then
294
- process_gvar text
295
335
  end # group /\$/
296
336
  when text = ss.scan(/\_/) then
297
337
  process_underscore text
298
- when text = ss.scan(/#{IDENT}/o) then
338
+ when text = ss.scan(/#{IDENT_CHAR}+/o) then
299
339
  process_token text
300
340
  when ss.skip(/\004|\032|\000|\Z/) then
301
341
  action { [RubyLexer::EOF, RubyLexer::EOF] }
@@ -9,28 +9,29 @@ class RubyParser
9
9
 
10
10
  VERSIONS = []
11
11
 
12
- class Parser < Racc::Parser
13
- include RubyParserStuff
12
+ attr_accessor :current
14
13
 
15
- def self.inherited x
16
- RubyParser::VERSIONS << x
17
- end
18
-
19
- def self.version= v
20
- @version = v
21
- end
14
+ def self.for_current_ruby
15
+ name = "V#{RUBY_VERSION[/^\d+\.\d+/].delete "."}"
16
+ klass = if const_defined? name then
17
+ const_get name
18
+ else
19
+ latest = VERSIONS.first
20
+ warn "NOTE: RubyParser::#{name} undefined, using #{latest}."
21
+ latest
22
+ end
22
23
 
23
- def self.version
24
- @version ||= Parser > self && self.name[/(?:V|Ruby)(\d+)/, 1].to_i
25
- end
24
+ klass.new
26
25
  end
27
26
 
28
- class SyntaxError < RuntimeError; end
27
+ def self.latest
28
+ VERSIONS.first.new
29
+ end
29
30
 
30
31
  def process s, f = "(string)", t = 10
31
32
  e = nil
32
33
  VERSIONS.each do |klass|
33
- parser = klass.new
34
+ self.current = parser = klass.new
34
35
  begin
35
36
  return parser.process s, f, t
36
37
  rescue Racc::ParseError, RubyParser::SyntaxError => exc
@@ -46,22 +47,23 @@ class RubyParser
46
47
  # do nothing
47
48
  end
48
49
 
49
- def self.latest
50
- VERSIONS.first.new
51
- end
50
+ class Parser < Racc::Parser
51
+ include RubyParserStuff
52
52
 
53
- def self.for_current_ruby
54
- name = "V#{RUBY_VERSION[/^\d+\.\d+/].delete "."}"
55
- klass = if const_defined? name then
56
- const_get name
57
- else
58
- latest = VERSIONS.first
59
- warn "NOTE: RubyParser::#{name} undefined, using #{latest}."
60
- latest
61
- end
53
+ def self.inherited x
54
+ RubyParser::VERSIONS << x
55
+ end
62
56
 
63
- klass.new
57
+ def self.version= v
58
+ @version = v
59
+ end
60
+
61
+ def self.version
62
+ @version ||= Parser > self && self.name[/(?:V|Ruby)(\d+)/, 1].to_i
63
+ end
64
64
  end
65
+
66
+ class SyntaxError < RuntimeError; end
65
67
  end
66
68
 
67
69
  ##
@@ -76,10 +78,12 @@ require "ruby23_parser"
76
78
  require "ruby24_parser"
77
79
  require "ruby25_parser"
78
80
  require "ruby26_parser"
81
+ require "ruby27_parser"
79
82
 
80
83
  class RubyParser # HACK
81
84
  VERSIONS.clear # also a HACK caused by racc namespace issues
82
85
 
86
+ class V27 < ::Ruby27Parser; end
83
87
  class V26 < ::Ruby26Parser; end
84
88
  class V25 < ::Ruby25Parser; end
85
89
  class V24 < ::Ruby24Parser; end