racc 1.4.14 → 1.4.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +5 -5
  2. data/Manifest.txt +50 -0
  3. data/ext/racc/com/headius/racc/Cparse.java +66 -23
  4. data/ext/racc/cparse.c +1 -1
  5. data/ext/racc/depend +1 -1
  6. data/lib/racc/info.rb +2 -2
  7. data/test/assets/bibtex.y +141 -0
  8. data/test/assets/cadenza.y +170 -0
  9. data/test/assets/cast.y +926 -0
  10. data/test/assets/csspool.y +729 -0
  11. data/test/assets/edtf.y +583 -0
  12. data/test/assets/huia.y +318 -0
  13. data/test/assets/journey.y +47 -0
  14. data/test/assets/liquor.y +313 -0
  15. data/test/assets/machete.y +423 -0
  16. data/test/assets/macruby.y +2197 -0
  17. data/test/assets/mediacloth.y +599 -0
  18. data/test/assets/mof.y +649 -0
  19. data/test/assets/namae.y +302 -0
  20. data/test/assets/nasl.y +626 -0
  21. data/test/assets/nokogiri-css.y +255 -0
  22. data/test/assets/opal.y +1807 -0
  23. data/test/assets/php_serialization.y +98 -0
  24. data/test/assets/rdblockparser.y +576 -0
  25. data/test/assets/rdinlineparser.y +561 -0
  26. data/test/assets/riml.y +665 -0
  27. data/test/assets/ruby18.y +1943 -0
  28. data/test/assets/ruby19.y +2174 -0
  29. data/test/assets/ruby20.y +2350 -0
  30. data/test/assets/ruby21.y +2359 -0
  31. data/test/assets/ruby22.y +2381 -0
  32. data/test/assets/tp_plus.y +622 -0
  33. data/test/assets/twowaysql.y +278 -0
  34. data/test/helper.rb +31 -15
  35. data/test/regress/bibtex +474 -0
  36. data/test/regress/cadenza +796 -0
  37. data/test/regress/cast +3425 -0
  38. data/test/regress/csspool +2318 -0
  39. data/test/regress/edtf +1794 -0
  40. data/test/regress/huia +1392 -0
  41. data/test/regress/journey +222 -0
  42. data/test/regress/liquor +885 -0
  43. data/test/regress/machete +833 -0
  44. data/test/regress/mediacloth +1463 -0
  45. data/test/regress/mof +1368 -0
  46. data/test/regress/namae +634 -0
  47. data/test/regress/nasl +2058 -0
  48. data/test/regress/nokogiri-css +836 -0
  49. data/test/regress/opal +6429 -0
  50. data/test/regress/php_serialization +336 -0
  51. data/test/regress/rdblockparser +1061 -0
  52. data/test/regress/rdinlineparser +1243 -0
  53. data/test/regress/riml +3297 -0
  54. data/test/regress/ruby18 +6351 -0
  55. data/test/regress/ruby22 +7456 -0
  56. data/test/regress/tp_plus +1933 -0
  57. data/test/regress/twowaysql +556 -0
  58. data/test/test_racc_command.rb +177 -0
  59. metadata +75 -20
@@ -0,0 +1,665 @@
1
+ # Copyright (c) 2012-2014 by Luke Gruber
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included
12
+ # in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ class Riml::Parser
23
+
24
+ token IF ELSE ELSEIF THEN UNLESS END
25
+ token WHILE UNTIL BREAK CONTINUE
26
+ token TRY CATCH FINALLY
27
+ token FOR IN
28
+ token DEF DEF_BANG SPLAT_PARAM SPLAT_ARG CALL BUILTIN_COMMAND # such as echo "hi"
29
+ token CLASS NEW DEFM DEFM_BANG SUPER
30
+ token RIML_FILE_COMMAND RIML_CLASS_COMMAND
31
+ token RETURN
32
+ token NEWLINE
33
+ token NUMBER
34
+ token STRING_D STRING_S # single- and double-quoted
35
+ token EX_LITERAL
36
+ token REGEXP
37
+ token TRUE FALSE
38
+ token LET UNLET UNLET_BANG IDENTIFIER
39
+ token DICT_VAL # like dict.key, 'key' is a DICT_VAL
40
+ token SCOPE_MODIFIER SCOPE_MODIFIER_LITERAL SPECIAL_VAR_PREFIX
41
+ token FINISH
42
+
43
+ prechigh
44
+ right '!'
45
+ left '*' '/' '%'
46
+ left '+' '-' '.'
47
+ left '>' '>#' '>?' '<' '<#' '<?' '>=' '>=#' '>=?' '<=' '<=#' '<=?'
48
+ left '==' '==?' '==#' '=~' '=~?' '=~#' '!~' '!~?' '!~#' '!=' '!=?' '!=#'
49
+ left IS ISNOT
50
+ left '&&'
51
+ left '||'
52
+ right '?'
53
+ right '=' '+=' '-=' '.='
54
+ left ','
55
+ left IF UNLESS
56
+ preclow
57
+
58
+ # All rules
59
+ rule
60
+
61
+ Root:
62
+ /* nothing */ { result = make_node(val) { |_| Riml::Nodes.new([]) } }
63
+ | Terminator { result = make_node(val) { |_| Riml::Nodes.new([]) } }
64
+ | Statements { result = val[0] }
65
+ ;
66
+
67
+ # any list of expressions
68
+ Statements:
69
+ Statement { result = make_node(val) { |v| Riml::Nodes.new([ v[0] ]) } }
70
+ | Statements Terminator Statement { result = val[0] << val[2] }
71
+ | Statements Terminator { result = val[0] }
72
+ | Terminator Statements { result = make_node(val) { |v| Riml::Nodes.new(v[1]) } }
73
+ ;
74
+
75
+ # All types of expressions in Riml
76
+ Statement:
77
+ ExplicitCall { result = val[0] }
78
+ | Def { result = val[0] }
79
+ | Return { result = val[0] }
80
+ | UnletVariable { result = val[0] }
81
+ | ExLiteral { result = val[0] }
82
+ | For { result = val[0] }
83
+ | While { result = val[0] }
84
+ | Until { result = val[0] }
85
+ | Try { result = val[0] }
86
+ | ClassDefinition { result = val[0] }
87
+ | LoopKeyword { result = val[0] }
88
+ | EndScript { result = val[0] }
89
+ | RimlFileCommand { result = val[0] }
90
+ | RimlClassCommand { result = val[0] }
91
+ | MultiAssign { result = val[0] }
92
+ | If { result = val[0] }
93
+ | Unless { result = val[0] }
94
+ | Expression { result = val[0] }
95
+ ;
96
+
97
+ Expression:
98
+ ExpressionWithoutDictLiteral { result = val[0] }
99
+ | Dictionary { result = val[0] }
100
+ | Dictionary DictGetWithDotLiteral { result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) } }
101
+ | BinaryOperator { result = val[0] }
102
+ | Ternary { result = val[0] }
103
+ | Assign { result = val[0] }
104
+ | Super { result = val[0] }
105
+ | '(' Expression ')' { result = make_node(val) { |v| Riml::WrapInParensNode.new(v[1]) } }
106
+ ;
107
+
108
+ ExpressionWithoutDictLiteral:
109
+ UnaryOperator { result = val[0] }
110
+ | DictGet { result = val[0] }
111
+ | ListOrDictGet { result = val[0] }
112
+ | AllVariableRetrieval { result = val[0] }
113
+ | LiteralWithoutDictLiteral { result = val[0] }
114
+ | Call { result = val[0] }
115
+ | ObjectInstantiation { result = val[0] }
116
+ | '(' ExpressionWithoutDictLiteral ')' { result = make_node(val) { |v| Riml::WrapInParensNode.new(v[1]) } }
117
+ ;
118
+
119
+ # for inside curly-brace variable names
120
+ PossibleStringValue:
121
+ String { result = val[0] }
122
+ | DictGet { result = val[0] }
123
+ | ListOrDictGet { result = val[0] }
124
+ | AllVariableRetrieval { result = val[0] }
125
+ | BinaryOperator { result = val[0] }
126
+ | Ternary { result = val[0] }
127
+ | Call { result = val[0] }
128
+ ;
129
+
130
+ Terminator:
131
+ NEWLINE { result = nil }
132
+ | ';' { result = nil }
133
+ ;
134
+
135
+ LiteralWithoutDictLiteral:
136
+ Number { result = val[0] }
137
+ | String { result = val[0] }
138
+ | Regexp { result = val[0] }
139
+ | List { result = val[0] }
140
+ | ScopeModifierLiteral { result = val[0] }
141
+ | TRUE { result = make_node(val) { |_| Riml::TrueNode.new } }
142
+ | FALSE { result = make_node(val) { |_| Riml::FalseNode.new } }
143
+ ;
144
+
145
+ Number:
146
+ NUMBER { result = make_node(val) { |v| Riml::NumberNode.new(v[0]) } }
147
+ ;
148
+
149
+ String:
150
+ STRING_S { result = make_node(val) { |v| Riml::StringNode.new(v[0], :s) } }
151
+ | STRING_D { result = make_node(val) { |v| Riml::StringNode.new(v[0], :d) } }
152
+ | String STRING_S { result = make_node(val) { |v| Riml::StringLiteralConcatNode.new(v[0], Riml::StringNode.new(v[1], :s)) } }
153
+ | String STRING_D { result = make_node(val) { |v| Riml::StringLiteralConcatNode.new(v[0], Riml::StringNode.new(v[1], :d)) } }
154
+ ;
155
+
156
+ Regexp:
157
+ REGEXP { result = make_node(val) { |v| Riml::RegexpNode.new(v[0]) } }
158
+ ;
159
+
160
+ ScopeModifierLiteral:
161
+ SCOPE_MODIFIER_LITERAL { result = make_node(val) { |v| Riml::ScopeModifierLiteralNode.new(v[0]) } }
162
+ ;
163
+
164
+ List:
165
+ ListLiteral { result = make_node(val) { |v| Riml::ListNode.new(v[0]) } }
166
+ ;
167
+
168
+ ListUnpack:
169
+ '[' ListItems ';' Expression ']' { result = make_node(val) { |v| Riml::ListUnpackNode.new(v[1] << v[3]) } }
170
+ ;
171
+
172
+ ListLiteral:
173
+ '[' ListItems ']' { result = val[1] }
174
+ | '[' ListItems ',' ']' { result = val[1] }
175
+ ;
176
+
177
+ ListItems:
178
+ /* nothing */ { result = [] }
179
+ | Expression { result = [val[0]] }
180
+ | ListItems ',' Expression { result = val[0] << val[2] }
181
+ ;
182
+
183
+ Dictionary:
184
+ DictionaryLiteral { result = make_node(val) { |v| Riml::DictionaryNode.new(v[0]) } }
185
+ ;
186
+
187
+ # {'key': 'value', 'key2': 'value2'}
188
+ # Save as [['key', 'value'], ['key2', 'value2']] because ruby-1.8.7 offers
189
+ # no guarantee for key-value pair ordering.
190
+ DictionaryLiteral:
191
+ '{' DictItems '}' { result = val[1] }
192
+ | '{' DictItems ',' '}' { result = val[1] }
193
+ ;
194
+
195
+ # [[key, value], [key, value]]
196
+ DictItems:
197
+ /* nothing */ { result = [] }
198
+ | DictItem { result = val }
199
+ | DictItems ',' DictItem { result = val[0] << val[2] }
200
+ ;
201
+
202
+ # [key, value]
203
+ DictItem:
204
+ Expression ':' Expression { result = [val[0], val[2]] }
205
+ ;
206
+
207
+ DictGet:
208
+ AllVariableRetrieval DictGetWithDot { result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) } }
209
+ | ListOrDictGet DictGetWithDot { result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) } }
210
+ | Call DictGetWithDot { result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) } }
211
+ | '(' Expression ')' DictGetWithDot { result = make_node(val) { |v| Riml::DictGetDotNode.new(Riml::WrapInParensNode.new(v[1]), v[3]) } }
212
+ ;
213
+
214
+ ListOrDictGet:
215
+ ExpressionWithoutDictLiteral ListOrDictGetWithBrackets { result = make_node(val) { |v| Riml::ListOrDictGetNode.new(v[0], v[1]) } }
216
+ | '(' Expression ')' ListOrDictGetWithBrackets { result = make_node(val) { |v| Riml::ListOrDictGetNode.new(Riml::WrapInParensNode.new(v[1]), v[3]) } }
217
+ ;
218
+
219
+ ListOrDictGetAssign:
220
+ ExpressionWithoutDictLiteral ListOrDictGetWithBrackets { result = make_node(val) { |v| Riml::ListOrDictGetNode.new(v[0], v[1]) } }
221
+ ;
222
+
223
+ ListOrDictGetWithBrackets:
224
+ '[' Expression ']' { result = [val[1]] }
225
+ | '[' SubList ']' { result = [val[1]] }
226
+ | ListOrDictGetWithBrackets '[' Expression ']' { result = val[0] << val[2] }
227
+ | ListOrDictGetWithBrackets '[' SubList ']' { result = val[0] << val[2] }
228
+ ;
229
+
230
+ SubList:
231
+ Expression ':' Expression { result = make_node(val) { |v| Riml::SublistNode.new([v[0], Riml::LiteralNode.new(' : '), v[2]]) } }
232
+ | Expression ':' { result = make_node(val) { |v| Riml::SublistNode.new([v[0], Riml::LiteralNode.new(' :')]) } }
233
+ | ':' Expression { result = make_node(val) { |v| Riml::SublistNode.new([Riml::LiteralNode.new(': '), v[1]]) } }
234
+ | ':' { result = make_node(val) { |_| Riml::SublistNode.new([Riml::LiteralNode.new(':')]) } }
235
+ ;
236
+
237
+ DictGetWithDot:
238
+ DICT_VAL { result = [val[0]] }
239
+ | DictGetWithDot DICT_VAL { result = val[0] << val[1] }
240
+ ;
241
+
242
+ DictGetWithDotLiteral:
243
+ '.' IDENTIFIER { result = [val[1]] }
244
+ | DictGetWithDotLiteral DICT_VAL { result = val[0] << val[1] }
245
+ ;
246
+
247
+ Call:
248
+ Scope DefCallIdentifier '(' ArgList ')' { result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], v[3]) } }
249
+ | DictGet '(' ArgList ')' { result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[2]) } }
250
+ | BUILTIN_COMMAND '(' ArgList ')' { result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[2]) } }
251
+ | BUILTIN_COMMAND ArgListWithoutNothing { result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[1]) } }
252
+ | BUILTIN_COMMAND NEWLINE { result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], []) } }
253
+ | CALL '(' ArgList ')' { result = make_node(val) { |v| Riml::ExplicitCallNode.new(nil, nil, v[2]) } }
254
+ ;
255
+
256
+ ObjectInstantiationCall:
257
+ Scope DefCallIdentifier '(' ArgList ')' { result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], v[3]) } }
258
+ | Scope DefCallIdentifier { result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], []) } }
259
+ ;
260
+
261
+ RimlFileCommand:
262
+ RIML_FILE_COMMAND '(' ArgList ')' { result = make_node(val) { |v| Riml::RimlFileCommandNode.new(nil, v[0], v[2]) } }
263
+ | RIML_FILE_COMMAND ArgList { result = make_node(val) { |v| Riml::RimlFileCommandNode.new(nil, v[0], v[1]) } }
264
+ ;
265
+
266
+ RimlClassCommand:
267
+ RIML_CLASS_COMMAND '(' ClassArgList ')' { result = make_node(val) { |v| Riml::RimlClassCommandNode.new(nil, v[0], v[2]) } }
268
+ | RIML_CLASS_COMMAND ClassArgList { result = make_node(val) { |v| Riml::RimlClassCommandNode.new(nil, v[0], v[1]) } }
269
+ ;
270
+
271
+ ClassArgList:
272
+ Scope IDENTIFIER { result = ["#{val[0]}#{val[1]}"] }
273
+ | String { result = val }
274
+ | ClassArgList ',' Scope IDENTIFIER { result = val[0].concat ["#{val[2]}#{val[3]}"] }
275
+ ;
276
+
277
+ ExplicitCall:
278
+ CALL Scope DefCallIdentifier '(' ArgList ')' { result = make_node(val) { |v| Riml::ExplicitCallNode.new(v[1], v[2], v[4]) } }
279
+ | CALL DictGet '(' ArgList ')' { result = make_node(val) { |v| Riml::ExplicitCallNode.new(nil, v[1], v[3]) } }
280
+ ;
281
+
282
+ Scope:
283
+ SCOPE_MODIFIER { result = val[0] }
284
+ | /* nothing */ { result = nil }
285
+ ;
286
+
287
+ # [SID, scope_modifier]
288
+ SIDAndScope:
289
+ Scope { result = [ nil, val[0] ] }
290
+ | '<' IDENTIFIER '>' Scope { result = [ make_node(val) { |v| Riml::SIDNode.new(v[1]) }, val[3] ] }
291
+ ;
292
+
293
+ ArgList:
294
+ /* nothing */ { result = [] }
295
+ | ArgListWithoutNothingWithSplat { result = val[0] }
296
+ ;
297
+
298
+ ArgListWithSplat:
299
+ /* nothing */ { result = [] }
300
+ | ArgListWithoutNothingWithSplat { result = val[0] }
301
+ ;
302
+
303
+ ArgListWithoutNothingWithSplat:
304
+ Expression { result = val }
305
+ | SPLAT_ARG Expression { result = [ make_node(val) { |v| Riml::SplatNode.new(v[1]) } ] }
306
+ | ArgListWithoutNothingWithSplat "," Expression { result = val[0] << val[2] }
307
+ | ArgListWithoutNothingWithSplat "," SPLAT_ARG Expression { result = val[0] << make_node(val) { |v| Riml::SplatNode.new(v[3]) } }
308
+ ;
309
+
310
+ ArgListWithoutNothing:
311
+ Expression { result = val }
312
+ | ArgListWithoutNothing "," Expression { result = val[0] << val[2] }
313
+ ;
314
+
315
+ BinaryOperator:
316
+ Expression '||' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
317
+ | Expression '&&' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
318
+
319
+ | Expression '==' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
320
+ | Expression '==#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
321
+ | Expression '==?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
322
+
323
+ # added by riml
324
+ | Expression '===' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
325
+
326
+ | Expression '!=' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
327
+ | Expression '!=#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
328
+ | Expression '!=?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
329
+
330
+ | Expression '=~' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
331
+ | Expression '=~#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
332
+ | Expression '=~?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
333
+
334
+ | Expression '!~' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
335
+ | Expression '!~#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
336
+ | Expression '!~?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
337
+
338
+ | Expression '>' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
339
+ | Expression '>#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
340
+ | Expression '>?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
341
+
342
+ | Expression '>=' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
343
+ | Expression '>=#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
344
+ | Expression '>=?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
345
+
346
+ | Expression '<' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
347
+ | Expression '<#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
348
+ | Expression '<?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
349
+
350
+ | Expression '<=' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
351
+ | Expression '<=#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
352
+ | Expression '<=?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
353
+
354
+ | Expression '+' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
355
+ | Expression '-' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
356
+ | Expression '*' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
357
+ | Expression '/' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
358
+ | Expression '.' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
359
+ | Expression '%' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
360
+
361
+ | Expression IS Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
362
+ | Expression ISNOT Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
363
+ ;
364
+
365
+ UnaryOperator:
366
+ '!' Expression { result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) } }
367
+ | '+' Expression { result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) } }
368
+ | '-' Expression { result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) } }
369
+ ;
370
+
371
+ # ['=', LHS, RHS]
372
+ Assign:
373
+ LET AssignExpression { result = make_node(val) { |v| Riml::AssignNode.new(v[1][0], v[1][1], v[1][2]) } }
374
+ | AssignExpression { result = make_node(val) { |v| Riml::AssignNode.new(v[0][0], v[0][1], v[0][2]) } }
375
+ ;
376
+
377
+ MultiAssign:
378
+ Assign ',' Assign { result = make_node(val) { |v| Riml::MultiAssignNode.new([v[0], v[2]]) } }
379
+ | MultiAssign ',' Assign { val[0].assigns << val[2]; result = val[0] }
380
+ ;
381
+
382
+ # ['=', AssignLHS, Expression]
383
+ AssignExpression:
384
+ AssignLHS '=' Expression { result = [val[1], val[0], val[2]] }
385
+ | AssignLHS '+=' Expression { result = [val[1], val[0], val[2]] }
386
+ | AssignLHS '-=' Expression { result = [val[1], val[0], val[2]] }
387
+ | AssignLHS '.=' Expression { result = [val[1], val[0], val[2]] }
388
+ ;
389
+
390
+ AssignLHS:
391
+ AllVariableRetrieval { result = val[0] }
392
+ | List { result = val[0] }
393
+ | ListUnpack { result = val[0] }
394
+ | DictGet { result = val[0] }
395
+ | ListOrDictGetAssign { result = val[0] }
396
+ ;
397
+
398
+ # retrieving the value of a variable
399
+ VariableRetrieval:
400
+ SimpleVariableRetrieval { result = val[0] }
401
+ | SPECIAL_VAR_PREFIX IDENTIFIER { result = make_node(val) { |v| Riml::GetSpecialVariableNode.new(v[0], v[1]) } }
402
+ | ScopeModifierLiteral ListOrDictGetWithBrackets { result = make_node(val) { |v| Riml::GetVariableByScopeAndDictNameNode.new(v[0], v[1]) } }
403
+ ;
404
+
405
+ SimpleVariableRetrieval:
406
+ Scope IDENTIFIER { result = make_node(val) { |v| Riml::GetVariableNode.new(v[0], v[1]) } }
407
+ ;
408
+
409
+ AllVariableRetrieval:
410
+ VariableRetrieval { result = val[0] }
411
+ | Scope CurlyBraceName { result = make_node(val) { |v| Riml::GetCurlyBraceNameNode.new(v[0], v[1]) } }
412
+ ;
413
+
414
+ UnletVariable:
415
+ UNLET VariableRetrieval { result = make_node(val) { |v| Riml::UnletVariableNode.new('!', [ v[1] ]) } }
416
+ | UNLET_BANG VariableRetrieval { result = make_node(val) { |v| Riml::UnletVariableNode.new('!', [ v[1] ]) } }
417
+ | UnletVariable VariableRetrieval { result = val[0] << val[1] }
418
+ ;
419
+
420
+ CurlyBraceName:
421
+ CurlyBraceVarPart { result = make_node(val) { |v| Riml::CurlyBraceVariable.new([ v[0] ]) } }
422
+ | IDENTIFIER CurlyBraceName { result = make_node(val) { |v| Riml::CurlyBraceVariable.new([ Riml::CurlyBracePart.new(v[0]), v[1] ]) } }
423
+ | CurlyBraceName IDENTIFIER { result = val[0] << make_node(val) { |v| Riml::CurlyBracePart.new(v[1]) } }
424
+ | CurlyBraceName CurlyBraceVarPart { result = val[0] << val[1] }
425
+ ;
426
+
427
+ CurlyBraceVarPart:
428
+ '{' PossibleStringValue '}' { result = make_node(val) { |v| Riml::CurlyBracePart.new(v[1]) } }
429
+ | '{' PossibleStringValue CurlyBraceVarPart '}' { result = make_node(val) { |v| Riml::CurlyBracePart.new([v[1], v[2]]) } }
430
+ | '{' CurlyBraceVarPart PossibleStringValue '}' { result = make_node(val) { |v| Riml::CurlyBracePart.new([v[1], v[2]]) } }
431
+ ;
432
+
433
+ # Method definition
434
+ # [SID, scope_modifier, name, parameters, keyword, expressions]
435
+ Def:
436
+ FunctionType SIDAndScope DefCallIdentifier DefKeywords Block END { result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], [], v[3], v[4]) } }
437
+ | FunctionType SIDAndScope DefCallIdentifier '(' ParamList ')' DefKeywords Block END { result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], v[4], v[6], v[7]) } }
438
+ | FunctionType SIDAndScope DefCallIdentifier '(' SPLAT_PARAM ')' DefKeywords Block END { result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], [v[4]], v[6], v[7]) } }
439
+ | FunctionType SIDAndScope DefCallIdentifier '(' ParamList ',' SPLAT_PARAM ')' DefKeywords Block END { result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], v[4] << v[6], v[8], v[9]) } }
440
+ ;
441
+
442
+ FunctionType:
443
+ DEF { result = "DefNode" }
444
+ | DEF_BANG { result = "DefNode" }
445
+ | DEFM { result = "DefMethodNode" }
446
+ ;
447
+
448
+ DefCallIdentifier:
449
+ # use '' for first argument instead of nil in order to avoid a double scope-modifier
450
+ CurlyBraceName { result = make_node(val) { |v| Riml::GetCurlyBraceNameNode.new('', v[0]) } }
451
+ | IDENTIFIER { result = val[0] }
452
+ ;
453
+
454
+ # Example: 'range', 'dict' or 'abort' after function definition
455
+ DefKeywords:
456
+ IDENTIFIER { result = [val[0]] }
457
+ | DefKeywords IDENTIFIER { result = val[0] << val[1] }
458
+ | /* nothing */ { result = nil }
459
+ ;
460
+
461
+ ParamList:
462
+ /* nothing */ { result = [] }
463
+ | IDENTIFIER { result = val }
464
+ | DefaultParam { result = val }
465
+ | ParamList ',' IDENTIFIER { result = val[0] << val[2] }
466
+ | ParamList ',' DefaultParam { result = val[0] << val[2] }
467
+ ;
468
+
469
+ DefaultParam:
470
+ IDENTIFIER '=' Expression { result = make_node(val) { |v| Riml::DefaultParamNode.new(v[0], v[2]) } }
471
+ ;
472
+
473
+ Return:
474
+ RETURN Returnable { result = make_node(val) { |v| Riml::ReturnNode.new(v[1]) } }
475
+ | RETURN Returnable IF Expression { result = make_node(val) { |v| Riml::IfNode.new(v[3], Nodes.new([ReturnNode.new(v[1])])) } }
476
+ | RETURN Returnable UNLESS Expression { result = make_node(val) { |v| Riml::UnlessNode.new(v[3], Nodes.new([ReturnNode.new(v[1])])) } }
477
+ ;
478
+
479
+ Returnable:
480
+ /* nothing */ { result = nil }
481
+ | Expression { result = val[0] }
482
+ ;
483
+
484
+ EndScript:
485
+ FINISH { result = make_node(val) { |_| Riml::FinishNode.new } }
486
+ ;
487
+
488
+ # [expression, expressions]
489
+ If:
490
+ IF Expression IfBlock END { result = make_node(val) { |v| Riml::IfNode.new(v[1], v[2]) } }
491
+ | IF Expression THEN Expression END { result = make_node(val) { |v| Riml::IfNode.new(v[1], Riml::Nodes.new([v[3]])) } }
492
+ | Expression IF Expression { result = make_node(val) { |v| Riml::IfNode.new(v[2], Riml::Nodes.new([v[0]])) } }
493
+ ;
494
+
495
+ Unless:
496
+ UNLESS Expression IfBlock END { result = make_node(val) { |v| Riml::UnlessNode.new(v[1], v[2]) } }
497
+ | UNLESS Expression THEN Expression END { result = make_node(val) { |v| Riml::UnlessNode.new(v[1], Riml::Nodes.new([v[3]])) } }
498
+ | Expression UNLESS Expression { result = make_node(val) { |v| Riml::UnlessNode.new(v[2], Riml::Nodes.new([v[0]])) } }
499
+ ;
500
+
501
+ Ternary:
502
+ Expression '?' Expression ':' Expression { result = make_node(val) { |v| Riml::TernaryOperatorNode.new([v[0], v[2], v[4]]) } }
503
+ ;
504
+
505
+ While:
506
+ WHILE Expression Block END { result = make_node(val) { |v| Riml::WhileNode.new(v[1], v[2]) } }
507
+ ;
508
+
509
+ LoopKeyword:
510
+ BREAK { result = make_node(val) { |_| Riml::BreakNode.new } }
511
+ | CONTINUE { result = make_node(val) { |_| Riml::ContinueNode.new } }
512
+ ;
513
+
514
+ Until:
515
+ UNTIL Expression Block END { result = make_node(val) { |v| Riml::UntilNode.new(v[1], v[2]) } }
516
+ ;
517
+
518
+ For:
519
+ FOR SimpleVariableRetrieval IN Expression Block END { result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) } }
520
+ | FOR List IN Expression Block END { result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) } }
521
+ | FOR ListUnpack IN Expression Block END { result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) } }
522
+ ;
523
+
524
+ Try:
525
+ TRY Block END { result = make_node(val) { |v| Riml::TryNode.new(v[1], nil, nil) } }
526
+ | TRY Block Catch END { result = make_node(val) { |v| Riml::TryNode.new(v[1], v[2], nil) } }
527
+ | TRY Block Catch FINALLY Block END { result = make_node(val) { |v| Riml::TryNode.new(v[1], v[2], v[4]) } }
528
+ ;
529
+
530
+ Catch:
531
+ /* nothing */ { result = nil }
532
+ | CATCH Block { result = [ make_node(val) { |v| Riml::CatchNode.new(nil, v[1]) } ] }
533
+ | CATCH Catchable Block { result = [ make_node(val) { |v| Riml::CatchNode.new(v[1], v[2]) } ] }
534
+ | Catch CATCH Block { result = val[0] << make_node(val) { |v| Riml::CatchNode.new(nil, v[2]) } }
535
+ | Catch CATCH Catchable Block { result = val[0] << make_node(val) { |v| Riml::CatchNode.new(v[2], v[3]) } }
536
+ ;
537
+
538
+ Catchable:
539
+ Regexp { result = val[0] }
540
+ | String { result = val[0] }
541
+ ;
542
+
543
+ # [expressions]
544
+ # expressions list could contain an ElseNode, which contains expressions
545
+ # itself
546
+ Block:
547
+ NEWLINE Statements { result = val[1] }
548
+ | NEWLINE { result = make_node(val) { |_| Riml::Nodes.new([]) } }
549
+ ;
550
+
551
+ IfBlock:
552
+ Block { result = val[0] }
553
+ | NEWLINE Statements ElseBlock { result = val[1] << val[2] }
554
+ | NEWLINE Statements ElseifBlock { result = val[1] << val[2] }
555
+ | NEWLINE Statements ElseifBlock ElseBlock { result = val[1] << val[2] << val[3] }
556
+ ;
557
+
558
+ ElseBlock:
559
+ ELSE NEWLINE Statements { result = make_node(val) { |v| Riml::ElseNode.new(v[2]) } }
560
+ ;
561
+
562
+ ElseifBlock:
563
+ ELSEIF Expression NEWLINE Statements { result = make_node(val) { |v| Riml::Nodes.new([Riml::ElseifNode.new(v[1], v[3])]) } }
564
+ | ElseifBlock ELSEIF Expression NEWLINE Statements { result = val[0] << make_node(val) { |v| Riml::ElseifNode.new(v[2], v[4]) } }
565
+ ;
566
+
567
+ ClassDefinition:
568
+ CLASS Scope IDENTIFIER Block END { result = make_node(val) { |v| Riml::ClassDefinitionNode.new(v[1], v[2], nil, v[3]) } }
569
+ | CLASS Scope IDENTIFIER '<' Scope IDENTIFIER Block END { result = make_node(val) { |v| Riml::ClassDefinitionNode.new(v[1], v[2], (v[4] || ClassDefinitionNode::DEFAULT_SCOPE_MODIFIER) + v[5], v[6]) } }
570
+ ;
571
+
572
+ ObjectInstantiation:
573
+ NEW ObjectInstantiationCall { result = make_node(val) { |v| Riml::ObjectInstantiationNode.new(v[1]) } }
574
+ ;
575
+
576
+ Super:
577
+ SUPER '(' ArgListWithSplat ')' { result = make_node(val) { |v| Riml::SuperNode.new(v[2], true) } }
578
+ | SUPER { result = make_node(val) { |_| Riml::SuperNode.new([], false) } }
579
+ ;
580
+
581
+ ExLiteral:
582
+ EX_LITERAL { result = make_node(val) { |v| Riml::ExLiteralNode.new(v[0]) } }
583
+ ;
584
+ end
585
+
586
+ ---- header
587
+ require File.expand_path("../lexer", __FILE__)
588
+ require File.expand_path("../nodes", __FILE__)
589
+ require File.expand_path("../errors", __FILE__)
590
+ require File.expand_path("../ast_rewriter", __FILE__)
591
+ ---- inner
592
+ # This code will be put as-is in the parser class
593
+
594
+ attr_accessor :ast_rewriter
595
+ attr_writer :options
596
+
597
+ # The Parser and AST_Rewriter share this same hash of options
598
+ def options
599
+ @options ||= {}
600
+ end
601
+
602
+ def self.ast_cache
603
+ @ast_cache
604
+ end
605
+ @ast_cache = {}
606
+
607
+ # parses tokens or code into output nodes
608
+ def parse(object, ast_rewriter = Riml::AST_Rewriter.new, filename = nil, included = false)
609
+ if (ast = self.class.ast_cache[filename])
610
+ else
611
+ if tokens?(object)
612
+ @tokens = object
613
+ elsif code?(object)
614
+ @lexer = Riml::Lexer.new(object, filename, true)
615
+ end
616
+
617
+ begin
618
+ ast = do_parse
619
+ rescue Racc::ParseError => e
620
+ raise unless @lexer
621
+ if (invalid_token = @lexer.prev_token_is_keyword?)
622
+ warning = "#{invalid_token.inspect} is a keyword, and cannot " \
623
+ "be used as a variable name"
624
+ end
625
+ error_msg = e.message
626
+ error_msg << "\nWARNING: #{warning}" if warning
627
+ error = Riml::ParseError.new(error_msg, @lexer.filename, @lexer.lineno)
628
+ raise error
629
+ end
630
+ self.class.ast_cache[filename] = ast if filename
631
+ end
632
+ @ast_rewriter ||= ast_rewriter
633
+ return ast unless @ast_rewriter
634
+ @ast_rewriter.ast = ast.dup
635
+ @ast_rewriter.options ||= options
636
+ @ast_rewriter.rewrite(filename, included)
637
+ @ast_rewriter.ast
638
+ end
639
+
640
+ # get the next token from either the list of tokens provided, or
641
+ # the lexer getting the next token
642
+ def next_token
643
+ return @tokens.shift unless @lexer
644
+ token = @lexer.next_token
645
+ if token && @lexer.parser_info
646
+ @current_parser_info = token.pop
647
+ end
648
+ token
649
+ end
650
+
651
+ private
652
+
653
+ def tokens?(object)
654
+ Array === object
655
+ end
656
+
657
+ def code?(object)
658
+ String === object
659
+ end
660
+
661
+ def make_node(racc_val)
662
+ node = yield racc_val
663
+ node.parser_info = @current_parser_info
664
+ node
665
+ end