ruby_parser 3.14.2 → 3.15.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,12 +25,6 @@ class RubyLexer
25
25
 
26
26
  HAS_ENC = "".respond_to? :encoding
27
27
 
28
- IDENT_CHAR = if HAS_ENC then
29
- /[\w\u0080-\u{10ffff}]/u
30
- else
31
- /[\w\x80-\xFF]/n
32
- end
33
-
34
28
  TOKENS = {
35
29
  "!" => :tBANG,
36
30
  "!=" => :tNEQ,
@@ -162,7 +156,7 @@ class RubyLexer
162
156
  indent = func =~ STR_FUNC_INDENT ? "[ \t]*" : nil
163
157
  expand = func =~ STR_FUNC_EXPAND
164
158
  eol = last_line && last_line.end_with?("\r\n") ? "\r\n" : "\n"
165
- eos_re = /#{indent}#{Regexp.escape eos}(#{eol}|\z)/
159
+ eos_re = /#{indent}#{Regexp.escape eos}(\r*\n|\z)/
166
160
  err_msg = "can't match #{eos_re.inspect} anywhere in "
167
161
 
168
162
  rb_compile_error err_msg if end_of_stream?
@@ -177,10 +171,15 @@ class RubyLexer
177
171
 
178
172
  if expand then
179
173
  case
180
- when scan(/#[$@]/) then
181
- ss.pos -= 1 # FIX omg stupid
174
+ when scan(/#(?=\$(-.|[a-zA-Z_0-9~\*\$\?!@\/\\;,\.=:<>\"\&\`\'+]))/) then
175
+ # TODO: !ISASCII
176
+ # ?! see parser_peek_variable_name
177
+ return :tSTRING_DVAR, matched
178
+ when scan(/#(?=\@\@?[a-zA-Z_])/) then
179
+ # TODO: !ISASCII
182
180
  return :tSTRING_DVAR, matched
183
181
  when scan(/#[{]/) then
182
+ self.command_start = true
184
183
  return :tSTRING_DBEG, matched
185
184
  when scan(/#/) then
186
185
  string_buffer << "#"
@@ -320,6 +319,11 @@ class RubyLexer
320
319
  lpar_beg && lpar_beg == paren_nest
321
320
  end
322
321
 
322
+ def is_local_id id
323
+ # maybe just make this false for now
324
+ self.parser.env[id.to_sym] == :lvar # HACK: this isn't remotely right
325
+ end
326
+
323
327
  def lvar_defined? id
324
328
  # TODO: (dyna_in_block? && dvar_defined?(id)) || local_id?(id)
325
329
  self.parser.env[id.to_sym] == :lvar
@@ -338,9 +342,9 @@ class RubyLexer
338
342
 
339
343
  if scan(/[a-z0-9]{1,2}/i) then # Long-hand (e.g. %Q{}).
340
344
  rb_compile_error "unknown type of %string" if ss.matched_size == 2
341
- c, beg, short_hand = matched, ss.getch, false
345
+ c, beg, short_hand = matched, getch, false
342
346
  else # Short-hand (e.g. %{, %., %!, etc)
343
- c, beg, short_hand = "Q", ss.getch, true
347
+ c, beg, short_hand = "Q", getch, true
344
348
  end
345
349
 
346
350
  if end_of_stream? or c == RubyLexer::EOF or beg == RubyLexer::EOF then
@@ -457,7 +461,7 @@ class RubyLexer
457
461
  if text =~ check then
458
462
  content.gsub(ESC) { unescape $1 }
459
463
  else
460
- content.gsub(/\\\\/, "\\").gsub(/\\'/, "'")
464
+ content.gsub(/\\\\/, "\\").gsub(/\\\'/, "'")
461
465
  end
462
466
  end
463
467
 
@@ -495,16 +499,19 @@ class RubyLexer
495
499
  end
496
500
 
497
501
  def process_brace_close text
498
- # matching compare/parse23.y:8561
499
- cond.lexpop
500
- cmdarg.lexpop
501
-
502
502
  case matched
503
503
  when "}" then
504
504
  self.brace_nest -= 1
505
- self.lex_state = ruby24minus? ? EXPR_ENDARG : EXPR_END
506
-
507
505
  return :tSTRING_DEND, matched if brace_nest < 0
506
+ end
507
+
508
+ # matching compare/parse26.y:8099
509
+ cond.pop
510
+ cmdarg.pop
511
+
512
+ case matched
513
+ when "}" then
514
+ self.lex_state = ruby24minus? ? EXPR_ENDARG : EXPR_END
508
515
  return :tRCURLY, matched
509
516
  when "]" then
510
517
  self.paren_nest -= 1
@@ -605,7 +612,7 @@ class RubyLexer
605
612
  end
606
613
 
607
614
  def process_label text
608
- symbol = possibly_escape_string text, /^"/
615
+ symbol = possibly_escape_string text, /^\"/
609
616
 
610
617
  result EXPR_LAB, :tLABEL, [symbol, self.lineno]
611
618
  end
@@ -619,7 +626,7 @@ class RubyLexer
619
626
  text = text[0..-2]
620
627
  end
621
628
 
622
- result EXPR_END, :tSTRING, text[1..-2].gsub(/\\\\/, "\\").gsub(/\\'/, "'")
629
+ result EXPR_END, :tSTRING, text[1..-2].gsub(/\\\\/, "\\").gsub(/\\\'/, "\'")
623
630
  end
624
631
 
625
632
  def process_lchevron text
@@ -791,12 +798,22 @@ class RubyLexer
791
798
  c = if scan(/\\/) then
792
799
  self.read_escape
793
800
  else
794
- ss.getch
801
+ getch
795
802
  end
796
803
 
797
804
  result EXPR_END, :tSTRING, c
798
805
  end
799
806
 
807
+ def process_simple_string text
808
+ replacement = text[1..-2].gsub(ESC) {
809
+ unescape($1).b.force_encoding Encoding::UTF_8
810
+ }
811
+
812
+ replacement = replacement.b unless replacement.valid_encoding?
813
+
814
+ result EXPR_END, :tSTRING, replacement
815
+ end
816
+
800
817
  def process_slash text
801
818
  if is_beg? then
802
819
  string STR_REGEXP
@@ -870,16 +887,16 @@ class RubyLexer
870
887
 
871
888
  if [:tSTRING_END, :tREGEXP_END, :tLABEL_END].include? token_type then
872
889
  self.lex_strterm = nil
873
- self.lex_state = (token_type == :tLABEL_END) ? EXPR_PAR : EXPR_END|EXPR_ENDARG
890
+ self.lex_state = (token_type == :tLABEL_END) ? EXPR_PAR : EXPR_LIT
874
891
  end
875
892
 
876
893
  return token
877
894
  end
878
895
 
879
896
  def process_symbol text
880
- symbol = possibly_escape_string text, /^:"/
897
+ symbol = possibly_escape_string text, /^:\"/ # stupid emacs
881
898
 
882
- result EXPR_END|EXPR_ENDARG, :tSYMBOL, symbol
899
+ result EXPR_LIT, :tSYMBOL, symbol
883
900
  end
884
901
 
885
902
  def process_token text
@@ -928,6 +945,8 @@ class RubyLexer
928
945
  EXPR_END
929
946
  end
930
947
 
948
+ tok_id = :tIDENTIFIER if tok_id == :tCONSTANT && is_local_id(token)
949
+
931
950
  if last_state !~ EXPR_DOT|EXPR_FNAME and
932
951
  (tok_id == :tIDENTIFIER) and # not EXPR_FNAME, not attrasgn
933
952
  lvar_defined?(token) then
@@ -951,18 +970,16 @@ class RubyLexer
951
970
  self.command_start = true if lex_state =~ EXPR_BEG
952
971
 
953
972
  case
954
- when keyword.id0 == :kDO then
973
+ when keyword.id0 == :kDO then # parse26.y line 7591
955
974
  case
956
975
  when lambda_beginning? then
957
976
  self.lpar_beg = nil # lambda_beginning? == FALSE in the body of "-> do ... end"
958
- self.paren_nest -= 1
977
+ self.paren_nest -= 1 # TODO: question this?
959
978
  result lex_state, :kDO_LAMBDA, value
960
979
  when cond.is_in_state then
961
980
  result lex_state, :kDO_COND, value
962
981
  when cmdarg.is_in_state && state != EXPR_CMDARG then
963
982
  result lex_state, :kDO_BLOCK, value
964
- when state =~ EXPR_BEG|EXPR_ENDARG then
965
- result lex_state, :kDO_BLOCK, value
966
983
  else
967
984
  result lex_state, :kDO, value
968
985
  end
@@ -979,9 +996,9 @@ class RubyLexer
979
996
  ss.unscan # put back "_"
980
997
 
981
998
  if beginning_of_line? && scan(/\__END__(\r?\n|\Z)/) then
982
- return [RubyLexer::EOF, RubyLexer::EOF]
983
- elsif scan(/\_\w*/) then
984
- return process_token matched
999
+ [RubyLexer::EOF, RubyLexer::EOF]
1000
+ elsif scan(/#{IDENT_CHAR}+/) then
1001
+ process_token matched
985
1002
  end
986
1003
  end
987
1004
 
@@ -1018,7 +1035,7 @@ class RubyLexer
1018
1035
  when scan(/x([0-9a-fA-F]{1,2})/) then # hex constant
1019
1036
  # TODO: force encode everything to UTF-8?
1020
1037
  ss[1].to_i(16).chr.force_encoding Encoding::UTF_8
1021
- when check(/M-\\[\\MCc]/) then
1038
+ when check(/M-\\./) then
1022
1039
  scan(/M-\\/) # eat it
1023
1040
  c = self.read_escape
1024
1041
  c[0] = (c[0].ord | 0x80).chr
@@ -1032,6 +1049,11 @@ class RubyLexer
1032
1049
  c = self.read_escape
1033
1050
  c[0] = (c[0].ord & 0x9f).chr
1034
1051
  c
1052
+ when check(/(C-|c)\\(?!u|\\)/) then
1053
+ scan(/(C-|c)\\/) # eat it
1054
+ c = read_escape
1055
+ c[0] = (c[0].ord & 0x9f).chr
1056
+ c
1035
1057
  when scan(/C-\?|c\?/) then
1036
1058
  127.chr
1037
1059
  when scan(/(C-|c)(.)/) then
@@ -1040,17 +1062,25 @@ class RubyLexer
1040
1062
  c
1041
1063
  when scan(/^[89]/i) then # bad octal or hex... MRI ignores them :(
1042
1064
  matched
1043
- when scan(/u([0-9a-fA-F]{4}|\{[0-9a-fA-F]{2,6}\})/) then
1044
- [ss[1].delete("{}").to_i(16)].pack("U")
1045
- when scan(/u([0-9a-fA-F]{1,3})/) then
1065
+ when scan(/u(\h{4})/) then
1066
+ [ss[1].to_i(16)].pack("U")
1067
+ when scan(/u(\h{1,3})/) then
1046
1068
  rb_compile_error "Invalid escape character syntax"
1069
+ when scan(/u\{(\h+(?:\s+\h+)*)\}/) then
1070
+ ss[1].split.map { |s| s.to_i(16) }.pack("U*")
1047
1071
  when scan(/[McCx0-9]/) || end_of_stream? then
1048
1072
  rb_compile_error("Invalid escape character syntax")
1049
1073
  else
1050
- ss.getch
1074
+ getch
1051
1075
  end.dup
1052
1076
  end
1053
1077
 
1078
+ def getch
1079
+ c = ss.getch
1080
+ c = ss.getch if c == "\r" && ss.peek(1) == "\n"
1081
+ c
1082
+ end
1083
+
1054
1084
  def regx_options # TODO: rewrite / remove
1055
1085
  good, bad = [], []
1056
1086
 
@@ -1274,10 +1304,12 @@ class RubyLexer
1274
1304
  s
1275
1305
  when /^[McCx0-9]/ then
1276
1306
  rb_compile_error("Invalid escape character syntax")
1277
- when /u([0-9a-fA-F]{4}|\{[0-9a-fA-F]{2,6}\})/ then
1307
+ when /u(\h{4})/ then
1278
1308
  [$1.delete("{}").to_i(16)].pack("U")
1279
- when /u([0-9a-fA-F]{1,3})/ then
1309
+ when /u(\h{1,3})/ then
1280
1310
  rb_compile_error("Invalid escape character syntax")
1311
+ when /u\{(\h+(?:\s+\h+)*)\}/ then
1312
+ $1.split.map { |s| s.to_i(16) }.pack("U*")
1281
1313
  else
1282
1314
  s
1283
1315
  end
@@ -1355,11 +1387,11 @@ class RubyLexer
1355
1387
  # extra fake lex_state names to make things a bit cleaner
1356
1388
 
1357
1389
  EXPR_LAB = EXPR_ARG|EXPR_LABELED
1358
- EXPR_NUM = EXPR_END|EXPR_ENDARG
1390
+ EXPR_LIT = EXPR_END|EXPR_ENDARG
1359
1391
  EXPR_PAR = EXPR_BEG|EXPR_LABEL
1360
1392
  EXPR_PAD = EXPR_BEG|EXPR_LABELED
1361
1393
 
1362
- EXPR_LIT = EXPR_NUM # TODO: migrate to EXPR_LIT
1394
+ EXPR_NUM = EXPR_LIT
1363
1395
 
1364
1396
  expr_names.merge!(EXPR_NONE => "EXPR_NONE",
1365
1397
  EXPR_BEG => "EXPR_BEG",
@@ -6,9 +6,9 @@ class RubyLexer
6
6
 
7
7
  macro
8
8
 
9
- IDENT /^#{IDENT_CHAR}+/o
9
+ IDENT_CHAR /[a-zA-Z0-9_[:^ascii:]]/
10
10
 
11
- ESC /\\((?>[0-7]{1,3}|x[0-9a-fA-F]{1,2}|M-[^\\]|(C-|c)[^\\]|u[0-9a-fA-F]{1,4}|u\{[0-9a-fA-F]+\}|[^0-7xMCc]))/
11
+ ESC /\\((?>[0-7]{1,3}|x\h{1,2}|M-[^\\]|(C-|c)[^\\]|u\h{1,4}|u\{\h+(?:\s+\h+)*\}|[^0-7xMCc]))/
12
12
  SIMPLE_STRING /((#{ESC}|\#(#{ESC}|[^\{\#\@\$\"\\])|[^\"\\\#])*)/o
13
13
  SSTRING /((\\.|[^\'])*)/
14
14
 
@@ -62,7 +62,7 @@ rule
62
62
  | /\=(?=begin\b)/ { result arg_state, TOKENS[text], text }
63
63
 
64
64
  ruby22_label? /\"#{SIMPLE_STRING}\":/o process_label
65
- /\"(#{SIMPLE_STRING})\"/o { result EXPR_END, :tSTRING, text[1..-2].gsub(ESC) { unescape $1 } }
65
+ /\"(#{SIMPLE_STRING})\"/o process_simple_string
66
66
  /\"/ { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
67
67
 
68
68
  /\@\@?\d/ { rb_compile_error "`#{text}` is not allowed as a variable name" }
@@ -164,13 +164,12 @@ was_label? /\'#{SSTRING}\':?/o process_label_or_string
164
164
  | in_fname? /\$([1-9]\d*)/ process_gvar
165
165
  | /\$([1-9]\d*)/ process_nthref
166
166
  | /\$0/ process_gvar
167
- | /\$[^[:ascii:]]+/ process_gvar
167
+ | /\$#{IDENT_CHAR}+/ process_gvar
168
168
  | /\$\W|\$\z/ process_gvar_oddity
169
- | /\$\w+/ process_gvar
170
169
 
171
170
  /\_/ process_underscore
172
171
 
173
- /#{IDENT}/o process_token
172
+ /#{IDENT_CHAR}+/o process_token
174
173
 
175
174
  /\004|\032|\000|\Z/ { [RubyLexer::EOF, RubyLexer::EOF] }
176
175
 
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
  #--
3
3
  # This file is automatically generated. Do not modify it.
4
- # Generated by: oedipus_lex version 2.5.1.
4
+ # Generated by: oedipus_lex version 2.5.2.
5
5
  # Source: lib/ruby_lexer.rex
6
6
  #++
7
7
 
@@ -16,8 +16,8 @@ class RubyLexer
16
16
  require 'strscan'
17
17
 
18
18
  # :stopdoc:
19
- IDENT = /^#{IDENT_CHAR}+/o
20
- ESC = /\\((?>[0-7]{1,3}|x[0-9a-fA-F]{1,2}|M-[^\\]|(C-|c)[^\\]|u[0-9a-fA-F]{1,4}|u\{[0-9a-fA-F]+\}|[^0-7xMCc]))/
19
+ IDENT_CHAR = /[a-zA-Z0-9_[:^ascii:]]/
20
+ ESC = /\\((?>[0-7]{1,3}|x\h{1,2}|M-[^\\]|(C-|c)[^\\]|u\h{1,4}|u\{\h+(?:\s+\h+)*\}|[^0-7xMCc]))/
21
21
  SIMPLE_STRING = /((#{ESC}|\#(#{ESC}|[^\{\#\@\$\"\\])|[^\"\\\#])*)/o
22
22
  SSTRING = /((\\.|[^\'])*)/
23
23
  INT_DEC = /[+]?(?:(?:[1-9][\d_]*|0)(?!\.\d)(ri|r|i)?\b|0d[0-9_]+)(ri|r|i)?/i
@@ -160,7 +160,7 @@ class RubyLexer
160
160
  when ruby22_label? && (text = ss.scan(/\"#{SIMPLE_STRING}\":/o)) then
161
161
  process_label text
162
162
  when text = ss.scan(/\"(#{SIMPLE_STRING})\"/o) then
163
- action { result EXPR_END, :tSTRING, text[1..-2].gsub(ESC) { unescape $1 } }
163
+ process_simple_string text
164
164
  when text = ss.scan(/\"/) then
165
165
  action { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
166
166
  when text = ss.scan(/\@\@?\d/) then
@@ -328,16 +328,14 @@ class RubyLexer
328
328
  process_nthref text
329
329
  when text = ss.scan(/\$0/) then
330
330
  process_gvar text
331
- when text = ss.scan(/\$[^[:ascii:]]+/) then
331
+ when text = ss.scan(/\$#{IDENT_CHAR}+/) then
332
332
  process_gvar text
333
333
  when text = ss.scan(/\$\W|\$\z/) then
334
334
  process_gvar_oddity text
335
- when text = ss.scan(/\$\w+/) then
336
- process_gvar text
337
335
  end # group /\$/
338
336
  when text = ss.scan(/\_/) then
339
337
  process_underscore text
340
- when text = ss.scan(/#{IDENT}/o) then
338
+ when text = ss.scan(/#{IDENT_CHAR}+/o) then
341
339
  process_token text
342
340
  when ss.skip(/\004|\032|\000|\Z/) then
343
341
  action { [RubyLexer::EOF, RubyLexer::EOF] }
@@ -78,10 +78,12 @@ require "ruby23_parser"
78
78
  require "ruby24_parser"
79
79
  require "ruby25_parser"
80
80
  require "ruby26_parser"
81
+ require "ruby27_parser"
81
82
 
82
83
  class RubyParser # HACK
83
84
  VERSIONS.clear # also a HACK caused by racc namespace issues
84
85
 
86
+ class V27 < ::Ruby27Parser; end
85
87
  class V26 < ::Ruby26Parser; end
86
88
  class V25 < ::Ruby25Parser; end
87
89
  class V24 < ::Ruby24Parser; end
@@ -14,6 +14,8 @@ class Ruby24Parser
14
14
  class Ruby25Parser
15
15
  #elif V == 26
16
16
  class Ruby26Parser
17
+ #elif V == 27
18
+ class Ruby27Parser
17
19
  #else
18
20
  fail "version not specified or supported on code generation"
19
21
  #endif
@@ -286,13 +288,15 @@ rule
286
288
  }
287
289
  | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
288
290
  {
289
- result = s(:op_asgn, val[0], val[4], val[2], val[3])
290
- debug20 4, val, result
291
+ lhs1, _, lhs2, op, rhs = val
292
+
293
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, op.to_sym)
291
294
  }
292
295
  | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
293
296
  {
294
- result = s(:op_asgn, val[0], val[4], val[2], val[3])
295
- debug20 5, val, result
297
+ lhs1, _, lhs2, op, rhs = val
298
+
299
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, op.to_sym)
296
300
  }
297
301
  | backref tOP_ASGN command_rhs
298
302
  {
@@ -1078,12 +1082,39 @@ rule
1078
1082
  }
1079
1083
 
1080
1084
  command_args: {
1081
- result = lexer.cmdarg.store true
1085
+ # parse26.y line 2200
1086
+
1087
+ # If call_args starts with a open paren '(' or
1088
+ # '[', look-ahead reading of the letters calls
1089
+ # CMDARG_PUSH(0), but the push must be done
1090
+ # after CMDARG_PUSH(1). So this code makes them
1091
+ # consistent by first cancelling the premature
1092
+ # CMDARG_PUSH(0), doing CMDARG_PUSH(1), and
1093
+ # finally redoing CMDARG_PUSH(0).
1094
+
1095
+ result = yychar = self.last_token_type.first
1096
+ lookahead = [:tLPAREN, :tLPAREN_ARG, :tLPAREN2, :tLBRACK, :tLBRACK2].include?(yychar)
1097
+ lexer.cmdarg.pop if lookahead
1098
+ lexer.cmdarg.push true
1099
+ lexer.cmdarg.push false if lookahead
1082
1100
  }
1083
1101
  call_args
1084
1102
  {
1085
- lexer.cmdarg.restore val[0]
1086
- result = val[1]
1103
+ yychar, args = val
1104
+
1105
+ # call_args can be followed by tLBRACE_ARG (that
1106
+ # does CMDARG_PUSH(0) in the lexer) but the push
1107
+ # must be done after CMDARG_POP() in the parser.
1108
+ # So this code does CMDARG_POP() to pop 0 pushed
1109
+ # by tLBRACE_ARG, CMDARG_POP() to pop 1 pushed
1110
+ # by command_args, and CMDARG_PUSH(0) to restore
1111
+ # back the flag set by tLBRACE_ARG.
1112
+
1113
+ lookahead = [:tLBRACE_ARG].include?(yychar)
1114
+ lexer.cmdarg.pop if lookahead
1115
+ lexer.cmdarg.pop
1116
+ lexer.cmdarg.push false if lookahead
1117
+ result = args
1087
1118
  }
1088
1119
 
1089
1120
  block_arg: tAMPER arg_value
@@ -1101,8 +1132,9 @@ rule
1101
1132
  args: arg_value
1102
1133
  {
1103
1134
  arg, = val
1135
+ lineno = arg.line || lexer.lineno # HACK
1104
1136
 
1105
- result = s(:array, arg).line arg.line
1137
+ result = s(:array, arg).line lineno
1106
1138
  }
1107
1139
  | tSTAR arg_value
1108
1140
  {
@@ -1114,9 +1146,11 @@ rule
1114
1146
  args, _, id = val
1115
1147
  result = self.list_append args, id
1116
1148
  }
1117
- | args tCOMMA tSTAR { result = lexer.lineno } arg_value
1149
+ | args tCOMMA tSTAR arg_value
1118
1150
  {
1119
- args, _, _, line, id = val
1151
+ # TODO: the line number from tSTAR has been dropped
1152
+ args, _, _, id = val
1153
+ line = lexer.lineno
1120
1154
  result = self.list_append args, s(:splat, id).line(line)
1121
1155
  }
1122
1156
 
@@ -1137,7 +1171,6 @@ rule
1137
1171
  }
1138
1172
  | args tCOMMA tSTAR arg_value
1139
1173
  {
1140
- # FIX: bad shift/reduce conflict with rhs' comma star prod
1141
1174
  # TODO: make all tXXXX terminals include lexer.lineno
1142
1175
  arg, _, _, splat = val
1143
1176
  result = self.arg_concat arg, splat
@@ -1165,21 +1198,13 @@ rule
1165
1198
  }
1166
1199
  | k_begin
1167
1200
  {
1201
+ lexer.cmdarg.push false
1168
1202
  result = self.lexer.lineno
1169
- # TODO:
1170
- # $<val>1 = cmdarg_stack;
1171
- # CMDARG_SET(0);
1172
1203
  }
1173
1204
  bodystmt k_end
1174
1205
  {
1175
- # TODO: CMDARG_SET($<val>1);
1176
- unless val[2] then
1177
- result = s(:nil)
1178
- else
1179
- result = s(:begin, val[2])
1180
- end
1181
-
1182
- result.line = val[1]
1206
+ lexer.cmdarg.pop
1207
+ result = new_begin val
1183
1208
  }
1184
1209
  | tLPAREN_ARG
1185
1210
  {
@@ -1192,18 +1217,14 @@ rule
1192
1217
  result = s(:begin).line line
1193
1218
  }
1194
1219
  | tLPAREN_ARG
1195
- {
1196
- result = lexer.cmdarg.store false
1197
- }
1198
1220
  stmt
1199
1221
  {
1200
1222
  lexer.lex_state = EXPR_ENDARG
1201
1223
  }
1202
1224
  rparen
1203
1225
  {
1204
- _, cmdarg, stmt, _, _, = val
1205
- warning "(...) interpreted as grouped expression"
1206
- lexer.cmdarg.restore cmdarg
1226
+ _, stmt, _, _, = val
1227
+ # warning "(...) interpreted as grouped expression"
1207
1228
  result = stmt
1208
1229
  }
1209
1230
  | tLPAREN compstmt tRPAREN
@@ -1386,48 +1407,61 @@ rule
1386
1407
  }
1387
1408
  | k_def fname
1388
1409
  {
1389
- result = [self.in_def, self.lexer.cmdarg.stack.dup]
1410
+ result = self.in_def
1390
1411
 
1391
- self.comments.push self.lexer.comments
1392
- self.in_def = true
1412
+ self.in_def = true # group = local_push
1393
1413
  self.env.extend
1394
- # TODO: local->cmdargs = cmdarg_stack;
1395
- # TODO: port local_push_gen and local_pop_gen
1396
- lexer.cmdarg.stack.replace [false]
1414
+ lexer.cmdarg.push false
1415
+ lexer.cond.push false
1416
+
1417
+ self.comments.push self.lexer.comments
1397
1418
  }
1398
1419
  f_arglist bodystmt { result = lexer.lineno } k_end
1399
1420
  {
1400
- in_def, cmdarg = val[2]
1421
+ in_def = val[2]
1401
1422
 
1402
1423
  result = new_defn val
1403
1424
 
1404
- lexer.cmdarg.stack.replace cmdarg
1425
+ lexer.cond.pop # group = local_pop
1426
+ lexer.cmdarg.pop
1405
1427
  self.env.unextend
1406
1428
  self.in_def = in_def
1429
+
1407
1430
  self.lexer.comments # we don't care about comments in the body
1408
1431
  }
1409
1432
  | k_def singleton dot_or_colon
1410
1433
  {
1411
- self.comments.push self.lexer.comments
1412
1434
  lexer.lex_state = EXPR_FNAME
1413
1435
  }
1414
1436
  fname
1415
1437
  {
1416
- self.in_single += 1
1438
+ result = [self.in_def, lexer.lineno]
1439
+
1440
+ self.in_single += 1 # TODO: remove?
1441
+
1442
+ self.in_def = true # local_push
1417
1443
  self.env.extend
1418
- lexer.lex_state = EXPR_ENDFN # force for args
1419
- result = [lexer.lineno, self.lexer.cmdarg.stack.dup]
1420
- lexer.cmdarg.stack.replace [false]
1444
+ lexer.cmdarg.push false
1445
+ lexer.cond.push false
1446
+
1447
+ lexer.lex_state = EXPR_ENDFN|EXPR_LABEL
1448
+ self.comments.push self.lexer.comments
1421
1449
  }
1422
1450
  f_arglist bodystmt k_end
1423
1451
  {
1424
- _, cmdarg = val[5]
1425
- result = new_defs val
1452
+ _, _recv, _, _, _name, (in_def, _lineno), _args, _body, _ = val
1426
1453
 
1427
- lexer.cmdarg.stack.replace cmdarg
1454
+ result = new_defs val
1428
1455
 
1456
+ lexer.cond.pop # group = local_pop
1457
+ lexer.cmdarg.pop
1429
1458
  self.env.unextend
1459
+ self.in_def = in_def
1460
+
1430
1461
  self.in_single -= 1
1462
+
1463
+ # TODO: restore cur_arg ? what's cur_arg?
1464
+
1431
1465
  self.lexer.comments # we don't care about comments in the body
1432
1466
  }
1433
1467
  | kBREAK
@@ -1712,20 +1746,19 @@ opt_block_args_tail: tCOMMA block_args_tail
1712
1746
  }
1713
1747
  f_larglist
1714
1748
  {
1715
- result = lexer.cmdarg.store(false)
1749
+ lexer.cmdarg.push false
1716
1750
  }
1717
1751
  lambda_body
1718
1752
  {
1719
- (line, lpar), args, cmdarg, body = val
1753
+ (line, lpar), args, _cmdarg, body = val
1720
1754
  lexer.lpar_beg = lpar
1721
1755
 
1722
- lexer.cmdarg.restore cmdarg
1723
- lexer.cmdarg.lexpop
1756
+ lexer.cmdarg.pop
1724
1757
 
1725
1758
  call = s(:lambda).line line
1726
1759
  result = new_iter call, args, body
1727
1760
  result.line = line
1728
- self.env.unextend
1761
+ self.env.unextend # TODO: dynapush & dynapop
1729
1762
  }
1730
1763
 
1731
1764
  f_larglist: tLPAREN2 f_args opt_bv_decl rparen
@@ -1878,7 +1911,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1878
1911
  }
1879
1912
 
1880
1913
  do_body: { self.env.extend :dynamic; result = self.lexer.lineno }
1881
- { result = lexer.cmdarg.store(false) }
1914
+ { lexer.cmdarg.push false }
1882
1915
  opt_block_param
1883
1916
  #if V >= 25
1884
1917
  bodystmt
@@ -1886,11 +1919,11 @@ opt_block_args_tail: tCOMMA block_args_tail
1886
1919
  compstmt
1887
1920
  #endif
1888
1921
  {
1889
- line, cmdarg, param, cmpstmt = val
1922
+ line, _cmdarg, param, cmpstmt = val
1890
1923
 
1891
1924
  result = new_do_body param, cmpstmt, line
1925
+ lexer.cmdarg.pop
1892
1926
  self.env.unextend
1893
- lexer.cmdarg.restore cmdarg
1894
1927
  }
1895
1928
 
1896
1929
  case_body: k_when
@@ -1990,7 +2023,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1990
2023
 
1991
2024
  xstring: tXSTRING_BEG xstring_contents tSTRING_END
1992
2025
  {
1993
- result = new_xstring val[1]
2026
+ result = new_xstring val
1994
2027
  # TODO: dedent?!?! SERIOUSLY?!?
1995
2028
  }
1996
2029
 
@@ -2132,12 +2165,13 @@ regexp_contents: none
2132
2165
  result = [lexer.lex_strterm,
2133
2166
  lexer.brace_nest,
2134
2167
  lexer.string_nest, # TODO: remove
2135
- lexer.cond.store,
2136
- lexer.cmdarg.store,
2137
2168
  lexer.lex_state,
2138
2169
  lexer.lineno,
2139
2170
  ]
2140
2171
 
2172
+ lexer.cmdarg.push false
2173
+ lexer.cond.push false
2174
+
2141
2175
  lexer.lex_strterm = nil
2142
2176
  lexer.brace_nest = 0
2143
2177
  lexer.string_nest = 0
@@ -2149,14 +2183,15 @@ regexp_contents: none
2149
2183
  {
2150
2184
  _, memo, stmt, _ = val
2151
2185
 
2152
- lex_strterm, brace_nest, string_nest, oldcond, oldcmdarg, oldlex_state, line = memo
2186
+ lex_strterm, brace_nest, string_nest, oldlex_state, line = memo
2187
+ # TODO: heredoc_indent
2153
2188
 
2154
2189
  lexer.lex_strterm = lex_strterm
2155
2190
  lexer.brace_nest = brace_nest
2156
2191
  lexer.string_nest = string_nest
2157
2192
 
2158
- lexer.cond.restore oldcond
2159
- lexer.cmdarg.restore oldcmdarg
2193
+ lexer.cmdarg.pop
2194
+ lexer.cond.pop
2160
2195
 
2161
2196
  lexer.lex_state = oldlex_state
2162
2197