brakeman 4.10.1 → 5.0.4

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