parser 0.9.alpha1 → 0.9.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.
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