racc 1.4.14-java → 1.4.15-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Manifest.txt +50 -0
- data/ext/racc/com/headius/racc/Cparse.java +66 -23
- data/ext/racc/cparse.c +1 -1
- data/ext/racc/depend +1 -1
- data/lib/racc/cparse-jruby.jar +0 -0
- data/lib/racc/info.rb +2 -2
- data/test/assets/bibtex.y +141 -0
- data/test/assets/cadenza.y +170 -0
- data/test/assets/cast.y +926 -0
- data/test/assets/csspool.y +729 -0
- data/test/assets/edtf.y +583 -0
- data/test/assets/huia.y +318 -0
- data/test/assets/journey.y +47 -0
- data/test/assets/liquor.y +313 -0
- data/test/assets/machete.y +423 -0
- data/test/assets/macruby.y +2197 -0
- data/test/assets/mediacloth.y +599 -0
- data/test/assets/mof.y +649 -0
- data/test/assets/namae.y +302 -0
- data/test/assets/nasl.y +626 -0
- data/test/assets/nokogiri-css.y +255 -0
- data/test/assets/opal.y +1807 -0
- data/test/assets/php_serialization.y +98 -0
- data/test/assets/rdblockparser.y +576 -0
- data/test/assets/rdinlineparser.y +561 -0
- data/test/assets/riml.y +665 -0
- data/test/assets/ruby18.y +1943 -0
- data/test/assets/ruby19.y +2174 -0
- data/test/assets/ruby20.y +2350 -0
- data/test/assets/ruby21.y +2359 -0
- data/test/assets/ruby22.y +2381 -0
- data/test/assets/tp_plus.y +622 -0
- data/test/assets/twowaysql.y +278 -0
- data/test/helper.rb +50 -34
- data/test/regress/bibtex +474 -0
- data/test/regress/cadenza +796 -0
- data/test/regress/cast +3425 -0
- data/test/regress/csspool +2318 -0
- data/test/regress/edtf +1794 -0
- data/test/regress/huia +1392 -0
- data/test/regress/journey +222 -0
- data/test/regress/liquor +885 -0
- data/test/regress/machete +833 -0
- data/test/regress/mediacloth +1463 -0
- data/test/regress/mof +1368 -0
- data/test/regress/namae +634 -0
- data/test/regress/nasl +2058 -0
- data/test/regress/nokogiri-css +836 -0
- data/test/regress/opal +6429 -0
- data/test/regress/php_serialization +336 -0
- data/test/regress/rdblockparser +1061 -0
- data/test/regress/rdinlineparser +1243 -0
- data/test/regress/riml +3297 -0
- data/test/regress/ruby18 +6351 -0
- data/test/regress/ruby22 +7456 -0
- data/test/regress/tp_plus +1933 -0
- data/test/regress/twowaysql +556 -0
- data/test/test_racc_command.rb +177 -0
- metadata +80 -25
- data/.gemtest +0 -0
data/test/assets/riml.y
ADDED
@@ -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
|