ruby_parser 3.14.2 → 3.15.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.
@@ -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