ruby_parser 3.6.6 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.
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: **