parser 0.9.alpha1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -3
  3. data/AST_FORMAT.md +1338 -0
  4. data/README.md +58 -3
  5. data/Rakefile +32 -12
  6. data/bin/benchmark +47 -0
  7. data/bin/explain-parse +14 -0
  8. data/bin/parse +6 -0
  9. data/lib/parser.rb +84 -0
  10. data/lib/parser/all.rb +2 -0
  11. data/lib/parser/ast/node.rb +11 -0
  12. data/lib/parser/ast/processor.rb +8 -0
  13. data/lib/parser/base.rb +116 -0
  14. data/lib/parser/builders/default.rb +654 -0
  15. data/lib/parser/compatibility/ruby1_8.rb +13 -0
  16. data/lib/parser/diagnostic.rb +44 -0
  17. data/lib/parser/diagnostic/engine.rb +44 -0
  18. data/lib/parser/lexer.rl +335 -245
  19. data/lib/parser/lexer/explanation.rb +37 -0
  20. data/lib/parser/{lexer_literal.rb → lexer/literal.rb} +22 -12
  21. data/lib/parser/lexer/stack_state.rb +38 -0
  22. data/lib/parser/ruby18.y +1957 -0
  23. data/lib/parser/ruby19.y +2154 -0
  24. data/lib/parser/source/buffer.rb +78 -0
  25. data/lib/parser/source/map.rb +20 -0
  26. data/lib/parser/source/map/operator.rb +15 -0
  27. data/lib/parser/source/map/variable_assignment.rb +15 -0
  28. data/lib/parser/source/range.rb +66 -0
  29. data/lib/parser/static_environment.rb +12 -6
  30. data/parser.gemspec +23 -13
  31. data/test/helper.rb +45 -0
  32. data/test/parse_helper.rb +204 -0
  33. data/test/racc_coverage_helper.rb +130 -0
  34. data/test/test_diagnostic.rb +47 -0
  35. data/test/test_diagnostic_engine.rb +58 -0
  36. data/test/test_lexer.rb +601 -357
  37. data/test/test_lexer_stack_state.rb +69 -0
  38. data/test/test_parse_helper.rb +74 -0
  39. data/test/test_parser.rb +3654 -0
  40. data/test/test_source_buffer.rb +80 -0
  41. data/test/test_source_range.rb +51 -0
  42. data/test/test_static_environment.rb +1 -4
  43. metadata +137 -12
@@ -0,0 +1,37 @@
1
+ module Parser
2
+
3
+ module Lexer::Explanation
4
+
5
+ # Like #advance, but also pretty-print the token and its position
6
+ # in the stream to `stdout`.
7
+ def advance_and_explain
8
+ type, (val, range) = advance
9
+
10
+ puts decorate(range,
11
+ "\e[0;32m#{type} #{val.inspect}\e[0m",
12
+ "#{state.to_s.ljust(10)} #{@cond} #{@cmdarg}\e[0m")
13
+
14
+ [ type, [val, range] ]
15
+ end
16
+
17
+ private
18
+
19
+ def decorate(range, token, info)
20
+ from, to = range.begin_column, range.end_column
21
+
22
+ line = range.source_line
23
+ line[from..to] = "\e[4m#{line[from..to]}\e[0m"
24
+
25
+ tail_len = to - from
26
+ tail = "~" * (tail_len >= 0 ? tail_len : 0)
27
+ decoration = "#{" " * from}\e[1;31m^#{tail}\e[0m #{token} ".
28
+ ljust(70) + info
29
+
30
+ [ line, decoration ]
31
+ end
32
+
33
+ end
34
+
35
+ Lexer.send :include, Lexer::Explanation
36
+
37
+ end
@@ -1,6 +1,6 @@
1
1
  module Parser
2
2
 
3
- class LexerLiteral
3
+ class Lexer::Literal
4
4
  DELIMITERS = { '(' => ')', '[' => ']', '{' => '}', '<' => '>' }
5
5
  MONOLITHIC = { :tSTRING_BEG => :tSTRING, :tSYMBEG => :tSYMBOL }
6
6
 
@@ -26,15 +26,16 @@ module Parser
26
26
  '`' => [ :tXSTRING_BEG, true ],
27
27
  }
28
28
 
29
- attr_reader :heredoc_e
29
+ attr_reader :heredoc_e, :str_s
30
30
  attr_accessor :saved_herebody_s
31
31
 
32
32
  def initialize(lexer, str_type, delimiter, str_s, heredoc_e = nil, indent = false)
33
33
  @lexer = lexer
34
34
  @nesting = 1
35
35
 
36
- unless TYPES.include? str_type
37
- lexer.send :error, "#{str_type}: unknown type of %string"
36
+ unless TYPES.include?(str_type)
37
+ message = ERRORS[:unexpected_percent_str] % { :type => str_type }
38
+ lexer.send(:diagnostic, :error, message, @lexer.send(:range, str_s, str_s + 2))
38
39
  end
39
40
 
40
41
  # String type. For :'foo', it is :'
@@ -43,7 +44,7 @@ module Parser
43
44
  @str_s = str_s
44
45
 
45
46
  # Data buffer.
46
- @buffer = ""
47
+ @buffer = ''
47
48
  # Start of the current chunk in data buffer.
48
49
  @buffer_s = nil
49
50
 
@@ -63,6 +64,11 @@ module Parser
63
64
  !heredoc?
64
65
  )
65
66
 
67
+ # Also capture delimiter in %w() style literals
68
+ unless @heredoc_e || @str_type.end_with?(delimiter)
69
+ @str_type << delimiter
70
+ end
71
+
66
72
  emit_start_tok unless @monolithic
67
73
  end
68
74
 
@@ -90,7 +96,7 @@ module Parser
90
96
  if words? && character =~ /[ \t\v\r\f\n]/
91
97
  true
92
98
  else
93
- ['\\', @start_delim, @end_delim].include? character
99
+ ['\\', @start_delim, @end_delim].include?(character)
94
100
  end
95
101
  end
96
102
 
@@ -113,14 +119,14 @@ module Parser
113
119
  if @nesting == 0
114
120
  # Emit the string as a single token if it's applicable.
115
121
  if @monolithic
116
- @lexer.emit MONOLITHIC[@start_tok], @buffer, @str_s, te
122
+ emit(MONOLITHIC[@start_tok], @buffer, @str_s, te)
117
123
  else
118
124
  # If this is a heredoc, @buffer contains the sentinel now.
119
125
  # Just throw it out. Lexer flushes the heredoc after each
120
126
  # non-heredoc-terminating \n anyway, so no data will be lost.
121
127
  flush_string unless heredoc?
122
128
 
123
- @lexer.emit :tSTRING_END, @end_delim, ts, te
129
+ emit(:tSTRING_END, @end_delim, ts, te)
124
130
  end
125
131
  end
126
132
  end
@@ -152,13 +158,13 @@ module Parser
152
158
  end
153
159
 
154
160
  unless @buffer.empty?
155
- @lexer.emit :tSTRING_CONTENT, @buffer, @buffer_s, @buffer_e
161
+ emit(:tSTRING_CONTENT, @buffer, @buffer_s, @buffer_e)
156
162
 
157
163
  if words?
158
- @lexer.emit :tSPACE, nil, @buffer_e, @buffer_e + 1
164
+ emit(:tSPACE, nil, @buffer_e, @buffer_e + 1)
159
165
  end
160
166
 
161
- @buffer = ""
167
+ @buffer = ''
162
168
  @buffer_s = nil
163
169
  @buffer_e = nil
164
170
  end
@@ -168,7 +174,11 @@ module Parser
168
174
 
169
175
  def emit_start_tok
170
176
  str_e = @heredoc_e || @str_s + @str_type.length
171
- @lexer.emit @start_tok, @str_type, @str_s, str_e
177
+ emit(@start_tok, @str_type, @str_s, str_e)
178
+ end
179
+
180
+ def emit(token, type, s, e)
181
+ @lexer.send(:emit, token, type, s, e)
172
182
  end
173
183
  end
174
184
 
@@ -0,0 +1,38 @@
1
+ module Parser
2
+
3
+ class Lexer::StackState
4
+ def initialize(name)
5
+ @name = name.freeze
6
+ @stack = 0
7
+ end
8
+
9
+ def push(bit)
10
+ bit_value = bit ? 1 : 0
11
+ @stack = (@stack << 1) | bit_value
12
+
13
+ bit
14
+ end
15
+
16
+ def pop
17
+ bit_value = @stack & 1
18
+ @stack >>= 1
19
+
20
+ bit_value == 1
21
+ end
22
+
23
+ def lexpop
24
+ push(pop || pop)
25
+ end
26
+
27
+ def active?
28
+ @stack[0] == 1
29
+ end
30
+
31
+ def to_s
32
+ "[#{@stack.to_s(2)} <= #{@name}]"
33
+ end
34
+
35
+ alias inspect to_s
36
+ end
37
+
38
+ end
@@ -0,0 +1,1957 @@
1
+ class Parser::Ruby18
2
+
3
+ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
4
+ kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
5
+ kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kRETURN kYIELD kSUPER
6
+ kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
7
+ kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
8
+ k__FILE__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tNTH_REF
9
+ tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT tREGEXP_END tUPLUS
10
+ tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ tGEQ tLEQ tANDOP
11
+ tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF tASET tLSHFT tRSHFT
12
+ tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN tLPAREN2 tRPAREN tLPAREN_ARG
13
+ tLBRACK tLBRACK2 tRBRACK tLBRACE tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2
14
+ tTILDE tPERCENT tDIVIDE tPLUS tMINUS tLT tGT tPIPE tBANG tCARET
15
+ tLCURLY tRCURLY tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
16
+ tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END tSTRING
17
+ tSYMBOL tREGEXP_OPT tNL tEH tCOLON tCOMMA tSPACE tSEMI
18
+
19
+ prechigh
20
+ right tBANG tTILDE tUPLUS
21
+ right tPOW
22
+ right tUMINUS_NUM tUMINUS
23
+ left tSTAR2 tDIVIDE tPERCENT
24
+ left tPLUS tMINUS
25
+ left tLSHFT tRSHFT
26
+ left tAMPER2
27
+ left tPIPE tCARET
28
+ left tGT tGEQ tLT tLEQ
29
+ nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
30
+ left tANDOP
31
+ left tOROP
32
+ nonassoc tDOT2 tDOT3
33
+ right tEH tCOLON
34
+ left kRESCUE_MOD
35
+ right tEQL tOP_ASGN
36
+ nonassoc kDEFINED
37
+ right kNOT
38
+ left kOR kAND
39
+ nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
40
+ nonassoc tLBRACE_ARG
41
+ nonassoc tLOWEST
42
+ preclow
43
+
44
+ rule
45
+
46
+ program: compstmt
47
+ {
48
+ result = val[0]
49
+ }
50
+
51
+ bodystmt: compstmt opt_rescue opt_else opt_ensure
52
+ {
53
+ rescue_bodies = val[1]
54
+ else_, t_else = val[2]
55
+ ensure_, t_ensure = val[3]
56
+
57
+ if rescue_bodies.empty? && !else_.nil?
58
+ diagnostic :warning, :useless_else, t_else
59
+ end
60
+
61
+ result = @builder.begin_body(val[0],
62
+ rescue_bodies,
63
+ else_, t_else,
64
+ ensure_, t_ensure)
65
+ }
66
+
67
+ compstmt: stmts opt_terms
68
+ {
69
+ result = @builder.compstmt(val[0])
70
+ }
71
+
72
+ stmts: none
73
+ {
74
+ result = []
75
+ }
76
+ | stmt
77
+ {
78
+ result = [ val[0] ]
79
+ }
80
+ | error stmt
81
+ {
82
+ result = [ val[1] ]
83
+ }
84
+ | stmts terms stmt
85
+ {
86
+ result = val[0] << val[2]
87
+ }
88
+
89
+ stmt: kALIAS fitem
90
+ {
91
+ @lexer.state = :expr_fname
92
+ }
93
+ fitem
94
+ {
95
+ result = @builder.alias(val[0], val[1], val[3])
96
+ }
97
+ | kALIAS tGVAR tGVAR
98
+ {
99
+ result = @builder.alias(val[0],
100
+ @builder.gvar(val[1]),
101
+ @builder.gvar(val[2]))
102
+ }
103
+ | kALIAS tGVAR tBACK_REF
104
+ {
105
+ result = @builder.alias(val[0],
106
+ @builder.gvar(val[1]),
107
+ @builder.back_ref(val[2]))
108
+ }
109
+ | kALIAS tGVAR tNTH_REF
110
+ {
111
+ diagnostic(:error, :nth_ref_alias, val[2])
112
+ }
113
+ | kUNDEF undef_list
114
+ {
115
+ result = @builder.undef_method(val[0], val[1])
116
+ }
117
+ | stmt kIF_MOD expr_value
118
+ {
119
+ result = @builder.condition_mod(val[0], nil,
120
+ val[1], val[2])
121
+ }
122
+ | stmt kUNLESS_MOD expr_value
123
+ {
124
+ result = @builder.condition_mod(nil, val[0],
125
+ val[1], val[2])
126
+ }
127
+ | stmt kWHILE_MOD expr_value
128
+ {
129
+ result = @builder.loop_mod(val[0], val[1], val[2])
130
+ }
131
+ | stmt kUNTIL_MOD expr_value
132
+ {
133
+ result = @builder.loop_mod(val[0], val[1], val[2])
134
+ }
135
+ | stmt kRESCUE_MOD stmt
136
+ {
137
+ rescue_body = @builder.rescue_body(val[1],
138
+ nil, nil, nil,
139
+ nil, val[2])
140
+
141
+ result = @builder.begin_body(val[0], [ rescue_body ])
142
+ }
143
+ | klBEGIN
144
+ {
145
+ if in_def?
146
+ diagnostic(:error, :begin_in_method, val[0])
147
+ end
148
+
149
+ @static_env.extend_static
150
+ }
151
+ tLCURLY compstmt tRCURLY
152
+ {
153
+ @static_env.unextend
154
+
155
+ result = @builder.preexe(val[0], val[2], val[3], val[4])
156
+ }
157
+ | klEND tLCURLY compstmt tRCURLY
158
+ {
159
+ if in_def?
160
+ diagnostic(:warning, :end_in_method, val[0])
161
+ end
162
+
163
+ result = @builder.postexe(val[0], val[1], val[2], val[3])
164
+ }
165
+ | lhs tEQL command_call
166
+ {
167
+ result = @builder.assign(val[0], val[1], val[2])
168
+ }
169
+ | mlhs tEQL command_call
170
+ {
171
+ result = @builder.multi_assign(val[0], val[1], val[2])
172
+ }
173
+ | var_lhs tOP_ASGN command_call
174
+ {
175
+ result = @builder.op_assign(val[0], val[1], val[2])
176
+ }
177
+ | primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN command_call
178
+ {
179
+ result = @builder.op_assign(
180
+ @builder.index(
181
+ val[0], val[1], val[2], val[3]),
182
+ val[4], val[5])
183
+ }
184
+ | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
185
+ {
186
+ result = @builder.op_assign(
187
+ @builder.call_method(
188
+ val[0], val[1], val[2]),
189
+ val[3], val[4])
190
+ }
191
+ | primary_value tDOT tCONSTANT tOP_ASGN command_call
192
+ {
193
+ result = @builder.op_assign(
194
+ @builder.call_method(
195
+ val[0], val[1], val[2]),
196
+ val[3], val[4])
197
+ }
198
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
199
+ {
200
+ result = @builder.op_assign(
201
+ @builder.call_method(
202
+ val[0], val[1], val[2]),
203
+ val[3], val[4])
204
+ }
205
+ | backref tOP_ASGN command_call
206
+ {
207
+ @builder.op_assign(val[0], val[1], val[2])
208
+ }
209
+ | lhs tEQL mrhs
210
+ {
211
+ result = @builder.assign(val[0], val[1],
212
+ @builder.array(nil, val[2], nil))
213
+ }
214
+ | mlhs tEQL arg_value
215
+ {
216
+ result = @builder.multi_assign(val[0], val[1], val[2])
217
+ }
218
+ | mlhs tEQL mrhs
219
+ {
220
+ result = @builder.multi_assign(val[0], val[1],
221
+ @builder.array(nil, val[2], nil))
222
+ }
223
+ | expr
224
+
225
+ expr: command_call
226
+ | expr kAND expr
227
+ {
228
+ result = @builder.logical_op(:and, val[0], val[1], val[2])
229
+ }
230
+ | expr kOR expr
231
+ {
232
+ result = @builder.logical_op(:or, val[0], val[1], val[2])
233
+ }
234
+ | kNOT expr
235
+ {
236
+ result = @builder.not_op(val[0], val[1])
237
+ }
238
+ | tBANG command_call
239
+ {
240
+ result = @builder.not_op(val[0], val[1])
241
+ }
242
+ | arg
243
+
244
+ expr_value: expr
245
+ {
246
+ result = value_expr(val[0])
247
+ }
248
+
249
+ command_call: command
250
+ | block_command
251
+ | kRETURN call_args
252
+ {
253
+ result = @builder.keyword_cmd(:return, val[0],
254
+ nil, val[1], nil)
255
+ }
256
+ | kBREAK call_args
257
+ {
258
+ result = @builder.keyword_cmd(:break, val[0],
259
+ nil, val[1], nil)
260
+ }
261
+ | kNEXT call_args
262
+ {
263
+ result = @builder.keyword_cmd(:next, val[0],
264
+ nil, val[1], nil)
265
+ }
266
+
267
+ block_command: block_call
268
+ | block_call tDOT operation2 command_args
269
+ {
270
+ lparen_t, args, rparen_t = val[3]
271
+ result = @builder.call_method(val[0], val[1], val[2],
272
+ lparen_t, args, rparen_t)
273
+ }
274
+ | block_call tCOLON2 operation2 command_args
275
+ {
276
+ lparen_t, args, rparen_t = val[3]
277
+ result = @builder.call_method(val[0], val[1], val[2],
278
+ lparen_t, args, rparen_t)
279
+ }
280
+
281
+ cmd_brace_block: tLBRACE_ARG
282
+ {
283
+ @static_env.extend_dynamic
284
+ }
285
+ opt_block_var compstmt tRCURLY
286
+ {
287
+ result = [ val[0], val[2], val[3], val[4] ]
288
+
289
+ @static_env.unextend
290
+ }
291
+
292
+ command: operation command_args =tLOWEST
293
+ {
294
+ lparen_t, args, rparen_t = val[1]
295
+ result = @builder.call_method(nil, nil, val[0],
296
+ lparen_t, args, rparen_t)
297
+ }
298
+ | operation command_args cmd_brace_block
299
+ {
300
+ lparen_t, args, rparen_t = val[1]
301
+ method_call = @builder.call_method(nil, nil, val[0],
302
+ lparen_t, args, rparen_t)
303
+
304
+ begin_t, block_args, body, end_t = val[2]
305
+ result = @builder.block(method_call,
306
+ begin_t, block_args, body, end_t)
307
+ }
308
+ | primary_value tDOT operation2 command_args =tLOWEST
309
+ {
310
+ lparen_t, args, rparen_t = val[3]
311
+ result = @builder.call_method(val[0], val[1], val[2],
312
+ lparen_t, args, rparen_t)
313
+
314
+ }
315
+ | primary_value tDOT operation2 command_args cmd_brace_block
316
+ {
317
+ lparen_t, args, rparen_t = val[3]
318
+ method_call = @builder.call_method(val[0], val[1], val[2],
319
+ lparen_t, args, rparen_t)
320
+
321
+ begin_t, block_args, body, end_t = val[4]
322
+ result = @builder.block(method_call,
323
+ begin_t, block_args, body, end_t)
324
+ }
325
+ | primary_value tCOLON2 operation2 command_args =tLOWEST
326
+ {
327
+ lparen_t, args, rparen_t = val[3]
328
+ result = @builder.call_method(val[0], val[1], val[2],
329
+ lparen_t, args, rparen_t)
330
+ }
331
+ | primary_value tCOLON2 operation2 command_args cmd_brace_block
332
+ {
333
+ lparen_t, args, rparen_t = val[3]
334
+ method_call = @builder.call_method(val[0], val[1], val[2],
335
+ lparen_t, args, rparen_t)
336
+
337
+ begin_t, block_args, body, end_t = val[4]
338
+ result = @builder.block(method_call,
339
+ begin_t, block_args, body, end_t)
340
+ }
341
+ | kSUPER command_args
342
+ {
343
+ lparen_t, args, rparen_t = val[1]
344
+ result = @builder.keyword_cmd(:super, val[0],
345
+ lparen_t, args, rparen_t)
346
+ }
347
+ | kYIELD command_args
348
+ {
349
+ lparen_t, args, rparen_t = val[1]
350
+ result = @builder.keyword_cmd(:yield, val[0],
351
+ lparen_t, args, rparen_t)
352
+ }
353
+
354
+ mlhs: mlhs_basic
355
+ {
356
+ result = @builder.multi_lhs(nil, val[0], nil)
357
+ }
358
+ | tLPAREN mlhs_entry tRPAREN
359
+ {
360
+ result = @builder.parenthesize(val[0], val[1], val[2])
361
+ }
362
+
363
+ mlhs_entry: mlhs_basic
364
+ {
365
+ result = @builder.multi_lhs(nil, val[0], nil)
366
+ }
367
+ | tLPAREN mlhs_entry tRPAREN
368
+ {
369
+ result = @builder.multi_lhs(val[0], val[1], val[2])
370
+ }
371
+
372
+ mlhs_basic: mlhs_head
373
+ {
374
+ result = val[0]
375
+ }
376
+ | mlhs_head mlhs_item
377
+ {
378
+ result = val[0] << val[1]
379
+ }
380
+ | mlhs_head tSTAR mlhs_node
381
+ {
382
+ result = val[0] << @builder.splat(val[1], val[2])
383
+ }
384
+ | mlhs_head tSTAR
385
+ {
386
+ result = val[0] << @builder.splat(val[1])
387
+ }
388
+ | tSTAR mlhs_node
389
+ {
390
+ result = [ @builder.splat(val[0], val[1]) ]
391
+ }
392
+ | tSTAR
393
+ {
394
+ result = [ @builder.splat(val[0]) ]
395
+ }
396
+
397
+ mlhs_item: mlhs_node
398
+ | tLPAREN mlhs_entry tRPAREN
399
+ {
400
+ result = @builder.parenthesize(val[0], val[1], val[2])
401
+ }
402
+
403
+ mlhs_head: mlhs_item tCOMMA
404
+ {
405
+ result = [ val[0] ]
406
+ }
407
+ | mlhs_head mlhs_item tCOMMA
408
+ {
409
+ result = val[0] << val[1]
410
+ }
411
+
412
+ mlhs_node: variable
413
+ {
414
+ result = @builder.assignable(val[0])
415
+ }
416
+ | primary_value tLBRACK2 aref_args tRBRACK
417
+ {
418
+ result = @builder.index_asgn(val[0], val[1], val[2], val[3])
419
+ }
420
+ | primary_value tDOT tIDENTIFIER
421
+ {
422
+ result = @builder.attr_asgn(val[0], val[1], val[2])
423
+ }
424
+ | primary_value tCOLON2 tIDENTIFIER
425
+ {
426
+ result = @builder.attr_asgn(val[0], val[1], val[2])
427
+ }
428
+ | primary_value tDOT tCONSTANT
429
+ {
430
+ result = @builder.attr_asgn(val[0], val[1], val[2])
431
+ }
432
+ | primary_value tCOLON2 tCONSTANT
433
+ {
434
+ if in_def?
435
+ diagnostic(:error, :dynamic_const, val[2])
436
+ end
437
+
438
+ result = @builder.assignable(
439
+ @builder.const_fetch(val[0], val[1], val[2]))
440
+ }
441
+ | tCOLON3 tCONSTANT
442
+ {
443
+ if in_def?
444
+ diagnostic(:error, :dynamic_const, val[1])
445
+ end
446
+
447
+ result = @builder.assignable(
448
+ @builder.const_global(val[0], val[1]))
449
+ }
450
+ | backref
451
+ {
452
+ result = @builder.assignable(val[0])
453
+ }
454
+
455
+ lhs: variable
456
+ {
457
+ result = @builder.assignable(val[0])
458
+ }
459
+ | primary_value tLBRACK2 aref_args tRBRACK
460
+ {
461
+ result = @builder.index_asgn(val[0], val[1], val[2], val[3])
462
+ }
463
+ | primary_value tDOT tIDENTIFIER
464
+ {
465
+ result = @builder.attr_asgn(val[0], val[1], val[2])
466
+ }
467
+ | primary_value tCOLON2 tIDENTIFIER
468
+ {
469
+ result = @builder.attr_asgn(val[0], val[1], val[2])
470
+ }
471
+ | primary_value tDOT tCONSTANT
472
+ {
473
+ result = @builder.attr_asgn(val[0], val[1], val[2])
474
+ }
475
+ | primary_value tCOLON2 tCONSTANT
476
+ {
477
+ if in_def?
478
+ diagnostic(:error, :dynamic_const, val[2])
479
+ end
480
+
481
+ result = @builder.assignable(
482
+ @builder.const_fetch(val[0], val[1], val[2]))
483
+ }
484
+ | tCOLON3 tCONSTANT
485
+ {
486
+ if in_def?
487
+ diagnostic(:error, :dynamic_const, val[1])
488
+ end
489
+
490
+ result = @builder.assignable(
491
+ @builder.const_global(val[0], val[1]))
492
+ }
493
+ | backref
494
+ {
495
+ result = @builder.assignable(val[0])
496
+ }
497
+
498
+ cname: tIDENTIFIER
499
+ {
500
+ diagnostic(:error, :module_name_const, val[0])
501
+ }
502
+ | tCONSTANT
503
+
504
+ cpath: tCOLON3 cname
505
+ {
506
+ result = @builder.const_global(val[0], val[1])
507
+ }
508
+ | cname
509
+ {
510
+ result = @builder.const(val[0])
511
+ }
512
+ | primary_value tCOLON2 cname
513
+ {
514
+ result = @builder.const_fetch(val[0], val[1], val[2])
515
+ }
516
+
517
+ fname: tIDENTIFIER | tCONSTANT | tFID
518
+ | op
519
+ | reswords
520
+
521
+ fsym: fname
522
+ {
523
+ result = @builder.symbol(val[0])
524
+ }
525
+ | symbol
526
+
527
+ fitem: fsym
528
+ | dsym
529
+
530
+ undef_list: fitem
531
+ {
532
+ result = [ val[0] ]
533
+ }
534
+ | undef_list tCOMMA
535
+ {
536
+ @lexer.state = :expr_fname
537
+ }
538
+ fitem
539
+ {
540
+ result = val[0] << val[3]
541
+ }
542
+
543
+ op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
544
+ | tMATCH | tGT | tGEQ | tLT | tLEQ | tLSHFT
545
+ | tRSHFT | tPLUS | tMINUS | tSTAR2 | tSTAR | tDIVIDE
546
+ | tPERCENT | tPOW | tTILDE | tUPLUS | tUMINUS | tAREF
547
+ | tASET | tBACK_REF2
548
+
549
+ reswords: k__LINE__ | k__FILE__ | klBEGIN | klEND | kALIAS | kAND
550
+ | kBEGIN | kBREAK | kCASE | kCLASS | kDEF | kDEFINED
551
+ | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
552
+ | kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
553
+ | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF
554
+ | kSUPER | kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
555
+ | kIF | kUNLESS | kWHILE | kUNTIL
556
+
557
+ arg: lhs tEQL arg
558
+ {
559
+ result = @builder.assign(val[0], val[1], val[2])
560
+ }
561
+ | lhs tEQL arg kRESCUE_MOD arg
562
+ {
563
+ rescue_body = @builder.rescue_body(val[3],
564
+ nil, nil, nil,
565
+ nil, val[4])
566
+
567
+ rescue_ = @builder.begin_body(val[2], [ rescue_body ])
568
+
569
+ result = @builder.assign(val[0], val[1], rescue_)
570
+ }
571
+ | var_lhs tOP_ASGN arg
572
+ {
573
+ result = @builder.op_assign(val[0], val[1], val[2])
574
+ }
575
+ | primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN arg
576
+ {
577
+ result = @builder.op_assign(
578
+ @builder.index(
579
+ val[0], val[1], val[2], val[3]),
580
+ val[4], val[5])
581
+ }
582
+ | primary_value tDOT tIDENTIFIER tOP_ASGN arg
583
+ {
584
+ result = @builder.op_assign(
585
+ @builder.call_method(
586
+ val[0], val[1], val[2]),
587
+ val[3], val[4])
588
+ }
589
+ | primary_value tDOT tCONSTANT tOP_ASGN arg
590
+ {
591
+ result = @builder.op_assign(
592
+ @builder.call_method(
593
+ val[0], val[1], val[2]),
594
+ val[3], val[4])
595
+ }
596
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
597
+ {
598
+ result = @builder.op_assign(
599
+ @builder.call_method(
600
+ val[0], val[1], val[2]),
601
+ val[3], val[4])
602
+ }
603
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
604
+ {
605
+ diagnostic(:error, :dynamic_const, val[2], [ val[3] ])
606
+ }
607
+ | tCOLON3 tCONSTANT tOP_ASGN arg
608
+ {
609
+ diagnostic(:error, :dynamic_const, val[1], [ val[2] ])
610
+ }
611
+ | backref tOP_ASGN arg
612
+ {
613
+ result = @builder.op_assign(val[0], val[1], val[2])
614
+ }
615
+ | arg tDOT2 arg
616
+ {
617
+ result = @builder.range_inclusive(val[0], val[1], val[2])
618
+ }
619
+ | arg tDOT3 arg
620
+ {
621
+ result = @builder.range_exclusive(val[0], val[1], val[2])
622
+ }
623
+ | arg tPLUS arg
624
+ {
625
+ result = @builder.binary_op(val[0], val[1], val[2])
626
+ }
627
+ | arg tMINUS arg
628
+ {
629
+ result = @builder.binary_op(val[0], val[1], val[2])
630
+ }
631
+ | arg tSTAR2 arg
632
+ {
633
+ result = @builder.binary_op(val[0], val[1], val[2])
634
+ }
635
+ | arg tDIVIDE arg
636
+ {
637
+ result = @builder.binary_op(val[0], val[1], val[2])
638
+ }
639
+ | arg tPERCENT arg
640
+ {
641
+ result = @builder.binary_op(val[0], val[1], val[2])
642
+ }
643
+ | arg tPOW arg
644
+ {
645
+ result = @builder.binary_op(val[0], val[1], val[2])
646
+ }
647
+ | tUMINUS_NUM tINTEGER tPOW arg
648
+ {
649
+ result = @builder.unary_op(val[0],
650
+ @builder.binary_op(
651
+ @builder.integer(val[1]),
652
+ val[2], val[3]))
653
+ }
654
+ | tUMINUS_NUM tFLOAT tPOW arg
655
+ {
656
+ result = @builder.unary_op(val[0],
657
+ @builder.binary_op(
658
+ @builder.float(val[1]),
659
+ val[2], val[3]))
660
+ }
661
+ | tUPLUS arg
662
+ {
663
+ result = @builder.unary_op(val[0], val[1])
664
+ }
665
+ | tUMINUS arg
666
+ {
667
+ result = @builder.unary_op(val[0], val[1])
668
+ }
669
+ | arg tPIPE arg
670
+ {
671
+ result = @builder.binary_op(val[0], val[1], val[2])
672
+ }
673
+ | arg tCARET arg
674
+ {
675
+ result = @builder.binary_op(val[0], val[1], val[2])
676
+ }
677
+ | arg tAMPER2 arg
678
+ {
679
+ result = @builder.binary_op(val[0], val[1], val[2])
680
+ }
681
+ | arg tCMP arg
682
+ {
683
+ result = @builder.binary_op(val[0], val[1], val[2])
684
+ }
685
+ | arg tGT arg
686
+ {
687
+ result = @builder.binary_op(val[0], val[1], val[2])
688
+ }
689
+ | arg tGEQ arg
690
+ {
691
+ result = @builder.binary_op(val[0], val[1], val[2])
692
+ }
693
+ | arg tLT arg
694
+ {
695
+ result = @builder.binary_op(val[0], val[1], val[2])
696
+ }
697
+ | arg tLEQ arg
698
+ {
699
+ result = @builder.binary_op(val[0], val[1], val[2])
700
+ }
701
+ | arg tEQ arg
702
+ {
703
+ result = @builder.binary_op(val[0], val[1], val[2])
704
+ }
705
+ | arg tEQQ arg
706
+ {
707
+ result = @builder.binary_op(val[0], val[1], val[2])
708
+ }
709
+ | arg tNEQ arg
710
+ {
711
+ result = @builder.binary_op(val[0], val[1], val[2])
712
+ }
713
+ | arg tMATCH arg
714
+ {
715
+ result = @builder.binary_op(val[0], val[1], val[2])
716
+ }
717
+ | arg tNMATCH arg
718
+ {
719
+ result = @builder.binary_op(val[0], val[1], val[2])
720
+ }
721
+ | tBANG arg
722
+ {
723
+ result = @builder.not_op(val[0], val[1])
724
+ }
725
+ | tTILDE arg
726
+ {
727
+ result = @builder.unary_op(val[0], val[1])
728
+ }
729
+ | arg tLSHFT arg
730
+ {
731
+ result = @builder.binary_op(val[0], val[1], val[2])
732
+ }
733
+ | arg tRSHFT arg
734
+ {
735
+ result = @builder.binary_op(val[0], val[1], val[2])
736
+ }
737
+ | arg tANDOP arg
738
+ {
739
+ result = @builder.logical_op(:and, val[0], val[1], val[2])
740
+ }
741
+ | arg tOROP arg
742
+ {
743
+ result = @builder.logical_op(:or, val[0], val[1], val[2])
744
+ }
745
+ | kDEFINED opt_nl arg
746
+ {
747
+ result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
748
+ }
749
+ | arg tEH arg tCOLON arg
750
+ {
751
+ result = @builder.ternary(val[0], val[1],
752
+ val[2], val[3], val[4])
753
+ }
754
+ | primary
755
+
756
+ arg_value: arg
757
+ {
758
+ result = value_expr(val[0])
759
+ }
760
+
761
+ aref_args: none
762
+ | command opt_nl
763
+ {
764
+ result = [ val[0] ]
765
+ }
766
+ | args trailer
767
+ {
768
+ result = val[0]
769
+ }
770
+ | args tCOMMA tSTAR arg opt_nl
771
+ {
772
+ result = val[0] << @builder.splat(val[2], val[3])
773
+ }
774
+ | assocs trailer
775
+ {
776
+ result = [ @builder.associate(nil, val[0], nil) ]
777
+ }
778
+ | tSTAR arg opt_nl
779
+ {
780
+ result = [ @builder.splat(val[0], val[1]) ]
781
+ }
782
+
783
+ paren_args: tLPAREN2 none tRPAREN
784
+ {
785
+ result = [ val[0], [], val[2] ]
786
+ }
787
+ | tLPAREN2 call_args opt_nl tRPAREN
788
+ {
789
+ result = [ val[0], val[1], val[3] ]
790
+ }
791
+ | tLPAREN2 block_call opt_nl tRPAREN
792
+ {
793
+ result = [ val[0], [ val[1] ], val[3] ]
794
+ }
795
+ | tLPAREN2 args tCOMMA block_call opt_nl tRPAREN
796
+ {
797
+ result = [ val[0], val[1] << val[3], val[5] ]
798
+ }
799
+
800
+ opt_paren_args: none
801
+ {
802
+ result = [ nil, [], nil ]
803
+ }
804
+ | paren_args
805
+
806
+ call_args: command
807
+ {
808
+ result = [ val[0] ]
809
+ }
810
+ | args opt_block_arg
811
+ {
812
+ result = val[0].concat(val[1])
813
+ }
814
+ | args tCOMMA tSTAR arg_value opt_block_arg
815
+ {
816
+ result = val[0].concat(
817
+ [ @builder.splat(val[2], val[3]),
818
+ *val[4] ])
819
+ }
820
+ | assocs opt_block_arg
821
+ {
822
+ result = [ @builder.associate(nil, val[0], nil),
823
+ *val[1] ]
824
+ }
825
+ | assocs tCOMMA tSTAR arg_value opt_block_arg
826
+ {
827
+ result = [ @builder.associate(nil, val[0], nil),
828
+ @builder.splat(val[2], val[3]),
829
+ *val[4] ]
830
+ }
831
+ | args tCOMMA assocs opt_block_arg
832
+ {
833
+ result = val[0].concat(
834
+ [ @builder.associate(nil, val[2], nil),
835
+ *val[3] ])
836
+ }
837
+ | args tCOMMA assocs tCOMMA tSTAR arg opt_block_arg
838
+ {
839
+ result = val[0].concat(
840
+ [ @builder.associate(nil, val[2], nil),
841
+ @builder.splat(val[4], val[5]),
842
+ *val[6] ])
843
+ }
844
+ | tSTAR arg_value opt_block_arg
845
+ {
846
+ result = [ @builder.splat(val[0], val[1]),
847
+ *val[2] ]
848
+ }
849
+ | block_arg
850
+ {
851
+ result = [ val[0] ]
852
+ }
853
+
854
+ call_args2: arg_value tCOMMA args opt_block_arg
855
+ {
856
+ result = [ val[0], *val[2].concat(val[3]) ]
857
+ }
858
+ | arg_value tCOMMA block_arg
859
+ {
860
+ result = [ val[0], val[2] ]
861
+ }
862
+ | arg_value tCOMMA tSTAR arg_value opt_block_arg
863
+ {
864
+ result = [ val[0],
865
+ @builder.splat(val[2], val[3]),
866
+ *val[4] ]
867
+ }
868
+ | arg_value tCOMMA args tCOMMA tSTAR arg_value opt_block_arg
869
+ {
870
+ result = [ val[0],
871
+ *val[2].
872
+ push(@builder.splat(val[4], val[5])).
873
+ concat(val[6]) ]
874
+ }
875
+ | assocs opt_block_arg
876
+ {
877
+ result = [ @builder.associate(nil, val[0], nil),
878
+ *val[1] ]
879
+ }
880
+ | assocs tCOMMA tSTAR arg_value opt_block_arg
881
+ {
882
+ result = [ @builder.associate(nil, val[0], nil),
883
+ @builder.splat(val[2], val[3]),
884
+ *val[4] ]
885
+ }
886
+ | arg_value tCOMMA assocs opt_block_arg
887
+ {
888
+ result = [ val[0],
889
+ @builder.associate(nil, val[2], nil),
890
+ *val[3] ]
891
+ }
892
+ | arg_value tCOMMA args tCOMMA assocs opt_block_arg
893
+ {
894
+ result = [ val[0],
895
+ *val[2].
896
+ push(@builder.associate(nil, val[4], nil)).
897
+ concat(val[5]) ]
898
+ }
899
+ | arg_value tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
900
+ {
901
+ result = [ val[0],
902
+ @builder.associate(nil, val[2], nil),
903
+ @builder.splat(val[4], val[5]),
904
+ *val[6] ]
905
+ }
906
+ | arg_value tCOMMA args tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
907
+ {
908
+ result = [ val[0],
909
+ *val[2].
910
+ push(@builder.associate(nil, val[4], nil)).
911
+ push(@builder.splat(val[6], val[7])).
912
+ concat(val[8]) ]
913
+ }
914
+ | tSTAR arg_value opt_block_arg
915
+ {
916
+ result = [ @builder.splat(val[0], val[1]),
917
+ *val[2] ]
918
+ }
919
+ | block_arg
920
+ {
921
+ result = [ val[0] ]
922
+ }
923
+
924
+ command_args: {
925
+ result = @lexer.cmdarg.dup
926
+ @lexer.cmdarg.push(true)
927
+ }
928
+ open_args
929
+ {
930
+ @lexer.cmdarg = val[0]
931
+
932
+ result = val[1]
933
+ }
934
+
935
+ open_args: call_args
936
+ {
937
+ result = [ nil, val[0], nil ]
938
+ }
939
+ | tLPAREN_ARG
940
+ {
941
+ @lexer.state = :expr_endarg
942
+ }
943
+ tRPAREN
944
+ {
945
+ diagnostic(:warning, :space_before_lparen, val[0])
946
+
947
+ result = [ val[0], [], val[2] ]
948
+ }
949
+ | tLPAREN_ARG call_args2
950
+ {
951
+ @lexer.state = :expr_endarg
952
+ }
953
+ tRPAREN
954
+ {
955
+ diagnostic(:warning, :space_before_lparen, val[0])
956
+
957
+ result = [ val[0], val[1], val[3] ]
958
+ }
959
+
960
+ block_arg: tAMPER arg_value
961
+ {
962
+ result = @builder.block_pass(val[0], val[1])
963
+ }
964
+
965
+ opt_block_arg: tCOMMA block_arg
966
+ {
967
+ result = [ val[1] ]
968
+ }
969
+ | # nothing
970
+ {
971
+ result = []
972
+ }
973
+
974
+ args: arg_value
975
+ {
976
+ result = [ val[0] ]
977
+ }
978
+ | args tCOMMA arg_value
979
+ {
980
+ result = val[0] << val[2]
981
+ }
982
+
983
+ mrhs: args tCOMMA arg_value
984
+ {
985
+ result = val[0] << val[2]
986
+ }
987
+ | args tCOMMA tSTAR arg_value
988
+ {
989
+ result = val[0] << @builder.splat(val[2], val[3])
990
+ }
991
+ | tSTAR arg_value
992
+ {
993
+ result = [ @builder.splat(val[0], val[1]) ]
994
+ }
995
+
996
+ primary: literal
997
+ | strings
998
+ | xstring
999
+ | regexp
1000
+ | words
1001
+ | qwords
1002
+ | var_ref
1003
+ | backref
1004
+ | tFID
1005
+ {
1006
+ result = @builder.call_method(nil, nil, val[0])
1007
+ }
1008
+ | kBEGIN bodystmt kEND
1009
+ {
1010
+ result = @builder.begin(val[0], val[1], val[2])
1011
+ }
1012
+ | tLPAREN_ARG expr
1013
+ {
1014
+ @lexer.state = :expr_endarg
1015
+ }
1016
+ opt_nl tRPAREN
1017
+ {
1018
+ # TODO better location info here
1019
+ diagnostic :warning, :grouped_expression, val[0]
1020
+
1021
+ result = @builder.parenthesize(val[0], val[1], val[3])
1022
+ }
1023
+ | tLPAREN compstmt tRPAREN
1024
+ {
1025
+ result = @builder.parenthesize(val[0], val[1], val[2])
1026
+ }
1027
+ | primary_value tCOLON2 tCONSTANT
1028
+ {
1029
+ result = @builder.const_fetch(val[0], val[1], val[2])
1030
+ }
1031
+ | tCOLON3 tCONSTANT
1032
+ {
1033
+ result = @builder.const_global(val[0], val[1])
1034
+ }
1035
+ | primary_value tLBRACK2 aref_args tRBRACK
1036
+ {
1037
+ result = @builder.index(val[0], val[1], val[2], val[3])
1038
+ }
1039
+ | tLBRACK aref_args tRBRACK
1040
+ {
1041
+ result = @builder.array(val[0], val[1], val[2])
1042
+ }
1043
+ | tLBRACE assoc_list tRCURLY
1044
+ {
1045
+ result = @builder.associate(val[0], val[1], val[2])
1046
+ }
1047
+ | kRETURN
1048
+ {
1049
+ result = @builder.keyword_cmd(:return, val[0])
1050
+ }
1051
+ | kYIELD tLPAREN2 call_args tRPAREN
1052
+ {
1053
+ result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
1054
+ }
1055
+ | kYIELD tLPAREN2 tRPAREN
1056
+ {
1057
+ result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
1058
+ }
1059
+ | kYIELD
1060
+ {
1061
+ result = @builder.keyword_cmd(:yield, val[0])
1062
+ }
1063
+ | kDEFINED opt_nl tLPAREN2 expr tRPAREN
1064
+ {
1065
+ result = @builder.keyword_cmd(:defined?, val[0],
1066
+ val[2], [ val[3] ], val[4])
1067
+ }
1068
+ | operation brace_block
1069
+ {
1070
+ method_call = @builder.call_method(nil, nil, val[0])
1071
+
1072
+ begin_t, args, body, end_t = val[1]
1073
+ result = @builder.block(method_call,
1074
+ begin_t, args, body, end_t)
1075
+ }
1076
+ | method_call
1077
+ | method_call brace_block
1078
+ {
1079
+ begin_t, args, body, end_t = val[1]
1080
+ result = @builder.block(val[0],
1081
+ begin_t, args, body, end_t)
1082
+ }
1083
+ | kIF expr_value then compstmt if_tail kEND
1084
+ {
1085
+ else_t, else_ = val[4]
1086
+ result = @builder.condition(val[0], val[1], val[2],
1087
+ val[3], else_t,
1088
+ else_, val[5])
1089
+ }
1090
+ | kUNLESS expr_value then compstmt opt_else kEND
1091
+ {
1092
+ else_t, else_ = val[4]
1093
+ result = @builder.condition(val[0], val[1], val[2],
1094
+ else_, else_t,
1095
+ val[3], val[5])
1096
+ }
1097
+ | kWHILE
1098
+ {
1099
+ @lexer.cond.push(true)
1100
+ }
1101
+ expr_value do
1102
+ {
1103
+ @lexer.cond.pop
1104
+ }
1105
+ compstmt kEND
1106
+ {
1107
+ result = @builder.loop(val[0], val[2], val[3],
1108
+ val[5], val[6])
1109
+ }
1110
+ | kUNTIL
1111
+ {
1112
+ @lexer.cond.push(true)
1113
+ }
1114
+ expr_value do
1115
+ {
1116
+ @lexer.cond.pop
1117
+ }
1118
+ compstmt kEND
1119
+ {
1120
+ result = @builder.loop(val[0], val[2], val[3],
1121
+ val[5], val[6])
1122
+ }
1123
+ | kCASE expr_value opt_terms case_body kEND
1124
+ {
1125
+ result = @builder.case(val[0], val[1], val[3], val[4])
1126
+ }
1127
+ | kCASE opt_terms case_body kEND
1128
+ {
1129
+ result = @builder.case(val[0], nil, val[2], val[3])
1130
+ }
1131
+ | kCASE opt_terms kELSE compstmt kEND
1132
+ {
1133
+ result = @builder.case(val[0], nil, [ val[3] ], val[4])
1134
+ }
1135
+ | kFOR for_var kIN
1136
+ {
1137
+ @lexer.cond.push(true)
1138
+ }
1139
+ expr_value do
1140
+ {
1141
+ @lexer.cond.pop
1142
+ }
1143
+ compstmt kEND
1144
+ {
1145
+ result = @builder.for(val[0], val[1],
1146
+ val[2], val[4],
1147
+ val[5], val[7], val[8])
1148
+ }
1149
+ | kCLASS cpath superclass
1150
+ {
1151
+ if in_def?
1152
+ diagnostic(:error, :class_in_def, val[0])
1153
+ end
1154
+
1155
+ @comments.push @lexer.clear_comments
1156
+ @static_env.extend_static
1157
+ }
1158
+ bodystmt kEND
1159
+ {
1160
+ lt_t, superclass = val[2]
1161
+ result = @builder.def_class(val[0], val[1],
1162
+ lt_t, superclass,
1163
+ val[4], val[5])
1164
+
1165
+ @static_env.unextend
1166
+ @lexer.clear_comments
1167
+ }
1168
+ | kCLASS tLSHFT expr term
1169
+ {
1170
+ result = @def_level
1171
+ @def_level = 0
1172
+
1173
+ @static_env.extend_static
1174
+ }
1175
+ bodystmt kEND
1176
+ {
1177
+ result = @builder.def_sclass(val[0], val[1], val[2],
1178
+ val[5], val[6])
1179
+
1180
+ @static_env.unextend
1181
+ @lexer.clear_comments
1182
+
1183
+ @def_level = val[4]
1184
+ }
1185
+ | kMODULE cpath
1186
+ {
1187
+ if in_def?
1188
+ diagnostic(:error, :module_in_def, val[0])
1189
+ end
1190
+
1191
+ @comments.push @lexer.clear_comments
1192
+ @static_env.extend_static
1193
+ }
1194
+ bodystmt kEND
1195
+ {
1196
+ result = @builder.def_module(val[0], val[1],
1197
+ val[3], val[4])
1198
+
1199
+ @static_env.unextend
1200
+ @lexer.clear_comments
1201
+ }
1202
+ | kDEF fname
1203
+ {
1204
+ @comments.push @lexer.clear_comments
1205
+ @def_level += 1
1206
+ @static_env.extend_static
1207
+ }
1208
+ f_arglist bodystmt kEND
1209
+ {
1210
+ result = @builder.def_method(val[0], val[1],
1211
+ val[3], val[4], val[5], @comments.pop)
1212
+
1213
+ @static_env.unextend
1214
+ @def_level -= 1
1215
+ @lexer.clear_comments
1216
+ }
1217
+ | kDEF singleton dot_or_colon
1218
+ {
1219
+ @comments.push @lexer.clear_comments
1220
+ @lexer.state = :expr_fname
1221
+ }
1222
+ fname
1223
+ {
1224
+ @def_level += 1
1225
+ @static_env.extend_static
1226
+ }
1227
+ f_arglist bodystmt kEND
1228
+ {
1229
+ result = @builder.def_singleton(val[0], val[1], val[2],
1230
+ val[4], val[6], val[7], val[8], @comments.pop)
1231
+
1232
+ @static_env.unextend
1233
+ @def_level -= 1
1234
+ @lexer.clear_comments
1235
+ }
1236
+ | kBREAK
1237
+ {
1238
+ result = @builder.keyword_cmd(:break, val[0])
1239
+ }
1240
+ | kNEXT
1241
+ {
1242
+ result = @builder.keyword_cmd(:next, val[0])
1243
+ }
1244
+ | kREDO
1245
+ {
1246
+ result = @builder.keyword_cmd(:redo, val[0])
1247
+ }
1248
+ | kRETRY
1249
+ {
1250
+ result = @builder.keyword_cmd(:retry, val[0])
1251
+ }
1252
+
1253
+ primary_value: primary
1254
+ {
1255
+ result = value_expr(val[0])
1256
+ }
1257
+
1258
+ then: term
1259
+ | tCOLON
1260
+ | kTHEN
1261
+ | term kTHEN
1262
+
1263
+ do: term
1264
+ | tCOLON
1265
+ | kDO_COND
1266
+
1267
+ if_tail: opt_else
1268
+ | kELSIF expr_value then compstmt if_tail
1269
+ {
1270
+ else_t, else_ = val[4]
1271
+ result = [ val[0],
1272
+ @builder.condition(val[0], val[1], val[2],
1273
+ val[3], else_t,
1274
+ else_, nil),
1275
+ ]
1276
+ }
1277
+
1278
+ opt_else: none
1279
+ | kELSE compstmt
1280
+ {
1281
+ result = val
1282
+ }
1283
+
1284
+ for_var: lhs
1285
+ | mlhs
1286
+
1287
+ block_par: mlhs_item
1288
+ {
1289
+ result = [ @builder.arg_expr(val[0]) ]
1290
+ }
1291
+ | block_par tCOMMA mlhs_item
1292
+ {
1293
+ result = val[0] << @builder.arg_expr(val[2])
1294
+ }
1295
+
1296
+ block_var: block_par
1297
+ | block_par tCOMMA
1298
+ | block_par tCOMMA tAMPER lhs
1299
+ {
1300
+ result = val[0].
1301
+ push(@builder.blockarg_expr(val[2], val[3]))
1302
+ }
1303
+ | block_par tCOMMA tSTAR lhs tCOMMA tAMPER lhs
1304
+ {
1305
+ result = val[0].
1306
+ push(@builder.splatarg_expr(val[2], val[3])).
1307
+ push(@builder.blockarg_expr(val[5], val[6]))
1308
+ }
1309
+ | block_par tCOMMA tSTAR tCOMMA tAMPER lhs
1310
+ {
1311
+ result = val[0].
1312
+ push(@builder.splatarg_expr(val[2])).
1313
+ push(@builder.blockarg_expr(val[4], val[5]))
1314
+ }
1315
+ | block_par tCOMMA tSTAR lhs
1316
+ {
1317
+ result = val[0].
1318
+ push(@builder.splatarg_expr(val[2], val[3]))
1319
+ }
1320
+ | block_par tCOMMA tSTAR
1321
+ {
1322
+ result = val[0].
1323
+ push(@builder.splatarg_expr(val[2]))
1324
+ }
1325
+ | tSTAR lhs tCOMMA tAMPER lhs
1326
+ {
1327
+ result = [ @builder.splatarg_expr(val[0], val[1]),
1328
+ @builder.blockarg_expr(val[3], val[4]) ]
1329
+ }
1330
+ | tSTAR tCOMMA tAMPER lhs
1331
+ {
1332
+ result = [ @builder.splatarg_expr(val[0]),
1333
+ @builder.blockarg_expr(val[2], val[3]) ]
1334
+ }
1335
+ | tSTAR lhs
1336
+ {
1337
+ result = [ @builder.splatarg_expr(val[0], val[1]) ]
1338
+ }
1339
+ | tSTAR
1340
+ {
1341
+ result = [ @builder.splatarg_expr(val[0]) ]
1342
+ }
1343
+ | tAMPER lhs
1344
+ {
1345
+ result = [ @builder.blockarg_expr(val[0], val[1]) ]
1346
+ }
1347
+ ;
1348
+
1349
+ opt_block_var: none
1350
+ {
1351
+ result = @builder.args(nil, [], nil)
1352
+ }
1353
+ | tPIPE tPIPE
1354
+ {
1355
+ result = @builder.args(val[0], [], val[1])
1356
+ }
1357
+ | tOROP
1358
+ {
1359
+ result = @builder.args(val[0], [], val[0])
1360
+ }
1361
+ | tPIPE block_var tPIPE
1362
+ {
1363
+ result = @builder.args(val[0], val[1], val[2])
1364
+ }
1365
+
1366
+ do_block: kDO_BLOCK
1367
+ {
1368
+ @static_env.extend_dynamic
1369
+ }
1370
+ opt_block_var compstmt kEND
1371
+ {
1372
+ result = [ val[0], val[2], val[3], val[4] ]
1373
+
1374
+ @static_env.unextend
1375
+ }
1376
+
1377
+ block_call: command do_block
1378
+ {
1379
+ begin_t, block_args, body, end_t = val[1]
1380
+ result = @builder.block(val[0],
1381
+ begin_t, block_args, body, end_t)
1382
+ }
1383
+ | block_call tDOT operation2 opt_paren_args
1384
+ {
1385
+ lparen_t, args, rparen_t = val[3]
1386
+ result = @builder.call_method(val[0], val[1], val[2],
1387
+ lparen_t, args, rparen_t)
1388
+ }
1389
+ | block_call tCOLON2 operation2 opt_paren_args
1390
+ {
1391
+ lparen_t, args, rparen_t = val[3]
1392
+ result = @builder.call_method(val[0], val[1], val[2],
1393
+ lparen_t, args, rparen_t)
1394
+ }
1395
+
1396
+ method_call: operation paren_args
1397
+ {
1398
+ lparen_t, args, rparen_t = val[1]
1399
+ result = @builder.call_method(nil, nil, val[0],
1400
+ lparen_t, args, rparen_t)
1401
+ }
1402
+ | primary_value tDOT operation2 opt_paren_args
1403
+ {
1404
+ lparen_t, args, rparen_t = val[3]
1405
+ result = @builder.call_method(val[0], val[1], val[2],
1406
+ lparen_t, args, rparen_t)
1407
+ }
1408
+ | primary_value tCOLON2 operation2 paren_args
1409
+ {
1410
+ lparen_t, args, rparen_t = val[3]
1411
+ result = @builder.call_method(val[0], val[1], val[2],
1412
+ lparen_t, args, rparen_t)
1413
+ }
1414
+ | primary_value tCOLON2 operation3
1415
+ {
1416
+ result = @builder.call_method(val[0], val[1], val[2])
1417
+ }
1418
+ | kSUPER paren_args
1419
+ {
1420
+ lparen_t, args, rparen_t = val[1]
1421
+ result = @builder.keyword_cmd(:super, val[0],
1422
+ lparen_t, args, rparen_t)
1423
+ }
1424
+ | kSUPER
1425
+ {
1426
+ result = @builder.keyword_cmd(:zsuper, val[0])
1427
+ }
1428
+
1429
+ brace_block: tLCURLY
1430
+ {
1431
+ @static_env.extend_dynamic
1432
+ }
1433
+ opt_block_var compstmt tRCURLY
1434
+ {
1435
+ result = [ val[0], val[2], val[3], val[4] ]
1436
+
1437
+ @static_env.unextend
1438
+ }
1439
+ | kDO
1440
+ {
1441
+ @static_env.extend_dynamic
1442
+ }
1443
+ opt_block_var compstmt kEND
1444
+ {
1445
+ result = [ val[0], val[2], val[3], val[4] ]
1446
+
1447
+ @static_env.unextend
1448
+ }
1449
+
1450
+ case_body: kWHEN when_args then compstmt cases
1451
+ {
1452
+ result = [ @builder.when(val[0], val[1], val[2], val[3]),
1453
+ *val[4] ]
1454
+ }
1455
+
1456
+ when_args: args
1457
+ | args tCOMMA tSTAR arg_value
1458
+ {
1459
+ result = val[0] << @builder.splat(val[2], val[3])
1460
+ }
1461
+ | tSTAR arg_value
1462
+ {
1463
+ result = [ @builder.splat(val[0], val[1]) ]
1464
+ }
1465
+
1466
+ cases: opt_else
1467
+ {
1468
+ else_t, else_ = val[0]
1469
+ result = [ else_ ]
1470
+ }
1471
+ | case_body
1472
+
1473
+ opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
1474
+ {
1475
+ assoc_t, exc_var = val[2]
1476
+
1477
+ if val[1]
1478
+ exc_list = @builder.array(nil, val[1], nil)
1479
+ end
1480
+
1481
+ result = [ @builder.rescue_body(val[0],
1482
+ exc_list, assoc_t, exc_var,
1483
+ val[3], val[4]),
1484
+ *val[5] ]
1485
+ }
1486
+ |
1487
+ {
1488
+ result = []
1489
+ }
1490
+
1491
+ exc_list: arg_value
1492
+ {
1493
+ result = [ val[0] ]
1494
+ }
1495
+ | mrhs
1496
+ | none
1497
+
1498
+ exc_var: tASSOC lhs
1499
+ {
1500
+ result = val
1501
+ }
1502
+ | none
1503
+
1504
+ opt_ensure: kENSURE compstmt
1505
+ {
1506
+ result = val
1507
+ }
1508
+ | none
1509
+
1510
+ literal: numeric
1511
+ | symbol
1512
+ | dsym
1513
+
1514
+ strings: string
1515
+ {
1516
+ result = @builder.string_compose(nil, val[0], nil)
1517
+ }
1518
+
1519
+ string: string1
1520
+ {
1521
+ result = [ val[0] ]
1522
+ }
1523
+ | string string1
1524
+ {
1525
+ result = val[0] << val[1]
1526
+ }
1527
+
1528
+ string1: tSTRING_BEG string_contents tSTRING_END
1529
+ {
1530
+ result = @builder.string_compose(val[0], val[1], val[2])
1531
+ }
1532
+ | tSTRING
1533
+ {
1534
+ result = @builder.string(val[0])
1535
+ }
1536
+
1537
+ xstring: tXSTRING_BEG xstring_contents tSTRING_END
1538
+ {
1539
+ result = @builder.xstring_compose(val[0], val[1], val[2])
1540
+ }
1541
+
1542
+ regexp: tREGEXP_BEG xstring_contents tSTRING_END tREGEXP_OPT
1543
+ {
1544
+ opts = @builder.regexp_options(val[3])
1545
+ result = @builder.regexp_compose(val[0], val[1], val[2], opts)
1546
+ }
1547
+
1548
+ words: tWORDS_BEG tSPACE tSTRING_END
1549
+ { # :nocov: TODO: unused with Ragel lexer; remove?
1550
+ result = @builder.words_compose(val[0], [], val[2])
1551
+ }
1552
+ | tWORDS_BEG word_list tSTRING_END
1553
+ {
1554
+ result = @builder.words_compose(val[0], val[1], val[2])
1555
+ }
1556
+
1557
+ word_list: # nothing
1558
+ {
1559
+ result = []
1560
+ }
1561
+ | word_list word tSPACE
1562
+ {
1563
+ result = val[0] << val[1]
1564
+ }
1565
+
1566
+ word: string_content
1567
+ | word string_content
1568
+ { # :nocov: TODO: test this rule, remove if unused
1569
+ raise "unused 'word string_content'"
1570
+ }
1571
+
1572
+ qwords: tQWORDS_BEG tSPACE tSTRING_END
1573
+ { # :nocov: TODO: unused with Ragel lexer; remove?
1574
+ result = @builder.words_compose(val[0], [], val[2])
1575
+ }
1576
+ | tQWORDS_BEG qword_list tSTRING_END
1577
+ {
1578
+ result = @builder.words_compose(val[0], val[1], val[2])
1579
+ }
1580
+
1581
+ qword_list: # nothing
1582
+ {
1583
+ result = []
1584
+ }
1585
+ | qword_list tSTRING_CONTENT tSPACE
1586
+ {
1587
+ result = val[0] << @builder.string(val[1])
1588
+ }
1589
+
1590
+ string_contents: # nothing
1591
+ {
1592
+ result = []
1593
+ }
1594
+ | string_contents string_content
1595
+ {
1596
+ result = val[0] << val[1]
1597
+ }
1598
+
1599
+ xstring_contents: # nothing # TODO: replace with string_contents?
1600
+ {
1601
+ result = []
1602
+ }
1603
+ | xstring_contents string_content
1604
+ {
1605
+ result = val[0] << val[1]
1606
+ }
1607
+
1608
+ string_content: tSTRING_CONTENT
1609
+ {
1610
+ result = @builder.string(val[0])
1611
+ }
1612
+ | tSTRING_DVAR string_dvar
1613
+ {
1614
+ result = val[1]
1615
+ }
1616
+ | tSTRING_DBEG
1617
+ {
1618
+ @lexer.cond.push(false)
1619
+ @lexer.cmdarg.push(false)
1620
+ }
1621
+ compstmt tRCURLY
1622
+ {
1623
+ @lexer.cond.lexpop
1624
+ @lexer.cmdarg.lexpop
1625
+
1626
+ result = val[2]
1627
+ }
1628
+
1629
+ string_dvar: tGVAR
1630
+ {
1631
+ result = @builder.gvar(val[0])
1632
+ }
1633
+ | tIVAR
1634
+ {
1635
+ result = @builder.ivar(val[0])
1636
+ }
1637
+ | tCVAR
1638
+ {
1639
+ result = @builder.cvar(val[0])
1640
+ }
1641
+ | backref
1642
+
1643
+
1644
+ symbol: tSYMBOL
1645
+ {
1646
+ if val[0][0].empty?
1647
+ diagnostic(:error, :empty_symbol, val[0])
1648
+ end
1649
+
1650
+ result = @builder.symbol(val[0])
1651
+ }
1652
+
1653
+ dsym: tSYMBEG xstring_contents tSTRING_END
1654
+ {
1655
+ result = @builder.symbol_compose(val[0], val[1], val[2])
1656
+ }
1657
+
1658
+ numeric: tINTEGER
1659
+ {
1660
+ result = @builder.integer(val[0])
1661
+ }
1662
+ | tFLOAT
1663
+ {
1664
+ result = @builder.float(val[0])
1665
+ }
1666
+ | tUMINUS_NUM tINTEGER =tLOWEST
1667
+ {
1668
+ result = @builder.integer(val[1], true)
1669
+ }
1670
+ | tUMINUS_NUM tFLOAT =tLOWEST
1671
+ {
1672
+ result = @builder.float(val[1], true)
1673
+ }
1674
+
1675
+ variable: tIDENTIFIER
1676
+ {
1677
+ result = @builder.ident(val[0])
1678
+ }
1679
+ | tIVAR
1680
+ {
1681
+ result = @builder.ivar(val[0])
1682
+ }
1683
+ | tGVAR
1684
+ {
1685
+ result = @builder.gvar(val[0])
1686
+ }
1687
+ | tCVAR
1688
+ {
1689
+ result = @builder.cvar(val[0])
1690
+ }
1691
+ | tCONSTANT
1692
+ {
1693
+ result = @builder.const(val[0])
1694
+ }
1695
+ | kNIL
1696
+ {
1697
+ result = @builder.nil(val[0])
1698
+ }
1699
+ | kSELF
1700
+ {
1701
+ result = @builder.self(val[0])
1702
+ }
1703
+ | kTRUE
1704
+ {
1705
+ result = @builder.true(val[0])
1706
+ }
1707
+ | kFALSE
1708
+ {
1709
+ result = @builder.false(val[0])
1710
+ }
1711
+ | k__FILE__
1712
+ {
1713
+ result = @builder.__FILE__(val[0])
1714
+ }
1715
+ | k__LINE__
1716
+ {
1717
+ result = @builder.__LINE__(val[0])
1718
+ }
1719
+
1720
+ var_ref: variable
1721
+ {
1722
+ result = @builder.accessible(val[0])
1723
+ }
1724
+
1725
+ var_lhs: variable
1726
+ {
1727
+ result = @builder.assignable(val[0])
1728
+ }
1729
+
1730
+ backref: tNTH_REF
1731
+ {
1732
+ result = @builder.nth_ref(val[0])
1733
+ }
1734
+ | tBACK_REF
1735
+ {
1736
+ result = @builder.back_ref(val[0])
1737
+ }
1738
+
1739
+ superclass: term
1740
+ {
1741
+ result = nil
1742
+ }
1743
+ | tLT expr_value term
1744
+ {
1745
+ result = [ val[0], val[1] ]
1746
+ }
1747
+ | error term
1748
+ {
1749
+ yyerrok
1750
+ result = nil
1751
+ }
1752
+
1753
+ f_arglist: tLPAREN2 f_args opt_nl tRPAREN
1754
+ {
1755
+ result = @builder.args(val[0], val[1], val[3])
1756
+
1757
+ @lexer.state = :expr_beg
1758
+ }
1759
+ | f_args term
1760
+ {
1761
+ result = @builder.args(nil, val[0], nil)
1762
+ }
1763
+
1764
+ f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_f_block_arg
1765
+ {
1766
+ result = val[0].
1767
+ concat(val[2]).
1768
+ concat(val[4]).
1769
+ concat(val[5])
1770
+ }
1771
+ | f_arg tCOMMA f_optarg opt_f_block_arg
1772
+ {
1773
+ result = val[0].
1774
+ concat(val[2]).
1775
+ concat(val[3])
1776
+ }
1777
+ | f_arg tCOMMA f_rest_arg opt_f_block_arg
1778
+ {
1779
+ result = val[0].
1780
+ concat(val[2]).
1781
+ concat(val[3])
1782
+ }
1783
+ | f_arg opt_f_block_arg
1784
+ {
1785
+ result = val[0].
1786
+ concat(val[1])
1787
+ }
1788
+ | f_optarg tCOMMA f_rest_arg opt_f_block_arg
1789
+ {
1790
+ result = val[0].
1791
+ concat(val[2]).
1792
+ concat(val[3])
1793
+ }
1794
+ | f_optarg opt_f_block_arg
1795
+ {
1796
+ result = val[0].
1797
+ concat(val[1])
1798
+ }
1799
+ | f_rest_arg opt_f_block_arg
1800
+ {
1801
+ result = val[0].
1802
+ concat(val[1])
1803
+ }
1804
+ | f_block_arg
1805
+ {
1806
+ result = [ val[0] ]
1807
+ }
1808
+ | # nothing
1809
+ {
1810
+ result = []
1811
+ }
1812
+
1813
+ f_norm_arg: tCONSTANT
1814
+ {
1815
+ diagnostic(:error, :argument_const, val[0])
1816
+ }
1817
+ | tIVAR
1818
+ {
1819
+ diagnostic(:error, :argument_ivar, val[0])
1820
+ }
1821
+ | tGVAR
1822
+ {
1823
+ diagnostic(:error, :argument_gvar, val[0])
1824
+ }
1825
+ | tCVAR
1826
+ {
1827
+ diagnostic(:error, :argument_cvar, val[0])
1828
+ }
1829
+ | tIDENTIFIER
1830
+ {
1831
+ @static_env.declare val[0][0]
1832
+
1833
+ result = @builder.arg(val[0])
1834
+ }
1835
+
1836
+ f_arg: f_norm_arg
1837
+ {
1838
+ result = [ val[0] ]
1839
+ }
1840
+ | f_arg tCOMMA f_norm_arg
1841
+ {
1842
+ result = val[0] << val[2]
1843
+ }
1844
+
1845
+ f_opt: tIDENTIFIER tEQL arg_value
1846
+ {
1847
+ @static_env.declare val[0][0]
1848
+
1849
+ result = @builder.optarg(val[0], val[1], val[2])
1850
+ }
1851
+
1852
+ f_optarg: f_opt
1853
+ {
1854
+ result = [ val[0] ]
1855
+ }
1856
+ | f_optarg tCOMMA f_opt
1857
+ {
1858
+ result = val[0] << val[2]
1859
+ }
1860
+
1861
+ restarg_mark: tSTAR2 | tSTAR
1862
+
1863
+ f_rest_arg: restarg_mark tIDENTIFIER
1864
+ {
1865
+ @static_env.declare val[1][0]
1866
+
1867
+ result = [ @builder.splatarg(val[0], val[1]) ]
1868
+ }
1869
+ | restarg_mark
1870
+ {
1871
+ result = [ @builder.splatarg(val[0]) ]
1872
+ }
1873
+
1874
+ blkarg_mark: tAMPER2 | tAMPER
1875
+
1876
+ f_block_arg: blkarg_mark tIDENTIFIER
1877
+ {
1878
+ @static_env.declare val[1][0]
1879
+
1880
+ result = @builder.blockarg(val[0], val[1])
1881
+ }
1882
+
1883
+ opt_f_block_arg: tCOMMA f_block_arg
1884
+ {
1885
+ result = [ val[1] ]
1886
+ }
1887
+ | # nothing
1888
+ {
1889
+ result = []
1890
+ }
1891
+
1892
+ singleton: var_ref
1893
+ | tLPAREN2 expr opt_nl tRPAREN
1894
+ {
1895
+ result = val[1]
1896
+ }
1897
+
1898
+ assoc_list: none
1899
+ {
1900
+ result = []
1901
+ }
1902
+ | assocs trailer
1903
+ {
1904
+ result = val[0]
1905
+ }
1906
+ | args trailer
1907
+ {
1908
+ result = @builder.pair_list_18(val[0])
1909
+ }
1910
+
1911
+ assocs: assoc
1912
+ {
1913
+ result = [ val[0] ]
1914
+ }
1915
+ | assocs tCOMMA assoc
1916
+ {
1917
+ result = val[0] << val[2]
1918
+ }
1919
+
1920
+ assoc: arg_value tASSOC arg_value
1921
+ {
1922
+ result = @builder.pair(val[0], val[1], val[2])
1923
+ }
1924
+
1925
+ operation: tIDENTIFIER | tCONSTANT | tFID
1926
+ operation2: tIDENTIFIER | tCONSTANT | tFID | op
1927
+ operation3: tIDENTIFIER | tFID | op
1928
+ dot_or_colon: tDOT | tCOLON2
1929
+ opt_terms: | terms
1930
+ opt_nl: | tNL
1931
+ trailer: | tNL | tCOMMA
1932
+
1933
+ term: tSEMI
1934
+ {
1935
+ yyerrok
1936
+ }
1937
+ | tNL
1938
+
1939
+ terms: term
1940
+ | terms tSEMI
1941
+
1942
+ none: # nothing
1943
+ {
1944
+ result = nil
1945
+ }
1946
+
1947
+ end
1948
+
1949
+ ---- header
1950
+
1951
+ require 'parser'
1952
+
1953
+ ---- inner
1954
+
1955
+ def version
1956
+ 18
1957
+ end