ruby_parser 3.6.6 → 3.7.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.
data/lib/ruby_lexer.rb CHANGED
@@ -81,7 +81,6 @@ class RubyLexer
81
81
  # grammar use.
82
82
 
83
83
  attr_accessor :lex_state
84
-
85
84
  attr_accessor :lex_strterm
86
85
  attr_accessor :lpar_beg
87
86
  attr_accessor :paren_nest
@@ -120,10 +119,6 @@ class RubyLexer
120
119
  end
121
120
  alias :bol? :beginning_of_line? # to make .rex file more readable
122
121
 
123
- def check re
124
- ss.check re
125
- end
126
-
127
122
  def comments # TODO: remove this... maybe comment_string + attr_accessor
128
123
  c = @comments.join
129
124
  @comments.clear
@@ -278,10 +273,18 @@ class RubyLexer
278
273
  in_lex_state? :expr_end, :expr_endarg, :expr_endfn
279
274
  end
280
275
 
276
+ def ruby22_label?
277
+ ruby22? and is_label_possible?
278
+ end
279
+
281
280
  def is_label_possible?
282
281
  (in_lex_state?(:expr_beg, :expr_endfn) && !command_state) || is_arg?
283
282
  end
284
283
 
284
+ def is_label_suffix?
285
+ check(/:(?!:)/)
286
+ end
287
+
285
288
  def is_space_arg? c = "x"
286
289
  is_arg? and space_seen and c !~ /\s/
287
290
  end
@@ -335,6 +338,12 @@ class RubyLexer
335
338
  when "}" then
336
339
  self.brace_nest -= 1
337
340
  self.lex_state = :expr_endarg
341
+
342
+ # TODO
343
+ # if (c == '}') {
344
+ # if (!brace_nest--) c = tSTRING_DEND;
345
+ # }
346
+
338
347
  return :tRCURLY, matched
339
348
  when "]" then
340
349
  self.paren_nest -= 1
@@ -449,7 +458,7 @@ class RubyLexer
449
458
  self.lineno += matched.lines.to_a.size if scan(/\n+/)
450
459
 
451
460
  return if in_lex_state?(:expr_beg, :expr_value, :expr_class,
452
- :expr_fname, :expr_dot)
461
+ :expr_fname, :expr_dot, :expr_labelarg)
453
462
 
454
463
  if scan(/([\ \t\r\f\v]*)\./) then
455
464
  self.space_seen = true unless ss[1].empty?
@@ -653,6 +662,12 @@ class RubyLexer
653
662
  return result(:expr_end, :tSYMBOL, symbol)
654
663
  end
655
664
 
665
+ def process_label text
666
+ result = process_symbol text
667
+ result[0] = :tLABEL
668
+ result
669
+ end
670
+
656
671
  def process_token text
657
672
  # TODO: make this always return [token, lineno]
658
673
  token = self.token = text
@@ -673,7 +688,8 @@ class RubyLexer
673
688
  :tIDENTIFIER
674
689
  end
675
690
 
676
- if !ruby18 and is_label_possible? and scan(/:(?!:)/) then
691
+ if !ruby18 and is_label_possible? and is_label_suffix? then
692
+ scan(/:/)
677
693
  return result(:expr_labelarg, :tLABEL, [token, self.lineno])
678
694
  end
679
695
 
@@ -734,7 +750,7 @@ class RubyLexer
734
750
  else
735
751
  result(state, :kDO, value)
736
752
  end
737
- when in_lex_state?(:expr_beg, :expr_value) then
753
+ when in_lex_state?(:expr_beg, :expr_value) then # TODO: :expr_labelarg
738
754
  result(state, keyword.id0, value)
739
755
  when keyword.id0 != keyword.id1 then
740
756
  result(:expr_beg, keyword.id1, value)
@@ -866,6 +882,10 @@ class RubyLexer
866
882
  ss.scan re
867
883
  end
868
884
 
885
+ def check re
886
+ ss.check re
887
+ end
888
+
869
889
  def scanner_class # TODO: design this out of oedipus_lex. or something.
870
890
  RPStringScanner
871
891
  end
@@ -1036,6 +1056,10 @@ class RubyLexer
1036
1056
  # do nothing for now
1037
1057
  end
1038
1058
 
1059
+ def ruby22?
1060
+ Ruby22Parser === parser
1061
+ end
1062
+
1039
1063
  def process_string # TODO: rewrite / remove
1040
1064
  token = if lex_strterm[0] == :heredoc then
1041
1065
  self.heredoc lex_strterm
@@ -1043,11 +1067,20 @@ class RubyLexer
1043
1067
  self.parse_string lex_strterm
1044
1068
  end
1045
1069
 
1046
- token_type, _ = token
1070
+ token_type, c = token
1071
+
1072
+ if ruby22? && token_type == :tSTRING_END && ["'", '"'].include?(c) then
1073
+ if (([:expr_beg, :expr_endfn].include?(lex_state) &&
1074
+ !cond.is_in_state) || is_arg?) &&
1075
+ is_label_suffix? then
1076
+ scan(/:/)
1077
+ token_type = token[0] = :tLABEL_END
1078
+ end
1079
+ end
1047
1080
 
1048
- if token_type == :tSTRING_END || token_type == :tREGEXP_END then
1081
+ if [:tSTRING_END, :tREGEXP_END, :tLABEL_END].include? token_type then
1049
1082
  self.lex_strterm = nil
1050
- self.lex_state = :expr_end
1083
+ self.lex_state = (token_type == :tLABEL_END) ? :expr_labelarg : :expr_end
1051
1084
  end
1052
1085
 
1053
1086
  return token
data/lib/ruby_lexer.rex CHANGED
@@ -61,6 +61,7 @@ rule
61
61
  | bol? /\=begin(?=\s)/ process_begin
62
62
  | /\=(?=begin\b)/ { result arg_state, TOKENS[text], text }
63
63
 
64
+ ruby22_label? /\"(#{SIMPLE_STRING})\":/o process_label
64
65
  /\"(#{SIMPLE_STRING})\"/o { result :expr_end, :tSTRING, text[1..-2].gsub(ESC) { unescape $1 } }
65
66
  /\"/ { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
66
67
 
@@ -92,7 +93,8 @@ rule
92
93
 
93
94
  /\[/ process_square_bracket
94
95
 
95
- # 2.2: /\'#{SSTRING}\':/o process_symbol
96
+ # TODO: make this conditional on ruby 2.2
97
+ ruby22_label? /\'#{SSTRING}\':/o process_label
96
98
  /\'#{SSTRING}\'/o { result :expr_end, :tSTRING, matched[1..-2].gsub(/\\\\/, "\\").gsub(/\\'/, "'") } # " stupid emacs
97
99
 
98
100
  : /\|/
@@ -111,6 +111,8 @@ class RubyLexer
111
111
  when text = ss.scan(/\=(?=begin\b)/) then
112
112
  action { result arg_state, TOKENS[text], text }
113
113
  end # group /=/
114
+ when ruby22_label? && (text = ss.scan(/\"(#{SIMPLE_STRING})\":/o)) then
115
+ process_label text
114
116
  when text = ss.scan(/\"(#{SIMPLE_STRING})\"/o) then
115
117
  action { result :expr_end, :tSTRING, text[1..-2].gsub(ESC) { unescape $1 } }
116
118
  when text = ss.scan(/\"/) then
@@ -161,6 +163,8 @@ class RubyLexer
161
163
  end # group /[+\d]/
162
164
  when text = ss.scan(/\[/) then
163
165
  process_square_bracket text
166
+ when ruby22_label? && (text = ss.scan(/\'#{SSTRING}\':/o)) then
167
+ process_label text
164
168
  when text = ss.scan(/\'#{SSTRING}\'/o) then
165
169
  action { result :expr_end, :tSTRING, matched[1..-2].gsub(/\\\\/, "\\").gsub(/\\'/, "'") } # " stupid emacs
166
170
  when ss.check(/\|/) then
data/lib/ruby_parser.rb CHANGED
@@ -2,4 +2,5 @@ require 'ruby18_parser'
2
2
  require 'ruby19_parser'
3
3
  require 'ruby20_parser'
4
4
  require 'ruby21_parser'
5
+ require 'ruby22_parser'
5
6
  require 'ruby_parser_extras'
@@ -0,0 +1,2456 @@
1
+ # -*- racc -*-
2
+
3
+ #if defined(RUBY20)
4
+ class Ruby20Parser
5
+ #elif defined(RUBY21)
6
+ class Ruby21Parser
7
+ #elif defined(RUBY22)
8
+ class Ruby22Parser
9
+ #endif
10
+
11
+ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
12
+ kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
13
+ kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
14
+ kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
15
+ kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
16
+ k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
17
+ tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
18
+ tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
19
+ tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
20
+ tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
21
+ tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
22
+ tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
23
+ tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
24
+ tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
25
+ tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END
26
+ tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA
27
+ tLAMBEG tDSTAR tCHAR tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DEND tUBANG
28
+ #if defined(RUBY21) || defined(RUBY22)
29
+ tRATIONAL tIMAGINARY
30
+ #endif
31
+ #if defined(RUBY22)
32
+ tLABEL_END
33
+ #endif
34
+
35
+ prechigh
36
+ right tBANG tTILDE tUPLUS
37
+ right tPOW
38
+ right tUMINUS_NUM tUMINUS
39
+ left tSTAR2 tDIVIDE tPERCENT
40
+ left tPLUS tMINUS
41
+ left tLSHFT tRSHFT
42
+ left tAMPER2
43
+ left tPIPE tCARET
44
+ left tGT tGEQ tLT tLEQ
45
+ nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
46
+ left tANDOP
47
+ left tOROP
48
+ nonassoc tDOT2 tDOT3
49
+ right tEH tCOLON
50
+ left kRESCUE_MOD
51
+ right tEQL tOP_ASGN
52
+ nonassoc kDEFINED
53
+ right kNOT
54
+ left kOR kAND
55
+ nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
56
+ nonassoc tLBRACE_ARG
57
+ nonassoc tLOWEST
58
+ preclow
59
+
60
+ rule
61
+
62
+ program: {
63
+ self.lexer.lex_state = :expr_beg
64
+ }
65
+ top_compstmt
66
+ {
67
+ result = new_compstmt val
68
+ }
69
+
70
+ top_compstmt: top_stmts opt_terms
71
+ {
72
+ result = val[0]
73
+ }
74
+
75
+ top_stmts: none
76
+ | top_stmt
77
+ | top_stmts terms top_stmt
78
+ {
79
+ result = self.block_append val[0], val[2]
80
+ }
81
+ | error top_stmt
82
+
83
+ top_stmt: stmt
84
+ {
85
+ result = val[0]
86
+
87
+ # TODO: remove once I have more confidence this is fixed
88
+ # result.each_of_type :call_args do |s|
89
+ # debug20 666, s, result
90
+ # end
91
+ }
92
+ | klBEGIN
93
+ {
94
+ if (self.in_def || self.in_single > 0) then
95
+ debug20 1
96
+ yyerror "BEGIN in method"
97
+ end
98
+ self.env.extend
99
+ }
100
+ tLCURLY top_compstmt tRCURLY
101
+ {
102
+ result = new_iter s(:preexe), nil, val[3]
103
+ }
104
+
105
+ bodystmt: compstmt opt_rescue opt_else opt_ensure
106
+ {
107
+ result = new_body val
108
+ }
109
+
110
+ compstmt: stmts opt_terms
111
+ {
112
+ result = new_compstmt val
113
+ }
114
+
115
+ stmts: none
116
+ | stmt
117
+ | stmts terms stmt
118
+ {
119
+ result = self.block_append val[0], val[2]
120
+ }
121
+ | error stmt
122
+ {
123
+ result = val[1]
124
+ debug20 2, val, result
125
+ }
126
+
127
+ stmt: kALIAS fitem
128
+ {
129
+ lexer.lex_state = :expr_fname
130
+ result = self.lexer.lineno
131
+ }
132
+ fitem
133
+ {
134
+ result = s(:alias, val[1], val[3]).line(val[2])
135
+ }
136
+ | kALIAS tGVAR tGVAR
137
+ {
138
+ result = s(:valias, val[1].to_sym, val[2].to_sym)
139
+ }
140
+ | kALIAS tGVAR tBACK_REF
141
+ {
142
+ result = s(:valias, val[1].to_sym, :"$#{val[2]}")
143
+ }
144
+ | kALIAS tGVAR tNTH_REF
145
+ {
146
+ yyerror "can't make alias for the number variables"
147
+ }
148
+ | kUNDEF undef_list
149
+ {
150
+ result = val[1]
151
+ }
152
+ | stmt kIF_MOD expr_value
153
+ {
154
+ result = new_if val[2], val[0], nil
155
+ }
156
+ | stmt kUNLESS_MOD expr_value
157
+ {
158
+ result = new_if val[2], nil, val[0]
159
+ }
160
+ | stmt kWHILE_MOD expr_value
161
+ {
162
+ result = new_while val[0], val[2], true
163
+ }
164
+ | stmt kUNTIL_MOD expr_value
165
+ {
166
+ result = new_until val[0], val[2], true
167
+ }
168
+ | stmt kRESCUE_MOD stmt
169
+ {
170
+ result = s(:rescue, val[0], new_resbody(s(:array), val[2]))
171
+ }
172
+ | klEND tLCURLY compstmt tRCURLY
173
+ {
174
+ if (self.in_def || self.in_single > 0) then
175
+ debug20 3
176
+ yyerror "END in method; use at_exit"
177
+ end
178
+ result = new_iter s(:postexe), 0, val[2]
179
+ }
180
+ | command_asgn
181
+ | mlhs tEQL command_call
182
+ {
183
+ result = new_masgn val[0], val[2], :wrap
184
+ }
185
+ | var_lhs tOP_ASGN command_call
186
+ {
187
+ result = new_op_asgn val
188
+ }
189
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_call
190
+ {
191
+ result = s(:op_asgn1, val[0], val[2], val[4].to_sym, val[5])
192
+ }
193
+ | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
194
+ {
195
+ result = s(:op_asgn, val[0], val[4], val[2].to_sym, val[3].to_sym)
196
+ }
197
+ | primary_value tDOT tCONSTANT tOP_ASGN command_call
198
+ {
199
+ result = s(:op_asgn, val[0], val[4], val[2].to_sym, val[3].to_sym)
200
+ }
201
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
202
+ {
203
+ result = s(:op_asgn, val[0], val[4], val[2], val[3])
204
+ debug20 4, val, result
205
+ }
206
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
207
+ {
208
+ result = s(:op_asgn, val[0], val[4], val[2], val[3])
209
+ debug20 5, val, result
210
+ }
211
+ | backref tOP_ASGN command_call
212
+ {
213
+ self.backref_assign_error val[0]
214
+ }
215
+ | lhs tEQL mrhs
216
+ {
217
+ result = self.node_assign val[0], s(:svalue, val[2])
218
+ }
219
+ #if defined(RUBY20)
220
+ | mlhs tEQL arg_value
221
+ {
222
+ result = new_masgn val[0], val[2], :wrap
223
+ }
224
+ | mlhs tEQL mrhs
225
+ #elif defined(RUBY21) || defined(RUBY22)
226
+ | mlhs tEQL mrhs_arg
227
+ #endif
228
+ {
229
+ result = new_masgn val[0], val[2]
230
+ }
231
+ | expr
232
+
233
+ command_asgn: lhs tEQL command_call
234
+ {
235
+ result = self.node_assign val[0], val[2]
236
+ }
237
+ | lhs tEQL command_asgn
238
+ {
239
+ result = self.node_assign val[0], val[2]
240
+ }
241
+
242
+ expr: command_call
243
+ | expr kAND expr
244
+ {
245
+ result = logop(:and, val[0], val[2])
246
+ }
247
+ | expr kOR expr
248
+ {
249
+ result = logop(:or, val[0], val[2])
250
+ }
251
+ | kNOT opt_nl expr
252
+ {
253
+ result = s(:call, val[2], :"!")
254
+ }
255
+ | tBANG command_call
256
+ {
257
+ result = s(:call, val[1], :"!")
258
+ }
259
+ | arg
260
+
261
+ expr_value: expr
262
+ {
263
+ result = value_expr(val[0])
264
+ }
265
+
266
+ command_call: command
267
+ | block_command
268
+
269
+ block_command: block_call
270
+ | block_call dot_or_colon operation2 command_args
271
+ {
272
+ result = new_call val[0], val[2].to_sym, val[3]
273
+ }
274
+
275
+ cmd_brace_block: tLBRACE_ARG
276
+ {
277
+ self.env.extend(:dynamic)
278
+ result = self.lexer.lineno
279
+ }
280
+ opt_block_param
281
+ {
282
+ result = nil # self.env.dynamic.keys
283
+ }
284
+ compstmt tRCURLY
285
+ {
286
+ result = new_iter nil, val[2], val[4]
287
+ result.line = val[1]
288
+
289
+ self.env.unextend
290
+ }
291
+
292
+ fcall: operation
293
+ {
294
+ result = new_call nil, val[0].to_sym
295
+ }
296
+
297
+ command: fcall command_args =tLOWEST
298
+ {
299
+ result = val[0].concat val[1][1..-1] # REFACTOR pattern
300
+ }
301
+ | fcall command_args cmd_brace_block
302
+ {
303
+ result = val[0].concat val[1][1..-1]
304
+ if val[2] then
305
+ block_dup_check result, val[2]
306
+
307
+ result, operation = val[2], result
308
+ result.insert 1, operation
309
+ end
310
+ }
311
+ | primary_value tDOT operation2 command_args =tLOWEST
312
+ {
313
+ result = new_call val[0], val[2].to_sym, val[3]
314
+ }
315
+ | primary_value tDOT operation2 command_args cmd_brace_block
316
+ {
317
+ recv, _, msg, args, block = val
318
+ call = new_call recv, msg.to_sym, args
319
+
320
+ block_dup_check call, block
321
+
322
+ block.insert 1, call
323
+ result = block
324
+ }
325
+ | primary_value tCOLON2 operation2 command_args =tLOWEST
326
+ {
327
+ result = new_call val[0], val[2].to_sym, val[3]
328
+ }
329
+ | primary_value tCOLON2 operation2 command_args cmd_brace_block
330
+ {
331
+ recv, _, msg, args, block = val
332
+ call = new_call recv, msg.to_sym, args
333
+
334
+ block_dup_check call, block
335
+
336
+ block.insert 1, call
337
+ result = block
338
+ }
339
+ | kSUPER command_args
340
+ {
341
+ result = new_super val[1]
342
+ }
343
+ | kYIELD command_args
344
+ {
345
+ result = new_yield val[1]
346
+ }
347
+ | kRETURN call_args
348
+ {
349
+ line = val[0].last
350
+ result = s(:return, ret_args(val[1])).line(line)
351
+ }
352
+ | kBREAK call_args
353
+ {
354
+ line = val[0].last
355
+ result = s(:break, ret_args(val[1])).line(line)
356
+ }
357
+ | kNEXT call_args
358
+ {
359
+ line = val[0].last
360
+ result = s(:next, ret_args(val[1])).line(line)
361
+ }
362
+
363
+ mlhs: mlhs_basic
364
+ | tLPAREN mlhs_inner rparen
365
+ {
366
+ result = val[1]
367
+ }
368
+
369
+ mlhs_inner: mlhs_basic
370
+ | tLPAREN mlhs_inner rparen
371
+ {
372
+ result = s(:masgn, s(:array, val[1]))
373
+ }
374
+
375
+ mlhs_basic: mlhs_head
376
+ {
377
+ result = s(:masgn, val[0])
378
+ }
379
+ | mlhs_head mlhs_item
380
+ {
381
+ result = s(:masgn, val[0] << val[1].compact)
382
+ }
383
+ | mlhs_head tSTAR mlhs_node
384
+ {
385
+ result = s(:masgn, val[0] << s(:splat, val[2]))
386
+ }
387
+ | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
388
+ {
389
+ ary1, _, splat, _, ary2 = val
390
+
391
+ result = list_append ary1, s(:splat, splat)
392
+ result.concat ary2[1..-1]
393
+ result = s(:masgn, result)
394
+ }
395
+ | mlhs_head tSTAR
396
+ {
397
+ result = s(:masgn, val[0] << s(:splat))
398
+ }
399
+ | mlhs_head tSTAR tCOMMA mlhs_post
400
+ {
401
+ ary = list_append val[0], s(:splat)
402
+ ary.concat val[3][1..-1]
403
+ result = s(:masgn, ary)
404
+ }
405
+ | tSTAR mlhs_node
406
+ {
407
+ result = s(:masgn, s(:array, s(:splat, val[1])))
408
+ }
409
+ | tSTAR mlhs_node tCOMMA mlhs_post
410
+ {
411
+ ary = s(:array, s(:splat, val[1]))
412
+ ary.concat val[3][1..-1]
413
+ result = s(:masgn, ary)
414
+ }
415
+ | tSTAR
416
+ {
417
+ result = s(:masgn, s(:array, s(:splat)))
418
+ }
419
+ | tSTAR tCOMMA mlhs_post
420
+ {
421
+ result = s(:masgn, s(:array, s(:splat), *val[2][1..-1]))
422
+ }
423
+
424
+ mlhs_item: mlhs_node
425
+ | tLPAREN mlhs_inner rparen
426
+ {
427
+ result = val[1]
428
+ }
429
+
430
+ mlhs_head: mlhs_item tCOMMA
431
+ {
432
+ result = s(:array, val[0])
433
+ }
434
+ | mlhs_head mlhs_item tCOMMA
435
+ {
436
+ result = val[0] << val[1].compact
437
+ }
438
+
439
+ mlhs_post: mlhs_item
440
+ {
441
+ result = s(:array, val[0])
442
+ }
443
+ | mlhs_post tCOMMA mlhs_item
444
+ {
445
+ result = list_append val[0], val[2]
446
+ }
447
+
448
+ mlhs_node: user_variable
449
+ {
450
+ result = self.assignable val[0]
451
+ }
452
+ | keyword_variable
453
+ {
454
+ result = self.assignable val[0]
455
+ }
456
+ | primary_value tLBRACK2 opt_call_args rbracket
457
+ {
458
+ result = self.aryset val[0], val[2]
459
+ }
460
+ | primary_value tDOT tIDENTIFIER
461
+ {
462
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
463
+ }
464
+ | primary_value tCOLON2 tIDENTIFIER
465
+ {
466
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
467
+ }
468
+ | primary_value tDOT tCONSTANT
469
+ {
470
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
471
+ }
472
+ | primary_value tCOLON2 tCONSTANT
473
+ {
474
+ if (self.in_def || self.in_single > 0) then
475
+ debug20 7
476
+ yyerror "dynamic constant assignment"
477
+ end
478
+
479
+ result = s(:const, s(:colon2, val[0], val[2].to_sym), nil)
480
+ }
481
+ | tCOLON3 tCONSTANT
482
+ {
483
+ if (self.in_def || self.in_single > 0) then
484
+ debug20 8
485
+ yyerror "dynamic constant assignment"
486
+ end
487
+
488
+ result = s(:const, nil, s(:colon3, val[1].to_sym))
489
+ }
490
+ | backref
491
+ {
492
+ self.backref_assign_error val[0]
493
+ }
494
+
495
+ lhs: user_variable
496
+ {
497
+ result = self.assignable val[0]
498
+ }
499
+ | keyword_variable
500
+ {
501
+ result = self.assignable val[0]
502
+ debug20 9, val, result
503
+ }
504
+ | primary_value tLBRACK2 opt_call_args rbracket
505
+ {
506
+ result = self.aryset val[0], val[2]
507
+ }
508
+ | primary_value tDOT tIDENTIFIER # REFACTOR
509
+ {
510
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
511
+ }
512
+ | primary_value tCOLON2 tIDENTIFIER
513
+ {
514
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
515
+ }
516
+ | primary_value tDOT tCONSTANT # REFACTOR?
517
+ {
518
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
519
+ }
520
+ | primary_value tCOLON2 tCONSTANT
521
+ {
522
+ if (self.in_def || self.in_single > 0) then
523
+ debug20 10
524
+ yyerror "dynamic constant assignment"
525
+ end
526
+
527
+ result = s(:const, s(:colon2, val[0], val[2].to_sym))
528
+ }
529
+ | tCOLON3 tCONSTANT
530
+ {
531
+ if (self.in_def || self.in_single > 0) then
532
+ debug20 11
533
+ yyerror "dynamic constant assignment"
534
+ end
535
+
536
+ result = s(:const, s(:colon3, val[1].to_sym))
537
+ }
538
+ | backref
539
+ {
540
+ self.backref_assign_error val[0]
541
+ }
542
+
543
+ cname: tIDENTIFIER
544
+ {
545
+ yyerror "class/module name must be CONSTANT"
546
+ }
547
+ | tCONSTANT
548
+
549
+ cpath: tCOLON3 cname
550
+ {
551
+ result = s(:colon3, val[1].to_sym)
552
+ }
553
+ | cname
554
+ {
555
+ result = val[0].to_sym
556
+ }
557
+ | primary_value tCOLON2 cname
558
+ {
559
+ result = s(:colon2, val[0], val[2].to_sym)
560
+ }
561
+
562
+ fname: tIDENTIFIER | tCONSTANT | tFID
563
+ | op
564
+ {
565
+ lexer.lex_state = :expr_end
566
+ result = val[0]
567
+ }
568
+
569
+ | reswords
570
+ {
571
+ lexer.lex_state = :expr_end
572
+ result = val[0]
573
+ }
574
+
575
+ fsym: fname | symbol
576
+
577
+ fitem: fsym
578
+ {
579
+ result = s(:lit, val[0].to_sym)
580
+ }
581
+ | dsym
582
+
583
+ undef_list: fitem
584
+ {
585
+ result = new_undef val[0]
586
+ }
587
+ |
588
+ undef_list tCOMMA
589
+ {
590
+ lexer.lex_state = :expr_fname
591
+ }
592
+ fitem
593
+ {
594
+ result = new_undef val[0], val[3]
595
+ }
596
+
597
+ op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
598
+ | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
599
+ | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
600
+ | tSTAR | tDIVIDE | tPERCENT | tPOW | tDSTAR | tBANG | tTILDE
601
+ | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
602
+ #if defined(RUBY20)
603
+ | tUBANG
604
+ #endif
605
+
606
+ reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
607
+ | kALIAS | kAND | kBEGIN | kBREAK | kCASE
608
+ | kCLASS | kDEF | kDEFINED | kDO | kELSE
609
+ | kELSIF | kEND | kENSURE | kFALSE | kFOR
610
+ | kIN | kMODULE | kNEXT | kNIL | kNOT
611
+ | kOR | kREDO | kRESCUE | kRETRY | kRETURN
612
+ | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
613
+ | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
614
+ | kUNTIL
615
+
616
+ arg: lhs tEQL arg
617
+ {
618
+ result = self.node_assign val[0], val[2]
619
+ }
620
+ | lhs tEQL arg kRESCUE_MOD arg
621
+ {
622
+ result = self.node_assign val[0], s(:rescue, val[2], new_resbody(s(:array), val[4]))
623
+ }
624
+ | var_lhs tOP_ASGN arg
625
+ {
626
+ result = new_op_asgn val
627
+ }
628
+ | var_lhs tOP_ASGN arg kRESCUE_MOD arg
629
+ {
630
+ result = new_op_asgn val
631
+ result = s(:rescue, result, new_resbody(s(:array), val[4]))
632
+ }
633
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg
634
+ {
635
+ val[2][0] = :arglist if val[2]
636
+ result = s(:op_asgn1, val[0], val[2], val[4].to_sym, val[5])
637
+ }
638
+ | primary_value tDOT tIDENTIFIER tOP_ASGN arg
639
+ {
640
+ result = s(:op_asgn2, val[0], :"#{val[2]}=", val[3].to_sym, val[4])
641
+ }
642
+ | primary_value tDOT tCONSTANT tOP_ASGN arg
643
+ {
644
+ result = s(:op_asgn2, val[0], :"#{val[2]}=", val[3].to_sym, val[4])
645
+ }
646
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
647
+ {
648
+ result = s(:op_asgn, val[0], val[4], val[2].to_sym, val[3].to_sym)
649
+ }
650
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
651
+ {
652
+ yyerror "constant re-assignment"
653
+ }
654
+ | tCOLON3 tCONSTANT tOP_ASGN arg
655
+ {
656
+ yyerror "constant re-assignment"
657
+ }
658
+ | backref tOP_ASGN arg
659
+ {
660
+ self.backref_assign_error val[0]
661
+ }
662
+ | arg tDOT2 arg
663
+ {
664
+ v1, v2 = val[0], val[2]
665
+ if v1.node_type == :lit and v2.node_type == :lit and Fixnum === v1.last and Fixnum === v2.last then
666
+ result = s(:lit, (v1.last)..(v2.last))
667
+ else
668
+ result = s(:dot2, v1, v2)
669
+ end
670
+ }
671
+ | arg tDOT3 arg
672
+ {
673
+ v1, v2 = val[0], val[2]
674
+ if v1.node_type == :lit and v2.node_type == :lit and Fixnum === v1.last and Fixnum === v2.last then
675
+ result = s(:lit, (v1.last)...(v2.last))
676
+ else
677
+ result = s(:dot3, v1, v2)
678
+ end
679
+ }
680
+ | arg tPLUS arg
681
+ {
682
+ result = new_call val[0], :+, argl(val[2])
683
+ }
684
+ | arg tMINUS arg
685
+ {
686
+ result = new_call val[0], :-, argl(val[2])
687
+ }
688
+ | arg tSTAR2 arg # TODO: rename
689
+ {
690
+ result = new_call val[0], :*, argl(val[2])
691
+ }
692
+ | arg tDIVIDE arg
693
+ {
694
+ result = new_call val[0], :"/", argl(val[2])
695
+ }
696
+ | arg tPERCENT arg
697
+ {
698
+ result = new_call val[0], :"%", argl(val[2])
699
+ }
700
+ | arg tPOW arg
701
+ {
702
+ result = new_call val[0], :**, argl(val[2])
703
+ }
704
+ #if defined(RUBY20)
705
+ | tUMINUS_NUM tINTEGER tPOW arg
706
+ {
707
+ result = new_call(new_call(s(:lit, val[1]), :"**", argl(val[3])), :"-@")
708
+ }
709
+ | tUMINUS_NUM tFLOAT tPOW arg
710
+ #elif defined(RUBY21) || defined(RUBY22)
711
+ | tUMINUS_NUM simple_numeric tPOW arg
712
+ #endif
713
+ {
714
+ result = new_call(new_call(s(:lit, val[1]), :"**", argl(val[3])), :"-@")
715
+ #if defined(RUBY20)
716
+ ## TODO: why is this 2.0 only?
717
+ debug20 12, val, result
718
+ #endif
719
+ }
720
+ | tUPLUS arg
721
+ {
722
+ result = new_call val[1], :"+@"
723
+ }
724
+ | tUMINUS arg
725
+ {
726
+ result = new_call val[1], :"-@"
727
+ }
728
+ | arg tPIPE arg
729
+ {
730
+ result = new_call val[0], :"|", argl(val[2])
731
+ }
732
+ | arg tCARET arg
733
+ {
734
+ result = new_call val[0], :"^", argl(val[2])
735
+ }
736
+ | arg tAMPER2 arg
737
+ {
738
+ result = new_call val[0], :"&", argl(val[2])
739
+ }
740
+ | arg tCMP arg
741
+ {
742
+ result = new_call val[0], :"<=>", argl(val[2])
743
+ }
744
+ | arg tGT arg
745
+ {
746
+ result = new_call val[0], :">", argl(val[2])
747
+ }
748
+ | arg tGEQ arg
749
+ {
750
+ result = new_call val[0], :">=", argl(val[2])
751
+ }
752
+ | arg tLT arg
753
+ {
754
+ result = new_call val[0], :"<", argl(val[2])
755
+ }
756
+ | arg tLEQ arg
757
+ {
758
+ result = new_call val[0], :"<=", argl(val[2])
759
+ }
760
+ | arg tEQ arg
761
+ {
762
+ result = new_call val[0], :"==", argl(val[2])
763
+ }
764
+ | arg tEQQ arg
765
+ {
766
+ result = new_call val[0], :"===", argl(val[2])
767
+ }
768
+ | arg tNEQ arg
769
+ {
770
+ result = new_call val[0], :"!=", argl(val[2])
771
+ }
772
+ | arg tMATCH arg
773
+ {
774
+ result = self.get_match_node val[0], val[2]
775
+ }
776
+ | arg tNMATCH arg
777
+ {
778
+ result = s(:not, self.get_match_node(val[0], val[2]))
779
+ }
780
+ | tBANG arg
781
+ {
782
+ result = new_call val[1], :"!"
783
+ }
784
+ | tTILDE arg
785
+ {
786
+ result = new_call value_expr(val[1]), :"~"
787
+ }
788
+ | arg tLSHFT arg
789
+ {
790
+ val[0] = value_expr val[0]
791
+ val[2] = value_expr val[2]
792
+ result = new_call val[0], :"\<\<", argl(val[2])
793
+ }
794
+ | arg tRSHFT arg
795
+ {
796
+ val[0] = value_expr val[0]
797
+ val[2] = value_expr val[2]
798
+ result = new_call val[0], :">>", argl(val[2])
799
+ }
800
+ | arg tANDOP arg
801
+ {
802
+ result = logop(:and, val[0], val[2])
803
+ }
804
+ | arg tOROP arg
805
+ {
806
+ result = logop(:or, val[0], val[2])
807
+ }
808
+ | kDEFINED opt_nl arg
809
+ {
810
+ result = s(:defined, val[2])
811
+ }
812
+ | arg tEH arg opt_nl tCOLON arg
813
+ {
814
+ result = s(:if, val[0], val[2], val[5])
815
+ }
816
+ | primary
817
+
818
+ arg_value: arg
819
+ {
820
+ result = value_expr(val[0])
821
+ }
822
+
823
+ aref_args: none
824
+ | args trailer
825
+ {
826
+ result = args [val[0]]
827
+ }
828
+ | args tCOMMA assocs trailer
829
+ {
830
+ result = args [val[0], array_to_hash(val[2])]
831
+ }
832
+ | assocs trailer
833
+ {
834
+ result = args [array_to_hash(val[0])]
835
+ }
836
+
837
+ paren_args: tLPAREN2 opt_call_args rparen
838
+ {
839
+ result = val[1]
840
+ }
841
+
842
+ opt_paren_args: none
843
+ | paren_args
844
+
845
+ opt_call_args: none
846
+ {
847
+ result = val[0]
848
+ }
849
+ | call_args
850
+ {
851
+ result = val[0]
852
+ }
853
+ | args tCOMMA
854
+ {
855
+ result = args val
856
+ }
857
+ | args tCOMMA assocs tCOMMA
858
+ {
859
+ result = args [val[0], array_to_hash(val[2])]
860
+ }
861
+ | assocs tCOMMA
862
+ {
863
+ result = args [array_to_hash(val[0])]
864
+ }
865
+
866
+ call_args: command
867
+ {
868
+ warning "parenthesize argument(s) for future version"
869
+ result = call_args val
870
+ }
871
+ | args opt_block_arg
872
+ {
873
+ result = call_args val
874
+ result = self.arg_blk_pass val[0], val[1]
875
+ }
876
+ | assocs opt_block_arg
877
+ {
878
+ result = call_args [array_to_hash(val[0])]
879
+ result = self.arg_blk_pass result, val[1]
880
+ }
881
+ | args tCOMMA assocs opt_block_arg
882
+ {
883
+ result = call_args [val[0], array_to_hash(val[2])]
884
+ result = self.arg_blk_pass result, val[3]
885
+ }
886
+ | block_arg
887
+ {
888
+ result = call_args val
889
+ }
890
+
891
+ command_args: {
892
+ result = lexer.cmdarg.stack.dup # TODO: smell?
893
+ lexer.cmdarg.push true
894
+ }
895
+ call_args
896
+ {
897
+ lexer.cmdarg.stack.replace val[0]
898
+ result = val[1]
899
+ }
900
+
901
+ block_arg: tAMPER arg_value
902
+ {
903
+ result = s(:block_pass, val[1])
904
+ }
905
+
906
+ opt_block_arg: tCOMMA block_arg
907
+ {
908
+ result = val[1]
909
+ }
910
+ | none
911
+
912
+ args: arg_value
913
+ {
914
+ result = s(:array, val[0])
915
+ }
916
+ | tSTAR arg_value
917
+ {
918
+ result = s(:array, s(:splat, val[1]))
919
+ }
920
+ | args tCOMMA arg_value
921
+ {
922
+ result = self.list_append val[0], val[2]
923
+ }
924
+ | args tCOMMA tSTAR arg_value
925
+ {
926
+ result = self.list_append val[0], s(:splat, val[3])
927
+ }
928
+
929
+ #if defined(RUBY21) || defined(RUBY22)
930
+ mrhs_arg: mrhs
931
+ {
932
+ result = new_masgn_arg val[0]
933
+ }
934
+ | arg_value
935
+ {
936
+ result = new_masgn_arg val[0], :wrap
937
+ }
938
+
939
+ #endif
940
+ mrhs: args tCOMMA arg_value
941
+ {
942
+ result = val[0] << val[2]
943
+ }
944
+ | args tCOMMA tSTAR arg_value
945
+ {
946
+ result = self.arg_concat val[0], val[3]
947
+ }
948
+ | tSTAR arg_value
949
+ {
950
+ result = s(:splat, val[1])
951
+ }
952
+
953
+ primary: literal
954
+ | strings
955
+ | xstring
956
+ | regexp
957
+ | words
958
+ | qwords
959
+ | symbols
960
+ | qsymbols
961
+ | var_ref
962
+ | backref
963
+ | tFID
964
+ {
965
+ result = new_call nil, val[0].to_sym
966
+ }
967
+ | kBEGIN
968
+ {
969
+ result = self.lexer.lineno
970
+ }
971
+ bodystmt kEND
972
+ {
973
+ unless val[2] then
974
+ result = s(:nil)
975
+ else
976
+ result = s(:begin, val[2])
977
+ end
978
+
979
+ result.line = val[1]
980
+ }
981
+ | tLPAREN_ARG rparen
982
+ {
983
+ debug20 13, val, result
984
+ }
985
+ | tLPAREN_ARG expr
986
+ {
987
+ lexer.lex_state = :expr_endarg
988
+ }
989
+ rparen
990
+ {
991
+ warning "(...) interpreted as grouped expression"
992
+ result = val[1]
993
+ }
994
+ | tLPAREN compstmt tRPAREN
995
+ {
996
+ result = val[1] || s(:nil)
997
+ result.paren = true
998
+ }
999
+ | primary_value tCOLON2 tCONSTANT
1000
+ {
1001
+ result = s(:colon2, val[0], val[2].to_sym)
1002
+ }
1003
+ | tCOLON3 tCONSTANT
1004
+ {
1005
+ result = s(:colon3, val[1].to_sym)
1006
+ }
1007
+ | tLBRACK aref_args tRBRACK
1008
+ {
1009
+ result = val[1] || s(:array)
1010
+ result[0] = :array # aref_args is :args
1011
+ }
1012
+ | tLBRACE assoc_list tRCURLY
1013
+ {
1014
+ result = s(:hash, *val[1].values) # TODO: array_to_hash?
1015
+ }
1016
+ | kRETURN
1017
+ {
1018
+ result = s(:return)
1019
+ }
1020
+ | kYIELD tLPAREN2 call_args rparen
1021
+ {
1022
+ result = new_yield val[2]
1023
+ }
1024
+ | kYIELD tLPAREN2 rparen
1025
+ {
1026
+ result = new_yield
1027
+ }
1028
+ | kYIELD
1029
+ {
1030
+ result = new_yield
1031
+ }
1032
+ | kDEFINED opt_nl tLPAREN2 expr rparen
1033
+ {
1034
+ result = s(:defined, val[3])
1035
+ }
1036
+ | kNOT tLPAREN2 expr rparen
1037
+ {
1038
+ result = s(:call, val[2], :"!")
1039
+ }
1040
+ | kNOT tLPAREN2 rparen
1041
+ {
1042
+ debug20 14, val, result
1043
+ }
1044
+ | fcall brace_block
1045
+ {
1046
+ oper, iter = val[0], val[1]
1047
+ call = oper # FIX
1048
+ iter.insert 1, call
1049
+ result = iter
1050
+ call.line = iter.line
1051
+ }
1052
+ | method_call
1053
+ | method_call brace_block
1054
+ {
1055
+ call, iter = val[0], val[1]
1056
+ block_dup_check call, iter
1057
+ iter.insert 1, call # FIX
1058
+ result = iter
1059
+ }
1060
+ | tLAMBDA lambda
1061
+ {
1062
+ result = val[1] # TODO: fix lineno
1063
+ }
1064
+ | kIF expr_value then compstmt if_tail kEND
1065
+ {
1066
+ result = new_if val[1], val[3], val[4]
1067
+ }
1068
+ | kUNLESS expr_value then compstmt opt_else kEND
1069
+ {
1070
+ result = new_if val[1], val[4], val[3]
1071
+ }
1072
+ | kWHILE
1073
+ {
1074
+ lexer.cond.push true
1075
+ }
1076
+ expr_value do
1077
+ {
1078
+ lexer.cond.pop
1079
+ }
1080
+ compstmt kEND
1081
+ {
1082
+ result = new_while val[5], val[2], true
1083
+ }
1084
+ | kUNTIL
1085
+ {
1086
+ lexer.cond.push true
1087
+ }
1088
+ expr_value do
1089
+ {
1090
+ lexer.cond.pop
1091
+ }
1092
+ compstmt kEND
1093
+ {
1094
+ result = new_until val[5], val[2], true
1095
+ }
1096
+ | kCASE expr_value opt_terms case_body kEND
1097
+ {
1098
+ (_, line), expr, _, body, _ = val
1099
+ result = new_case expr, body, line
1100
+ }
1101
+ | kCASE opt_terms case_body kEND
1102
+ {
1103
+ (_, line), _, body, _ = val
1104
+ result = new_case nil, body, line
1105
+ }
1106
+ | kFOR for_var kIN
1107
+ {
1108
+ lexer.cond.push true
1109
+ }
1110
+ expr_value do
1111
+ {
1112
+ lexer.cond.pop
1113
+ }
1114
+ compstmt kEND
1115
+ {
1116
+ result = new_for val[4], val[1], val[7]
1117
+ }
1118
+ | kCLASS
1119
+ {
1120
+ result = self.lexer.lineno
1121
+ }
1122
+ cpath superclass
1123
+ {
1124
+ self.comments.push self.lexer.comments
1125
+ if (self.in_def || self.in_single > 0) then
1126
+ yyerror "class definition in method body"
1127
+ end
1128
+ self.env.extend
1129
+ }
1130
+ bodystmt kEND
1131
+ {
1132
+ result = new_class val
1133
+ self.env.unextend
1134
+ self.lexer.comments # we don't care about comments in the body
1135
+ }
1136
+ | kCLASS tLSHFT
1137
+ {
1138
+ result = self.lexer.lineno
1139
+ }
1140
+ expr
1141
+ {
1142
+ result = self.in_def
1143
+ self.in_def = false
1144
+ }
1145
+ term
1146
+ {
1147
+ result = self.in_single
1148
+ self.in_single = 0
1149
+ self.env.extend
1150
+ }
1151
+ bodystmt kEND
1152
+ {
1153
+ result = new_sclass val
1154
+ self.env.unextend
1155
+ self.lexer.comments # we don't care about comments in the body
1156
+ }
1157
+ | kMODULE
1158
+ {
1159
+ result = self.lexer.lineno
1160
+ }
1161
+ cpath
1162
+ {
1163
+ self.comments.push self.lexer.comments
1164
+ yyerror "module definition in method body" if
1165
+ self.in_def or self.in_single > 0
1166
+
1167
+ self.env.extend
1168
+ }
1169
+ bodystmt kEND
1170
+ {
1171
+ result = new_module val
1172
+ self.env.unextend
1173
+ self.lexer.comments # we don't care about comments in the body
1174
+ }
1175
+ | kDEF fname
1176
+ {
1177
+ result = [self.in_def, self.lexer.cmdarg.stack.dup]
1178
+
1179
+ self.comments.push self.lexer.comments
1180
+ self.in_def = true
1181
+ self.env.extend
1182
+ # TODO: local->cmdargs = cmdarg_stack;
1183
+ # TODO: port local_push_gen and local_pop_gen
1184
+ lexer.cmdarg.stack.replace [false]
1185
+ }
1186
+ f_arglist bodystmt kEND
1187
+ {
1188
+ in_def, cmdarg = val[2]
1189
+
1190
+ result = new_defn val
1191
+
1192
+ lexer.cmdarg.stack.replace cmdarg
1193
+ self.env.unextend
1194
+ self.in_def = in_def
1195
+ self.lexer.comments # we don't care about comments in the body
1196
+ }
1197
+ | kDEF singleton dot_or_colon
1198
+ {
1199
+ self.comments.push self.lexer.comments
1200
+ lexer.lex_state = :expr_fname
1201
+ }
1202
+ fname
1203
+ {
1204
+ self.in_single += 1
1205
+ self.env.extend
1206
+ lexer.lex_state = :expr_end # force for args
1207
+ result = lexer.lineno
1208
+ }
1209
+ f_arglist bodystmt kEND
1210
+ {
1211
+ result = new_defs val
1212
+ result[3].line val[5]
1213
+
1214
+ self.env.unextend
1215
+ self.in_single -= 1
1216
+ self.lexer.comments # we don't care about comments in the body
1217
+ }
1218
+ | kBREAK
1219
+ {
1220
+ result = s(:break)
1221
+ }
1222
+ | kNEXT
1223
+ {
1224
+ result = s(:next)
1225
+ }
1226
+ | kREDO
1227
+ {
1228
+ result = s(:redo)
1229
+ }
1230
+ | kRETRY
1231
+ {
1232
+ result = s(:retry)
1233
+ }
1234
+
1235
+ primary_value: primary
1236
+ {
1237
+ result = value_expr(val[0])
1238
+ }
1239
+
1240
+ # These are really stupid
1241
+ k_begin: kBEGIN
1242
+ k_if: kIF
1243
+ k_unless: kUNLESS
1244
+ k_while: kWHILE
1245
+ k_until: kUNTIL
1246
+ k_case: kCASE
1247
+ k_for: kFOR
1248
+ k_class: kCLASS
1249
+ k_module: kMODULE
1250
+ k_def: kDEF
1251
+ k_end: kEND
1252
+
1253
+ then: term
1254
+ | kTHEN
1255
+ | term kTHEN
1256
+
1257
+ do: term
1258
+ | kDO_COND
1259
+
1260
+ if_tail: opt_else
1261
+ | kELSIF expr_value then compstmt if_tail
1262
+ {
1263
+ result = s(:if, val[1], val[3], val[4])
1264
+ }
1265
+
1266
+ opt_else: none
1267
+ | kELSE compstmt
1268
+ {
1269
+ result = val[1]
1270
+ }
1271
+
1272
+ for_var: lhs
1273
+ | mlhs
1274
+ {
1275
+ val[0].delete_at 1 if val[0][1].nil? # HACK
1276
+ }
1277
+
1278
+ f_marg: f_norm_arg
1279
+ | tLPAREN f_margs rparen
1280
+ {
1281
+ result = val[1]
1282
+ }
1283
+
1284
+ f_marg_list: f_marg
1285
+ {
1286
+ result = s(:array, val[0])
1287
+ }
1288
+ | f_marg_list tCOMMA f_marg
1289
+ {
1290
+ result = list_append val[0], val[2]
1291
+ }
1292
+
1293
+ f_margs: f_marg_list
1294
+ {
1295
+ args, = val
1296
+
1297
+ result = block_var args
1298
+ }
1299
+ | f_marg_list tCOMMA tSTAR f_norm_arg
1300
+ {
1301
+ args, _, _, splat = val
1302
+
1303
+ result = block_var args, "*#{splat}".to_sym
1304
+ }
1305
+ | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
1306
+ {
1307
+ args, _, _, splat, _, args2 = val
1308
+
1309
+ result = block_var args, "*#{splat}".to_sym, args2
1310
+ }
1311
+ | f_marg_list tCOMMA tSTAR
1312
+ {
1313
+ args, _, _ = val
1314
+
1315
+ result = block_var args, :*
1316
+ }
1317
+ | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
1318
+ {
1319
+ args, _, _, _, args2 = val
1320
+
1321
+ result = block_var args, :*, args2
1322
+ debug20 16, val, result
1323
+ }
1324
+ | tSTAR f_norm_arg
1325
+ {
1326
+ _, splat = val
1327
+
1328
+ result = block_var :"*#{splat}"
1329
+ }
1330
+ | tSTAR f_norm_arg tCOMMA f_marg_list
1331
+ {
1332
+ _, splat, _, args = val
1333
+
1334
+ result = block_var :"*#{splat}", args
1335
+ debug20 17, val, result
1336
+ }
1337
+ | tSTAR
1338
+ {
1339
+ result = block_var :*
1340
+ debug20 18, val, result
1341
+ }
1342
+ | tSTAR tCOMMA f_marg_list
1343
+ {
1344
+ _, _, args = val
1345
+
1346
+ result = block_var :*, args
1347
+ }
1348
+
1349
+ block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
1350
+ {
1351
+ result = call_args val
1352
+ }
1353
+ | f_block_kwarg opt_f_block_arg
1354
+ {
1355
+ result = call_args val
1356
+ }
1357
+ | f_kwrest opt_f_block_arg
1358
+ {
1359
+ result = call_args val
1360
+ }
1361
+ | f_block_arg
1362
+ {
1363
+ result = call_args val
1364
+ }
1365
+
1366
+ opt_block_args_tail: tCOMMA block_args_tail
1367
+ {
1368
+ result = args val
1369
+ }
1370
+ | none
1371
+
1372
+ block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
1373
+ {
1374
+ result = args val
1375
+ }
1376
+ | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1377
+ {
1378
+ result = args val
1379
+ }
1380
+ | f_arg tCOMMA f_block_optarg opt_block_args_tail
1381
+ {
1382
+ result = args val
1383
+ }
1384
+ | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_block_args_tail
1385
+ {
1386
+ result = args val
1387
+ }
1388
+ | f_arg tCOMMA f_rest_arg opt_block_args_tail
1389
+ {
1390
+ result = args val
1391
+ }
1392
+ | f_arg tCOMMA
1393
+ {
1394
+ result = args val
1395
+ }
1396
+ | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1397
+ {
1398
+ result = args val
1399
+ }
1400
+ | f_arg opt_block_args_tail
1401
+ {
1402
+ result = args val
1403
+ }
1404
+ | f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
1405
+ {
1406
+ result = args val
1407
+ }
1408
+ | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1409
+ {
1410
+ result = args val
1411
+ }
1412
+ | f_block_optarg opt_block_args_tail
1413
+ {
1414
+ result = args val
1415
+ }
1416
+ | f_block_optarg tCOMMA f_arg opt_block_args_tail
1417
+ {
1418
+ result = args val
1419
+ }
1420
+ | f_rest_arg opt_block_args_tail
1421
+ {
1422
+ result = args val
1423
+ }
1424
+ | f_rest_arg tCOMMA f_arg opt_block_args_tail
1425
+ {
1426
+ result = args val
1427
+ }
1428
+ | block_args_tail
1429
+ {
1430
+ result = args val
1431
+ }
1432
+
1433
+ opt_block_param: none { result = 0 }
1434
+ | block_param_def
1435
+
1436
+ block_param_def: tPIPE opt_bv_decl tPIPE
1437
+ {
1438
+ result = args val
1439
+ }
1440
+ | tOROP
1441
+ {
1442
+ self.lexer.command_start = true
1443
+ result = s(:args)
1444
+ }
1445
+ | tPIPE block_param opt_bv_decl tPIPE
1446
+ {
1447
+ result = args val
1448
+ }
1449
+
1450
+ opt_bv_decl: opt_nl
1451
+ | opt_nl tSEMI bv_decls opt_nl
1452
+ {
1453
+ result = args val
1454
+ }
1455
+
1456
+ bv_decls: bvar
1457
+ {
1458
+ result = args val
1459
+ }
1460
+ | bv_decls tCOMMA bvar
1461
+ {
1462
+ result = args val
1463
+ }
1464
+
1465
+ bvar: tIDENTIFIER
1466
+ {
1467
+ result = s(:shadow, val[0].to_sym)
1468
+ }
1469
+ | f_bad_arg
1470
+
1471
+ lambda: {
1472
+ self.env.extend :dynamic
1473
+ result = self.lexer.lineno
1474
+
1475
+ result = lexer.lpar_beg
1476
+ lexer.paren_nest += 1
1477
+ lexer.lpar_beg = lexer.paren_nest
1478
+ }
1479
+ f_larglist lambda_body
1480
+ {
1481
+ lpar, args, body = val
1482
+ lexer.lpar_beg = lpar
1483
+
1484
+ call = new_call nil, :lambda
1485
+ result = new_iter call, args, body
1486
+ self.env.unextend
1487
+ }
1488
+
1489
+ f_larglist: tLPAREN2 f_args opt_bv_decl rparen
1490
+ {
1491
+ result = args val
1492
+ }
1493
+ | f_args
1494
+ {
1495
+ result = val[0]
1496
+ result = 0 if result == s(:args)
1497
+ }
1498
+
1499
+ lambda_body: tLAMBEG compstmt tRCURLY
1500
+ {
1501
+ result = val[1]
1502
+ }
1503
+ | kDO_LAMBDA compstmt kEND
1504
+ {
1505
+ result = val[1]
1506
+ }
1507
+
1508
+ do_block: kDO_BLOCK
1509
+ {
1510
+ self.env.extend :dynamic
1511
+ result = self.lexer.lineno
1512
+ }
1513
+ opt_block_param
1514
+ {
1515
+ result = nil # self.env.dynamic.keys
1516
+ }
1517
+ compstmt kEND
1518
+ {
1519
+ args = val[2]
1520
+ body = val[4]
1521
+ result = new_iter nil, args, body
1522
+ result.line = val[1]
1523
+
1524
+ self.env.unextend
1525
+ }
1526
+
1527
+ block_call: command do_block
1528
+ {
1529
+ # TODO:
1530
+ ## if (nd_type($1) == NODE_YIELD) {
1531
+ ## compile_error(PARSER_ARG "block given to yield");
1532
+
1533
+ syntax_error "Both block arg and actual block given." if
1534
+ val[0].block_pass?
1535
+
1536
+ val = invert_block_call val if inverted? val
1537
+
1538
+ result = val[1]
1539
+ result.insert 1, val[0]
1540
+ }
1541
+ | block_call dot_or_colon operation2 opt_paren_args
1542
+ {
1543
+ result = new_call val[0], val[2].to_sym, val[3]
1544
+ }
1545
+ | block_call dot_or_colon operation2 opt_paren_args brace_block
1546
+ {
1547
+ iter1, _, name, args, iter2 = val
1548
+
1549
+ call = new_call iter1, name.to_sym, args
1550
+ iter2.insert 1, call
1551
+
1552
+ result = iter2
1553
+ }
1554
+ | block_call dot_or_colon operation2 command_args do_block
1555
+ {
1556
+ iter1, _, name, args, iter2 = val
1557
+
1558
+ call = new_call iter1, name.to_sym, args
1559
+ iter2.insert 1, call
1560
+
1561
+ result = iter2
1562
+ }
1563
+
1564
+ method_call: fcall
1565
+ {
1566
+ result = self.lexer.lineno
1567
+ }
1568
+ paren_args
1569
+ {
1570
+ args = self.call_args val[2..-1]
1571
+ result = val[0].concat args[1..-1]
1572
+ }
1573
+ | primary_value tDOT operation2 opt_paren_args
1574
+ {
1575
+ result = new_call val[0], val[2].to_sym, val[3]
1576
+ }
1577
+ | primary_value tCOLON2 operation2 paren_args
1578
+ {
1579
+ result = new_call val[0], val[2].to_sym, val[3]
1580
+ }
1581
+ | primary_value tCOLON2 operation3
1582
+ {
1583
+ result = new_call val[0], val[2].to_sym
1584
+ }
1585
+ | primary_value tDOT paren_args
1586
+ {
1587
+ result = new_call val[0], :call, val[2]
1588
+ }
1589
+ | primary_value tCOLON2 paren_args
1590
+ {
1591
+ result = new_call val[0], :call, val[2]
1592
+ }
1593
+ | kSUPER paren_args
1594
+ {
1595
+ result = new_super val[1]
1596
+ }
1597
+ | kSUPER
1598
+ {
1599
+ result = s(:zsuper)
1600
+ }
1601
+ | primary_value tLBRACK2 opt_call_args rbracket
1602
+ {
1603
+ result = new_aref val
1604
+ }
1605
+
1606
+ brace_block: tLCURLY
1607
+ {
1608
+ self.env.extend :dynamic
1609
+ result = self.lexer.lineno
1610
+ }
1611
+ opt_block_param
1612
+ {
1613
+ result = nil # self.env.dynamic.keys
1614
+ }
1615
+ compstmt tRCURLY
1616
+ {
1617
+ _, line, args, _, body, _ = val
1618
+
1619
+ result = new_iter nil, args, body
1620
+ result.line = line
1621
+
1622
+ self.env.unextend
1623
+ }
1624
+ | kDO
1625
+ {
1626
+ self.env.extend :dynamic
1627
+ result = self.lexer.lineno
1628
+ }
1629
+ opt_block_param
1630
+ {
1631
+ result = nil # self.env.dynamic.keys
1632
+ }
1633
+ compstmt kEND
1634
+ {
1635
+ _, line, args, _, body, _ = val
1636
+
1637
+ result = new_iter nil, args, body
1638
+ result.line = line
1639
+
1640
+ self.env.unextend
1641
+ }
1642
+
1643
+ case_body: kWHEN
1644
+ {
1645
+ result = self.lexer.lineno
1646
+ }
1647
+ args then compstmt cases
1648
+ {
1649
+ result = new_when(val[2], val[4])
1650
+ result.line = val[1]
1651
+ result << val[5] if val[5]
1652
+ }
1653
+
1654
+ cases: opt_else | case_body
1655
+
1656
+ opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
1657
+ {
1658
+ _, klasses, var, _, body, rest = val
1659
+
1660
+ klasses ||= s(:array)
1661
+ klasses << node_assign(var, s(:gvar, :"$!")) if var
1662
+
1663
+ result = new_resbody(klasses, body)
1664
+ result << rest if rest # UGH, rewritten above
1665
+ }
1666
+ |
1667
+ {
1668
+ result = nil
1669
+ }
1670
+
1671
+ exc_list: arg_value
1672
+ {
1673
+ result = s(:array, val[0])
1674
+ }
1675
+ | mrhs
1676
+ | none
1677
+
1678
+ exc_var: tASSOC lhs
1679
+ {
1680
+ result = val[1]
1681
+ }
1682
+ | none
1683
+
1684
+ opt_ensure: kENSURE compstmt
1685
+ {
1686
+ _, body = val
1687
+
1688
+ result = body || s(:nil)
1689
+ }
1690
+ | none
1691
+
1692
+ literal: numeric
1693
+ {
1694
+ result = s(:lit, val[0])
1695
+ }
1696
+ | symbol
1697
+ {
1698
+ result = s(:lit, val[0])
1699
+ }
1700
+ | dsym
1701
+
1702
+ strings: string
1703
+ {
1704
+ val[0] = s(:dstr, val[0].value) if val[0][0] == :evstr
1705
+ result = val[0]
1706
+ }
1707
+
1708
+ string: tCHAR
1709
+ {
1710
+ debug20 23, val, result
1711
+ }
1712
+ | string1
1713
+ | string string1
1714
+ {
1715
+ result = self.literal_concat val[0], val[1]
1716
+ }
1717
+
1718
+ string1: tSTRING_BEG string_contents tSTRING_END
1719
+ {
1720
+ result = val[1]
1721
+ }
1722
+ | tSTRING
1723
+ {
1724
+ result = new_string val
1725
+ }
1726
+
1727
+ xstring: tXSTRING_BEG xstring_contents tSTRING_END
1728
+ {
1729
+ result = new_xstring val[1]
1730
+ }
1731
+
1732
+ regexp: tREGEXP_BEG regexp_contents tREGEXP_END
1733
+ {
1734
+ result = new_regexp val
1735
+ }
1736
+
1737
+ words: tWORDS_BEG tSPACE tSTRING_END
1738
+ {
1739
+ result = s(:array)
1740
+ }
1741
+ | tWORDS_BEG word_list tSTRING_END
1742
+ {
1743
+ result = val[1]
1744
+ }
1745
+
1746
+ word_list: none
1747
+ {
1748
+ result = s(:array)
1749
+ }
1750
+ | word_list word tSPACE
1751
+ {
1752
+ word = val[1][0] == :evstr ? s(:dstr, "", val[1]) : val[1]
1753
+ result = val[0].dup << word
1754
+ }
1755
+
1756
+ word: string_content
1757
+ | word string_content
1758
+ {
1759
+ result = self.literal_concat val[0], val[1]
1760
+ }
1761
+
1762
+ symbols: tSYMBOLS_BEG tSPACE tSTRING_END
1763
+ {
1764
+ result = s(:array)
1765
+ }
1766
+ | tSYMBOLS_BEG symbol_list tSTRING_END
1767
+ {
1768
+ result = val[1]
1769
+ }
1770
+
1771
+ symbol_list: none
1772
+ {
1773
+ result = s(:array)
1774
+ }
1775
+ | symbol_list word tSPACE
1776
+ {
1777
+ list, sym, _ = val
1778
+
1779
+ case sym[0]
1780
+ when :dstr then
1781
+ sym[0] = :dsym
1782
+ when :str then
1783
+ sym = s(:lit, sym.last.to_sym)
1784
+ else
1785
+ debug20 24
1786
+ sym = s(:dsym, "", result)
1787
+ end
1788
+
1789
+ result = list.dup << sym
1790
+ }
1791
+
1792
+ qwords: tQWORDS_BEG tSPACE tSTRING_END
1793
+ {
1794
+ result = s(:array)
1795
+ }
1796
+ | tQWORDS_BEG qword_list tSTRING_END
1797
+ {
1798
+ result = val[1]
1799
+ }
1800
+
1801
+ qsymbols: tQSYMBOLS_BEG tSPACE tSTRING_END
1802
+ {
1803
+ result = s(:array)
1804
+ }
1805
+ | tQSYMBOLS_BEG qsym_list tSTRING_END
1806
+ {
1807
+ result = val[1]
1808
+ }
1809
+
1810
+ qword_list: none
1811
+ {
1812
+ result = s(:array)
1813
+ }
1814
+ | qword_list tSTRING_CONTENT tSPACE
1815
+ {
1816
+ result = val[0].dup << s(:str, val[1])
1817
+ }
1818
+
1819
+ qsym_list: none
1820
+ {
1821
+ result = s(:array)
1822
+ }
1823
+ | qsym_list tSTRING_CONTENT tSPACE
1824
+ {
1825
+ result = val[0].dup << s(:lit, val[1].to_sym)
1826
+ }
1827
+
1828
+ string_contents: none
1829
+ {
1830
+ result = s(:str, "")
1831
+ }
1832
+ | string_contents string_content
1833
+ {
1834
+ result = literal_concat(val[0], val[1])
1835
+ }
1836
+
1837
+ xstring_contents: none
1838
+ {
1839
+ result = nil
1840
+ }
1841
+ | xstring_contents string_content
1842
+ {
1843
+ result = literal_concat(val[0], val[1])
1844
+ }
1845
+
1846
+ regexp_contents: none
1847
+ {
1848
+ result = nil
1849
+ }
1850
+ | regexp_contents string_content
1851
+ {
1852
+ result = literal_concat(val[0], val[1])
1853
+ }
1854
+
1855
+ string_content: tSTRING_CONTENT
1856
+ {
1857
+ result = new_string val
1858
+ }
1859
+ | tSTRING_DVAR
1860
+ {
1861
+ result = lexer.lex_strterm
1862
+
1863
+ lexer.lex_strterm = nil
1864
+ lexer.lex_state = :expr_beg
1865
+ }
1866
+ string_dvar
1867
+ {
1868
+ lexer.lex_strterm = val[1]
1869
+ result = s(:evstr, val[2])
1870
+ }
1871
+ | tSTRING_DBEG
1872
+ {
1873
+ result = [lexer.lex_strterm,
1874
+ lexer.brace_nest,
1875
+ lexer.string_nest, # TODO: remove
1876
+ lexer.cond.store,
1877
+ lexer.cmdarg.store,
1878
+ lexer.lex_state,
1879
+ ]
1880
+
1881
+ lexer.lex_strterm = nil
1882
+ lexer.brace_nest = 0
1883
+ lexer.string_nest = 0
1884
+
1885
+ lexer.lex_state = :expr_beg
1886
+ }
1887
+ compstmt tRCURLY
1888
+ {
1889
+ #if defined(RUBY20)
1890
+ # TODO: tRCURLY -> tSTRING_DEND
1891
+ #elif defined(RUBY21) || defined(RUBY22)
1892
+ # TODO: tRCURLY -> tSTRING_END
1893
+ #endif
1894
+ _, memo, stmt, _ = val
1895
+
1896
+ lex_strterm, brace_nest, string_nest, oldcond, oldcmdarg, oldlex_state = memo
1897
+
1898
+ lexer.lex_strterm = lex_strterm
1899
+ lexer.brace_nest = brace_nest
1900
+ lexer.string_nest = string_nest
1901
+
1902
+ lexer.cond.restore oldcond
1903
+ lexer.cmdarg.restore oldcmdarg
1904
+
1905
+ lexer.lex_state = oldlex_state
1906
+
1907
+ case stmt
1908
+ when Sexp then
1909
+ case stmt[0]
1910
+ when :str, :dstr, :evstr then
1911
+ result = stmt
1912
+ else
1913
+ result = s(:evstr, stmt)
1914
+ end
1915
+ when nil then
1916
+ result = s(:evstr)
1917
+ else
1918
+ debug20 25
1919
+ raise "unknown string body: #{stmt.inspect}"
1920
+ end
1921
+ }
1922
+
1923
+ string_dvar: tGVAR { result = s(:gvar, val[0].to_sym) }
1924
+ | tIVAR { result = s(:ivar, val[0].to_sym) }
1925
+ | tCVAR { result = s(:cvar, val[0].to_sym) }
1926
+ | backref
1927
+
1928
+ symbol: tSYMBEG sym
1929
+ {
1930
+ lexer.lex_state = :expr_end
1931
+ result = val[1].to_sym
1932
+ }
1933
+ | tSYMBOL
1934
+ {
1935
+ result = val[0].to_sym
1936
+ }
1937
+
1938
+ sym: fname | tIVAR | tGVAR | tCVAR
1939
+
1940
+ dsym: tSYMBEG xstring_contents tSTRING_END
1941
+ {
1942
+ lexer.lex_state = :expr_end
1943
+ result = val[1]
1944
+
1945
+ result ||= s(:str, "")
1946
+
1947
+ case result[0]
1948
+ when :dstr then
1949
+ result[0] = :dsym
1950
+ when :str then
1951
+ result = s(:lit, result.last.to_sym)
1952
+ when :evstr then
1953
+ result = s(:dsym, "", result)
1954
+ else
1955
+ debug20 26, val, result
1956
+ end
1957
+ }
1958
+
1959
+ #if defined(RUBY20)
1960
+ numeric: tINTEGER
1961
+ | tFLOAT
1962
+ | tUMINUS_NUM tINTEGER =tLOWEST
1963
+ #elif defined(RUBY21) || defined(RUBY22)
1964
+ numeric: simple_numeric
1965
+ | tUMINUS_NUM simple_numeric
1966
+ #endif
1967
+ {
1968
+ result = -val[1] # TODO: pt_testcase
1969
+ #if defined(RUBY20)
1970
+ }
1971
+ | tUMINUS_NUM tFLOAT =tLOWEST
1972
+ {
1973
+ result = -val[1] # TODO: pt_testcase
1974
+ #endif
1975
+ }
1976
+
1977
+ #if defined(RUBY21) || defined(RUBY22)
1978
+ simple_numeric: tINTEGER
1979
+ | tFLOAT
1980
+ | tRATIONAL
1981
+ | tIMAGINARY
1982
+
1983
+ #endif
1984
+ user_variable: tIDENTIFIER
1985
+ | tIVAR
1986
+ | tGVAR
1987
+ | tCONSTANT
1988
+ | tCVAR
1989
+
1990
+ keyword_variable: kNIL { result = s(:nil) }
1991
+ | kSELF { result = s(:self) }
1992
+ | kTRUE { result = s(:true) }
1993
+ | kFALSE { result = s(:false) }
1994
+ | k__FILE__ { result = s(:str, self.file) }
1995
+ | k__LINE__ { result = s(:lit, lexer.lineno) }
1996
+ | k__ENCODING__
1997
+ {
1998
+ result =
1999
+ if defined? Encoding then
2000
+ s(:colon2, s(:const, :Encoding), :UTF_8)
2001
+ else
2002
+ s(:str, "Unsupported!")
2003
+ end
2004
+ }
2005
+
2006
+ var_ref: user_variable
2007
+ {
2008
+ var = val[0]
2009
+ result = Sexp === var ? var : self.gettable(var)
2010
+ }
2011
+ | keyword_variable
2012
+ {
2013
+ var = val[0]
2014
+ result = Sexp === var ? var : self.gettable(var)
2015
+ }
2016
+
2017
+ var_lhs: user_variable
2018
+ {
2019
+ result = self.assignable val[0]
2020
+ }
2021
+ | keyword_variable
2022
+ {
2023
+ result = self.assignable val[0]
2024
+ debug20 29, val, result
2025
+ }
2026
+
2027
+ backref: tNTH_REF { result = s(:nth_ref, val[0]) }
2028
+ | tBACK_REF { result = s(:back_ref, val[0]) }
2029
+
2030
+ superclass: term
2031
+ {
2032
+ result = nil
2033
+ }
2034
+ | tLT
2035
+ {
2036
+ lexer.lex_state = :expr_beg
2037
+ }
2038
+ expr_value term
2039
+ {
2040
+ result = val[2]
2041
+ }
2042
+ | error term
2043
+ {
2044
+ yyerrok
2045
+ result = nil
2046
+ debug20 30, val, result
2047
+ }
2048
+
2049
+ f_arglist: tLPAREN2 f_args rparen
2050
+ {
2051
+ result = val[1]
2052
+ self.lexer.lex_state = :expr_beg
2053
+ self.lexer.command_start = true
2054
+ # TODO:
2055
+ # $<num>$ = parser->parser_in_kwarg;
2056
+ # parser->parser_in_kwarg = 1;
2057
+ }
2058
+ | f_args term
2059
+ {
2060
+ # TODO: parser->parser_in_kwarg = $<num>1;
2061
+ result = val[0]
2062
+ self.lexer.lex_state = :expr_beg
2063
+ self.lexer.command_start = true
2064
+ }
2065
+
2066
+ args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
2067
+ {
2068
+ result = args val
2069
+ }
2070
+ | f_kwarg opt_f_block_arg
2071
+ {
2072
+ result = args val
2073
+ }
2074
+ | f_kwrest opt_f_block_arg
2075
+ {
2076
+ result = args val
2077
+ }
2078
+ | f_block_arg
2079
+
2080
+ opt_args_tail: tCOMMA args_tail
2081
+ {
2082
+ result = val[1]
2083
+ }
2084
+ |
2085
+ {
2086
+ result = nil
2087
+ }
2088
+
2089
+ f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_args_tail
2090
+ {
2091
+ result = args val
2092
+ }
2093
+ | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
2094
+ {
2095
+ result = args val
2096
+ }
2097
+ | f_arg tCOMMA f_optarg opt_args_tail
2098
+ {
2099
+ result = args val
2100
+ }
2101
+ | f_arg tCOMMA f_optarg tCOMMA f_arg opt_args_tail
2102
+ {
2103
+ result = args val
2104
+ }
2105
+ | f_arg tCOMMA f_rest_arg opt_args_tail
2106
+ {
2107
+ result = args val
2108
+ }
2109
+ | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
2110
+ {
2111
+ result = args val
2112
+ }
2113
+ | f_arg opt_args_tail
2114
+ {
2115
+ result = args val
2116
+ }
2117
+ | f_optarg tCOMMA f_rest_arg opt_args_tail
2118
+ {
2119
+ result = args val
2120
+ }
2121
+ | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
2122
+ {
2123
+ result = args val
2124
+ }
2125
+ | f_optarg opt_args_tail
2126
+ {
2127
+ result = args val
2128
+ }
2129
+ | f_optarg tCOMMA f_arg opt_args_tail
2130
+ {
2131
+ result = args val
2132
+ }
2133
+ | f_rest_arg opt_args_tail
2134
+ {
2135
+ result = args val
2136
+ }
2137
+ | f_rest_arg tCOMMA f_arg opt_args_tail
2138
+ {
2139
+ result = args val
2140
+ }
2141
+ | args_tail
2142
+ {
2143
+ result = args val
2144
+ }
2145
+ |
2146
+ {
2147
+ result = args val
2148
+ }
2149
+
2150
+ f_bad_arg: tCONSTANT
2151
+ {
2152
+ yyerror "formal argument cannot be a constant"
2153
+ }
2154
+ | tIVAR
2155
+ {
2156
+ yyerror "formal argument cannot be an instance variable"
2157
+ }
2158
+ | tGVAR
2159
+ {
2160
+ yyerror "formal argument cannot be a global variable"
2161
+ }
2162
+ | tCVAR
2163
+ {
2164
+ yyerror "formal argument cannot be a class variable"
2165
+ }
2166
+
2167
+ f_norm_arg: f_bad_arg
2168
+ | tIDENTIFIER
2169
+ {
2170
+ identifier = val[0].to_sym
2171
+ self.env[identifier] = :lvar
2172
+
2173
+ result = identifier
2174
+ }
2175
+
2176
+ #if defined(RUBY22)
2177
+ f_arg_asgn: f_norm_arg
2178
+
2179
+ f_arg_item: f_arg_asgn
2180
+ | tLPAREN f_margs rparen
2181
+ {
2182
+ result = val[1]
2183
+ }
2184
+ #else
2185
+ f_arg_item: f_norm_arg
2186
+ | tLPAREN f_margs rparen
2187
+ {
2188
+ result = val[1]
2189
+ }
2190
+ #endif
2191
+
2192
+ f_arg: f_arg_item
2193
+ {
2194
+ case val[0]
2195
+ when Symbol then
2196
+ result = s(:args)
2197
+ result << val[0]
2198
+ when Sexp then
2199
+ result = val[0]
2200
+ else
2201
+ debug20 32
2202
+ raise "Unknown f_arg type: #{val.inspect}"
2203
+ end
2204
+ }
2205
+ | f_arg tCOMMA f_arg_item
2206
+ {
2207
+ list, _, item = val
2208
+
2209
+ if list.sexp_type == :args then
2210
+ result = list
2211
+ else
2212
+ result = s(:args, list)
2213
+ end
2214
+
2215
+ result << item
2216
+ }
2217
+
2218
+ #if defined(RUBY20)
2219
+ f_kw: tLABEL arg_value
2220
+ #elif defined(RUBY21) || defined(RUBY22)
2221
+ f_label: tLABEL
2222
+
2223
+ f_kw: f_label arg_value
2224
+ #endif
2225
+ {
2226
+ # TODO: call_args
2227
+ label, _ = val[0] # TODO: fix lineno?
2228
+ identifier = label.to_sym
2229
+ self.env[identifier] = :lvar
2230
+
2231
+ result = s(:array, s(:kwarg, identifier, val[1]))
2232
+ }
2233
+ #if defined(RUBY21) || defined(RUBY22)
2234
+ | f_label
2235
+ {
2236
+ label, _ = val[0] # TODO: fix lineno?
2237
+ identifier = label.to_sym
2238
+ self.env[identifier] = :lvar
2239
+
2240
+ result = s(:array, s(:kwarg, identifier))
2241
+ }
2242
+ #endif
2243
+
2244
+ #if defined(RUBY20)
2245
+ f_block_kw: tLABEL primary_value
2246
+ #elif defined(RUBY21) || defined(RUBY22)
2247
+ f_block_kw: f_label primary_value
2248
+ #endif
2249
+ {
2250
+ # TODO: call_args
2251
+ label, _ = val[0] # TODO: fix lineno?
2252
+ identifier = label.to_sym
2253
+ self.env[identifier] = :lvar
2254
+
2255
+ result = s(:array, s(:kwarg, identifier, val[1]))
2256
+ }
2257
+ #if defined(RUBY21) || defined(RUBY22)
2258
+ | f_label
2259
+ {
2260
+ label, _ = val[0] # TODO: fix lineno?
2261
+ identifier = label.to_sym
2262
+ self.env[identifier] = :lvar
2263
+
2264
+ result = s(:array, s(:kwarg, identifier))
2265
+ }
2266
+ #endif
2267
+
2268
+ f_block_kwarg: f_block_kw
2269
+ | f_block_kwarg tCOMMA f_block_kw
2270
+ {
2271
+ list, _, item = val
2272
+ result = list << item.last
2273
+ }
2274
+
2275
+ f_kwarg: f_kw
2276
+ | f_kwarg tCOMMA f_kw
2277
+ {
2278
+ result = args val
2279
+ }
2280
+
2281
+ kwrest_mark: tPOW
2282
+ | tDSTAR
2283
+
2284
+ f_kwrest: kwrest_mark tIDENTIFIER
2285
+ {
2286
+ result = :"**#{val[1]}"
2287
+ }
2288
+ | kwrest_mark
2289
+ {
2290
+ debug20 36, val, result
2291
+ }
2292
+
2293
+ #if defined(RUBY20)
2294
+ f_opt: tIDENTIFIER tEQL arg_value
2295
+ #elif defined(RUBY21)
2296
+ f_opt: f_norm_arg tEQL arg_value
2297
+ #elif defined(RUBY22)
2298
+ f_opt: f_arg_asgn tEQL arg_value
2299
+ #endif
2300
+ {
2301
+ result = self.assignable val[0], val[2]
2302
+ # TODO: detect duplicate names
2303
+ }
2304
+
2305
+ #if defined(RUBY20)
2306
+ f_block_opt: tIDENTIFIER tEQL primary_value
2307
+ #elif defined(RUBY21)
2308
+ f_block_opt: f_norm_arg tEQL primary_value
2309
+ #elif defined(RUBY22)
2310
+ f_block_opt: f_arg_asgn tEQL primary_value
2311
+ #endif
2312
+ {
2313
+ result = self.assignable val[0], val[2]
2314
+ }
2315
+
2316
+ f_block_optarg: f_block_opt
2317
+ {
2318
+ result = s(:block, val[0])
2319
+ }
2320
+ | f_block_optarg tCOMMA f_block_opt
2321
+ {
2322
+ result = val[0]
2323
+ result << val[2]
2324
+ }
2325
+
2326
+ f_optarg: f_opt
2327
+ {
2328
+ result = s(:block, val[0])
2329
+ }
2330
+ | f_optarg tCOMMA f_opt
2331
+ {
2332
+ result = self.block_append val[0], val[2]
2333
+ }
2334
+
2335
+ restarg_mark: tSTAR2 | tSTAR
2336
+
2337
+ f_rest_arg: restarg_mark tIDENTIFIER
2338
+ {
2339
+ # TODO: differs from parse.y - needs tests
2340
+ name = val[1].to_sym
2341
+ self.assignable name
2342
+ result = :"*#{name}"
2343
+ }
2344
+ | restarg_mark
2345
+ {
2346
+ name = :"*"
2347
+ self.env[name] = :lvar
2348
+ result = name
2349
+ }
2350
+
2351
+ blkarg_mark: tAMPER2 | tAMPER
2352
+
2353
+ f_block_arg: blkarg_mark tIDENTIFIER
2354
+ {
2355
+ identifier = val[1].to_sym
2356
+
2357
+ self.env[identifier] = :lvar
2358
+ result = "&#{identifier}".to_sym
2359
+ }
2360
+
2361
+ opt_f_block_arg: tCOMMA f_block_arg
2362
+ {
2363
+ result = val[1]
2364
+ }
2365
+ |
2366
+ {
2367
+ result = nil
2368
+ }
2369
+
2370
+ singleton: var_ref
2371
+ | tLPAREN2
2372
+ {
2373
+ lexer.lex_state = :expr_beg
2374
+ }
2375
+ expr rparen
2376
+ {
2377
+ result = val[2]
2378
+ yyerror "Can't define single method for literals." if
2379
+ result[0] == :lit
2380
+ }
2381
+
2382
+ assoc_list: none # [!nil]
2383
+ {
2384
+ result = s(:array)
2385
+ }
2386
+ | assocs trailer # [!nil]
2387
+ {
2388
+ result = val[0]
2389
+ }
2390
+
2391
+ assocs: assoc
2392
+ | assocs tCOMMA assoc
2393
+ {
2394
+ list = val[0].dup
2395
+ more = val[2][1..-1]
2396
+ list.push(*more) unless more.empty?
2397
+ result = list
2398
+ result[0] = :hash
2399
+ # TODO: shouldn't this be a hash?
2400
+ }
2401
+
2402
+ assoc: arg_value tASSOC arg_value
2403
+ {
2404
+ result = s(:array, val[0], val[2])
2405
+ }
2406
+ | tLABEL arg_value
2407
+ {
2408
+ result = s(:array, s(:lit, val[0][0].to_sym), val[1])
2409
+ }
2410
+ #if defined(RUBY22)
2411
+ | tSTRING_BEG string_contents tLABEL_END arg_value
2412
+ {
2413
+ _, sym, _, value = val
2414
+ sym[0] = :dsym
2415
+ result = s(:array, sym, value)
2416
+ }
2417
+ | tSYMBOL arg_value
2418
+ {
2419
+ raise "not yet: #{val.inspect}"
2420
+ # result = s(:array, s(:lit, val[1].to_sym), val[1])
2421
+ }
2422
+ #endif
2423
+ | tDSTAR arg_value
2424
+ {
2425
+ result = s(:array, s(:kwsplat, val[1]))
2426
+ }
2427
+
2428
+ operation: tIDENTIFIER | tCONSTANT | tFID
2429
+ operation2: tIDENTIFIER | tCONSTANT | tFID | op
2430
+ operation3: tIDENTIFIER | tFID | op
2431
+ dot_or_colon: tDOT | tCOLON2
2432
+ opt_terms: | terms
2433
+ opt_nl: | tNL
2434
+ rparen: opt_nl tRPAREN
2435
+ rbracket: opt_nl tRBRACK
2436
+ trailer: | tNL | tCOMMA
2437
+
2438
+ term: tSEMI { yyerrok }
2439
+ | tNL
2440
+
2441
+ terms: term
2442
+ | terms tSEMI { yyerrok }
2443
+
2444
+ none: { result = nil; }
2445
+ end
2446
+
2447
+ ---- inner
2448
+
2449
+ require "ruby_lexer"
2450
+ require "ruby_parser_extras"
2451
+
2452
+ # :stopdoc:
2453
+
2454
+ # Local Variables: **
2455
+ # racc-token-length-max:14 **
2456
+ # End: **