antlr3 1.2.3
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.
- data/ANTLR-LICENSE.txt +26 -0
- data/History.txt +66 -0
- data/README.txt +139 -0
- data/bin/antlr4ruby +33 -0
- data/java/RubyTarget.java +524 -0
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3.rb +176 -0
- data/lib/antlr3/constants.rb +88 -0
- data/lib/antlr3/debug.rb +701 -0
- data/lib/antlr3/debug/event-hub.rb +210 -0
- data/lib/antlr3/debug/record-event-listener.rb +25 -0
- data/lib/antlr3/debug/rule-tracer.rb +55 -0
- data/lib/antlr3/debug/socket.rb +360 -0
- data/lib/antlr3/debug/trace-event-listener.rb +92 -0
- data/lib/antlr3/dfa.rb +247 -0
- data/lib/antlr3/dot.rb +174 -0
- data/lib/antlr3/error.rb +657 -0
- data/lib/antlr3/main.rb +561 -0
- data/lib/antlr3/modes/ast-builder.rb +41 -0
- data/lib/antlr3/modes/filter.rb +56 -0
- data/lib/antlr3/profile.rb +322 -0
- data/lib/antlr3/recognizers.rb +1280 -0
- data/lib/antlr3/streams.rb +985 -0
- data/lib/antlr3/streams/interactive.rb +91 -0
- data/lib/antlr3/streams/rewrite.rb +412 -0
- data/lib/antlr3/test/call-stack.rb +57 -0
- data/lib/antlr3/test/config.rb +23 -0
- data/lib/antlr3/test/core-extensions.rb +269 -0
- data/lib/antlr3/test/diff.rb +165 -0
- data/lib/antlr3/test/functional.rb +207 -0
- data/lib/antlr3/test/grammar.rb +371 -0
- data/lib/antlr3/token.rb +592 -0
- data/lib/antlr3/tree.rb +1415 -0
- data/lib/antlr3/tree/debug.rb +163 -0
- data/lib/antlr3/tree/visitor.rb +84 -0
- data/lib/antlr3/tree/wizard.rb +481 -0
- data/lib/antlr3/util.rb +149 -0
- data/lib/antlr3/version.rb +27 -0
- data/samples/ANTLRv3Grammar.g +621 -0
- data/samples/Cpp.g +749 -0
- data/templates/AST.stg +335 -0
- data/templates/ASTDbg.stg +40 -0
- data/templates/ASTParser.stg +153 -0
- data/templates/ASTTreeParser.stg +272 -0
- data/templates/Dbg.stg +192 -0
- data/templates/Ruby.stg +1514 -0
- data/test/functional/ast-output/auto-ast.rb +797 -0
- data/test/functional/ast-output/construction.rb +555 -0
- data/test/functional/ast-output/hetero-nodes.rb +753 -0
- data/test/functional/ast-output/rewrites.rb +1327 -0
- data/test/functional/ast-output/tree-rewrite.rb +1662 -0
- data/test/functional/debugging/debug-mode.rb +689 -0
- data/test/functional/debugging/profile-mode.rb +165 -0
- data/test/functional/debugging/rule-tracing.rb +74 -0
- data/test/functional/delegation/import.rb +379 -0
- data/test/functional/lexer/basic.rb +559 -0
- data/test/functional/lexer/filter-mode.rb +245 -0
- data/test/functional/lexer/nuances.rb +47 -0
- data/test/functional/lexer/properties.rb +104 -0
- data/test/functional/lexer/syn-pred.rb +32 -0
- data/test/functional/lexer/xml.rb +206 -0
- data/test/functional/main/main-scripts.rb +245 -0
- data/test/functional/parser/actions.rb +224 -0
- data/test/functional/parser/backtracking.rb +244 -0
- data/test/functional/parser/basic.rb +282 -0
- data/test/functional/parser/calc.rb +98 -0
- data/test/functional/parser/ll-star.rb +143 -0
- data/test/functional/parser/nuances.rb +165 -0
- data/test/functional/parser/predicates.rb +103 -0
- data/test/functional/parser/properties.rb +242 -0
- data/test/functional/parser/rule-methods.rb +132 -0
- data/test/functional/parser/scopes.rb +274 -0
- data/test/functional/token-rewrite/basic.rb +318 -0
- data/test/functional/token-rewrite/via-parser.rb +100 -0
- data/test/functional/tree-parser/basic.rb +750 -0
- data/test/unit/sample-input/file-stream-1 +2 -0
- data/test/unit/sample-input/teststreams.input2 +2 -0
- data/test/unit/test-dfa.rb +52 -0
- data/test/unit/test-exceptions.rb +44 -0
- data/test/unit/test-recognizers.rb +55 -0
- data/test/unit/test-scheme.rb +62 -0
- data/test/unit/test-streams.rb +459 -0
- data/test/unit/test-tree-wizard.rb +535 -0
- data/test/unit/test-trees.rb +854 -0
- metadata +205 -0
@@ -0,0 +1,797 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'antlr3/test/functional'
|
5
|
+
|
6
|
+
class TestAutoAST < ANTLR3::Test::Functional
|
7
|
+
|
8
|
+
def parse(grammar, rule, input, expect_errors = false)
|
9
|
+
@grammar = inline_grammar(grammar)
|
10
|
+
compile_and_load @grammar
|
11
|
+
grammar_module = self.class.const_get(@grammar.name)
|
12
|
+
|
13
|
+
grammar_module::Lexer.send(:include, ANTLR3::Test::CollectErrors)
|
14
|
+
grammar_module::Lexer.send(:include, ANTLR3::Test::CaptureOutput)
|
15
|
+
grammar_module::Parser.send(:include, ANTLR3::Test::CollectErrors)
|
16
|
+
grammar_module::Parser.send(:include, ANTLR3::Test::CaptureOutput)
|
17
|
+
|
18
|
+
lexer = grammar_module::Lexer.new( input )
|
19
|
+
parser = grammar_module::Parser.new( lexer )
|
20
|
+
|
21
|
+
r = parser.send(rule)
|
22
|
+
parser.reported_errors.should be_empty unless expect_errors
|
23
|
+
result = ''
|
24
|
+
|
25
|
+
unless r.nil?
|
26
|
+
result += r.result if r.respond_to?(:result)
|
27
|
+
result += r.tree.inspect if r.tree
|
28
|
+
end
|
29
|
+
return(expect_errors ? [result, parser.reported_errors] : result)
|
30
|
+
end
|
31
|
+
|
32
|
+
def tree_parse(grammar, tree_grammar, rule, tree_rule, input)
|
33
|
+
@grammar = inline_grammar(grammar)
|
34
|
+
@tree_grammar = inline_grammar(tree_grammar)
|
35
|
+
compile_and_load @grammar
|
36
|
+
compile_and_load @tree_grammar
|
37
|
+
|
38
|
+
grammar_module = self.class.const_get(@grammar.name)
|
39
|
+
tree_grammar_module = self.class.const_get(@tree_grammar.name)
|
40
|
+
|
41
|
+
grammar_module::Lexer.send(:include, ANTLR3::Test::CollectErrors)
|
42
|
+
grammar_module::Lexer.send(:include, ANTLR3::Test::CaptureOutput)
|
43
|
+
grammar_module::Parser.send(:include, ANTLR3::Test::CollectErrors)
|
44
|
+
grammar_module::Parser.send(:include, ANTLR3::Test::CaptureOutput)
|
45
|
+
tree_grammar_module::TreeParser.send(:include, ANTLR3::Test::CollectErrors)
|
46
|
+
tree_grammar_module::TreeParser.send(:include, ANTLR3::Test::CaptureOutput)
|
47
|
+
|
48
|
+
lexer = grammar_module::Lexer.new( input )
|
49
|
+
parser = grammar.module::Parser.new( lexer )
|
50
|
+
r = parser.send(rule)
|
51
|
+
nodes = ANTLR3::CommonTreeNodeStream( r.tree )
|
52
|
+
nodes.token_stream = parser.input
|
53
|
+
walker = tree_grammar_module::TreeParser.new( nodes )
|
54
|
+
r = walker.send(tree_rule)
|
55
|
+
|
56
|
+
return(r ? r.tree.inspect : '')
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
example 'flat token list' do
|
61
|
+
result = parse(<<-'END', :a, 'abc 34')
|
62
|
+
grammar TokenList;
|
63
|
+
options {language=Ruby;output=AST;}
|
64
|
+
a : ID INT ;
|
65
|
+
ID : 'a'..'z'+ ;
|
66
|
+
INT : '0'..'9'+;
|
67
|
+
WS : (' '|'\n') {$channel=HIDDEN;};
|
68
|
+
END
|
69
|
+
result.should == 'abc 34'
|
70
|
+
end
|
71
|
+
|
72
|
+
example 'token list in a single-alternative subrule' do
|
73
|
+
result = parse(<<-'END', :a, 'abc 34')
|
74
|
+
grammar TokenListInSingleAltBlock;
|
75
|
+
options {language=Ruby;output=AST;}
|
76
|
+
a : (ID INT) ;
|
77
|
+
ID : 'a'..'z'+ ;
|
78
|
+
INT : '0'..'9'+;
|
79
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
80
|
+
END
|
81
|
+
result.should == 'abc 34'
|
82
|
+
end
|
83
|
+
|
84
|
+
example "simple root at the outer level via the `^' operator" do
|
85
|
+
result = parse(<<-'END', :a, 'abc 34')
|
86
|
+
grammar SimpleRootAtOuterLevel;
|
87
|
+
options {language=Ruby;output=AST;}
|
88
|
+
a : ID^ INT ;
|
89
|
+
ID : 'a'..'z'+ ;
|
90
|
+
INT : '0'..'9'+;
|
91
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
92
|
+
END
|
93
|
+
result.should == '(abc 34)'
|
94
|
+
end
|
95
|
+
|
96
|
+
example "outer-level root changing token order from the `^' operator" do
|
97
|
+
result = parse(<<-'END', :a, '34 abc')
|
98
|
+
grammar SimpleRootAtOuterLevelReverse;
|
99
|
+
options {language=Ruby;output=AST;}
|
100
|
+
a : INT ID^ ;
|
101
|
+
ID : 'a'..'z'+ ;
|
102
|
+
INT : '0'..'9'+;
|
103
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
104
|
+
END
|
105
|
+
result.should == '(abc 34)'
|
106
|
+
end
|
107
|
+
|
108
|
+
example "leaving out tokens using the `!' operator" do
|
109
|
+
result = parse(<<-'END', :a, 'abc 34 dag 4532')
|
110
|
+
grammar Bang;
|
111
|
+
options {language=Ruby;output=AST;}
|
112
|
+
a : ID INT! ID! INT ;
|
113
|
+
ID : 'a'..'z'+ ;
|
114
|
+
INT : '0'..'9'+;
|
115
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
116
|
+
END
|
117
|
+
|
118
|
+
result.should == 'abc 4532'
|
119
|
+
end
|
120
|
+
|
121
|
+
example "tokens in `(...)?' optional subrule" do
|
122
|
+
result = parse(<<-'END', :a, 'a 1 b')
|
123
|
+
grammar OptionalThenRoot;
|
124
|
+
options {language=Ruby;output=AST;}
|
125
|
+
a : ( ID INT )? ID^ ;
|
126
|
+
ID : 'a'..'z'+ ;
|
127
|
+
INT : '0'..'9'+;
|
128
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
129
|
+
END
|
130
|
+
result.should == '(b a 1)'
|
131
|
+
end
|
132
|
+
|
133
|
+
example "labeled literal-string root token" do
|
134
|
+
result = parse(<<-'END', :a, 'void foo;')
|
135
|
+
grammar LabeledStringRoot;
|
136
|
+
options {language=Ruby;output=AST;}
|
137
|
+
a : v='void'^ ID ';' ;
|
138
|
+
ID : 'a'..'z'+ ;
|
139
|
+
INT : '0'..'9'+;
|
140
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
141
|
+
END
|
142
|
+
result.should == '(void foo ;)'
|
143
|
+
end
|
144
|
+
|
145
|
+
example 'rule with token wildcard' do
|
146
|
+
result = parse(<<-'END', :a, 'void foo;')
|
147
|
+
grammar Wildcard;
|
148
|
+
options {language=Ruby;output=AST;}
|
149
|
+
a : v='void'^ . ';' ;
|
150
|
+
ID : 'a'..'z'+ ;
|
151
|
+
INT : '0'..'9'+;
|
152
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
153
|
+
END
|
154
|
+
result.should == '(void foo ;)'
|
155
|
+
end
|
156
|
+
|
157
|
+
example "token wildcard as root via the `^' operator" do
|
158
|
+
result = parse(<<-'END', :a, 'void foo;')
|
159
|
+
grammar WildcardRoot;
|
160
|
+
options {language=Ruby;output=AST;}
|
161
|
+
a : v='void' .^ ';' ;
|
162
|
+
ID : 'a'..'z'+ ;
|
163
|
+
INT : '0'..'9'+;
|
164
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
165
|
+
END
|
166
|
+
result.should == '(foo void ;)'
|
167
|
+
end
|
168
|
+
|
169
|
+
example "labeled token wildcard as root via the `^' operator" do
|
170
|
+
result = parse(<<-'END', :a, 'void foo;')
|
171
|
+
grammar WildcardRootWithLabel;
|
172
|
+
options {language=Ruby;output=AST;}
|
173
|
+
a : v='void' x=.^ ';' ;
|
174
|
+
ID : 'a'..'z'+ ;
|
175
|
+
INT : '0'..'9'+;
|
176
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
177
|
+
END
|
178
|
+
result.should == '(foo void ;)'
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
example "token wildcard as root (with list label)" do
|
183
|
+
result = parse(<<-'END', :a, 'void foo;')
|
184
|
+
grammar WildcardRootWithListLabel;
|
185
|
+
options {language=Ruby;output=AST;}
|
186
|
+
a : v='void' x=.^ ';' ;
|
187
|
+
ID : 'a'..'z'+ ;
|
188
|
+
INT : '0'..'9'+;
|
189
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
190
|
+
|
191
|
+
END
|
192
|
+
result.should == '(foo void ;)'
|
193
|
+
end
|
194
|
+
|
195
|
+
example "trashed token wildcard" do
|
196
|
+
result = parse(<<-'END', :a, 'void foo;')
|
197
|
+
grammar WildcardBangWithListLabel;
|
198
|
+
options {language=Ruby;output=AST;}
|
199
|
+
a : v='void' x=.! ';' ;
|
200
|
+
ID : 'a'..'z'+ ;
|
201
|
+
INT : '0'..'9'+;
|
202
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
203
|
+
|
204
|
+
END
|
205
|
+
result.should == 'void ;'
|
206
|
+
end
|
207
|
+
|
208
|
+
example "multiple occurences of the `^' operator in a list of tokens" do
|
209
|
+
result = parse(<<-'END', :a, 'a 34 c')
|
210
|
+
grammar RootRoot;
|
211
|
+
options {language=Ruby;output=AST;}
|
212
|
+
a : ID^ INT^ ID ;
|
213
|
+
ID : 'a'..'z'+ ;
|
214
|
+
INT : '0'..'9'+;
|
215
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
216
|
+
|
217
|
+
END
|
218
|
+
result.should == '(34 a c)'
|
219
|
+
end
|
220
|
+
|
221
|
+
example "another case of multiple occurences of the `^' operator" do
|
222
|
+
result = parse(<<-'END', :a, 'a 34 c')
|
223
|
+
grammar RootRoot2;
|
224
|
+
options {language=Ruby;output=AST;}
|
225
|
+
a : ID INT^ ID^ ;
|
226
|
+
ID : 'a'..'z'+ ;
|
227
|
+
INT : '0'..'9'+;
|
228
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
229
|
+
|
230
|
+
END
|
231
|
+
result.should == '(c (34 a))'
|
232
|
+
end
|
233
|
+
|
234
|
+
example "root-hoist using `^' from within a (...)+ block" do
|
235
|
+
result = parse(<<-'END', :a, 'a 34 * b 9 * c')
|
236
|
+
grammar RootThenRootInLoop;
|
237
|
+
options {language=Ruby;output=AST;}
|
238
|
+
a : ID^ (INT '*'^ ID)+ ;
|
239
|
+
ID : 'a'..'z'+ ;
|
240
|
+
INT : '0'..'9'+;
|
241
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
242
|
+
|
243
|
+
END
|
244
|
+
result.should == '(* (* (a 34) b 9) c)'
|
245
|
+
end
|
246
|
+
|
247
|
+
example "nested subrules without any AST ops resulting in a flat list" do
|
248
|
+
result = parse(<<-'END', :a, 'void a b;')
|
249
|
+
grammar NestedSubrule;
|
250
|
+
options {language=Ruby;output=AST;}
|
251
|
+
a : 'void' (({
|
252
|
+
#do nothing
|
253
|
+
} ID|INT) ID | 'null' ) ';' ;
|
254
|
+
ID : 'a'..'z'+ ;
|
255
|
+
INT : '0'..'9'+;
|
256
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
257
|
+
|
258
|
+
END
|
259
|
+
result.should == 'void a b ;'
|
260
|
+
end
|
261
|
+
|
262
|
+
example "invoking another rule without any AST ops, resulting in a flat list" do
|
263
|
+
result = parse(<<-'END', :a, 'int a')
|
264
|
+
grammar InvokeRule;
|
265
|
+
options {language=Ruby;output=AST;}
|
266
|
+
a : type ID ;
|
267
|
+
type : {
|
268
|
+
# do nothing
|
269
|
+
}'int' | 'float' ;
|
270
|
+
ID : 'a'..'z'+ ;
|
271
|
+
INT : '0'..'9'+;
|
272
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
273
|
+
|
274
|
+
END
|
275
|
+
result.should == 'int a'
|
276
|
+
end
|
277
|
+
|
278
|
+
example "hoisting the results of another rule as root using the `^' operator" do
|
279
|
+
result = parse(<<-'END', :a, 'int a')
|
280
|
+
grammar InvokeRuleAsRoot;
|
281
|
+
options {language=Ruby;output=AST;}
|
282
|
+
a : type^ ID ;
|
283
|
+
type : {
|
284
|
+
# do nothing
|
285
|
+
}'int' | 'float' ;
|
286
|
+
ID : 'a'..'z'+ ;
|
287
|
+
INT : '0'..'9'+;
|
288
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
289
|
+
|
290
|
+
END
|
291
|
+
result.should == '(int a)'
|
292
|
+
end
|
293
|
+
|
294
|
+
example "hoisting another rule's true as root using the `^' operator (with a label)" do
|
295
|
+
result = parse(<<-'END', :a, 'int a')
|
296
|
+
grammar InvokeRuleAsRootWithLabel;
|
297
|
+
options {language=Ruby;output=AST;}
|
298
|
+
a : x=type^ ID ;
|
299
|
+
type : {
|
300
|
+
# do nothing
|
301
|
+
}'int' | 'float' ;
|
302
|
+
ID : 'a'..'z'+ ;
|
303
|
+
INT : '0'..'9'+;
|
304
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
305
|
+
|
306
|
+
END
|
307
|
+
result.should == '(int a)'
|
308
|
+
end
|
309
|
+
|
310
|
+
example "hoisting another rule's result tree as root using the `^' operator (with a list += label)" do
|
311
|
+
result = parse(<<-'END', :a, 'int a')
|
312
|
+
grammar InvokeRuleAsRootWithListLabel;
|
313
|
+
options {language=Ruby;output=AST;}
|
314
|
+
a : x+=type^ ID ;
|
315
|
+
type : {
|
316
|
+
# do nothing
|
317
|
+
}'int' | 'float' ;
|
318
|
+
ID : 'a'..'z'+ ;
|
319
|
+
INT : '0'..'9'+;
|
320
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
321
|
+
|
322
|
+
END
|
323
|
+
result.should == '(int a)'
|
324
|
+
end
|
325
|
+
|
326
|
+
example "root-hoist via `^' within a (...)* loop resulting in a deeply-nested tree" do
|
327
|
+
result = parse(<<-'END', :a, 'a+b+c+d')
|
328
|
+
grammar RuleRootInLoop;
|
329
|
+
options {language=Ruby;output=AST;}
|
330
|
+
a : ID ('+'^ ID)* ;
|
331
|
+
ID : 'a'..'z'+ ;
|
332
|
+
INT : '0'..'9'+;
|
333
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
334
|
+
|
335
|
+
END
|
336
|
+
result.should == '(+ (+ (+ a b) c) d)'
|
337
|
+
end
|
338
|
+
|
339
|
+
example "hoisting another rule's result tree as root from within a (...)* loop resulting in a deeply nested tree" do
|
340
|
+
result = parse(<<-'END', :a, 'a+b+c-d')
|
341
|
+
grammar RuleInvocationRuleRootInLoop;
|
342
|
+
options {language=Ruby;output=AST;}
|
343
|
+
a : ID (op^ ID)* ;
|
344
|
+
op : {
|
345
|
+
# do nothing
|
346
|
+
}'+' | '-' ;
|
347
|
+
ID : 'a'..'z'+ ;
|
348
|
+
INT : '0'..'9'+;
|
349
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
350
|
+
|
351
|
+
END
|
352
|
+
result.should == '(- (+ (+ a b) c) d)'
|
353
|
+
end
|
354
|
+
|
355
|
+
example "using tail recursion to build deeply-nested expression trees" do
|
356
|
+
result = parse(<<-'END', :s, '3 exp 4 exp 5')
|
357
|
+
grammar TailRecursion;
|
358
|
+
options {language=Ruby;output=AST;}
|
359
|
+
s : a ;
|
360
|
+
a : atom ('exp'^ a)? ;
|
361
|
+
atom : INT ;
|
362
|
+
ID : 'a'..'z'+ ;
|
363
|
+
INT : '0'..'9'+;
|
364
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
365
|
+
|
366
|
+
END
|
367
|
+
result.should == '(exp 3 (exp 4 5))'
|
368
|
+
end
|
369
|
+
|
370
|
+
example "simple token node from a token type set" do
|
371
|
+
result = parse(<<-'END', :a, 'abc')
|
372
|
+
grammar TokenSet;
|
373
|
+
options {language=Ruby; output=AST;}
|
374
|
+
a : ID|INT ;
|
375
|
+
ID : 'a'..'z'+ ;
|
376
|
+
INT : '0'..'9'+;
|
377
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
378
|
+
END
|
379
|
+
result.should == 'abc'
|
380
|
+
end
|
381
|
+
|
382
|
+
example "hoisting a token-type set token as root with `^'" do
|
383
|
+
result = parse(<<-'END', :a, '+abc')
|
384
|
+
grammar SetRoot;
|
385
|
+
options {language=Ruby;output=AST;}
|
386
|
+
a : ('+' | '-')^ ID ;
|
387
|
+
ID : 'a'..'z'+ ;
|
388
|
+
INT : '0'..'9'+;
|
389
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
390
|
+
|
391
|
+
END
|
392
|
+
result.should == '(+ abc)'
|
393
|
+
end
|
394
|
+
|
395
|
+
example "hoisting a token-type set token as root with `^' (with a label)" do
|
396
|
+
result = parse(<<-'END', :a, '+abc')
|
397
|
+
grammar SetRootWithLabel;
|
398
|
+
options {language=Ruby;output=AST;}
|
399
|
+
a : (x=('+' | '-'))^ ID ;
|
400
|
+
ID : 'a'..'z'+ ;
|
401
|
+
INT : '0'..'9'+;
|
402
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
403
|
+
|
404
|
+
END
|
405
|
+
result.should == '+ abc'
|
406
|
+
end
|
407
|
+
|
408
|
+
example "hoisting a token-type set token as root from within a (...)* loop" do
|
409
|
+
result = parse(<<-'END', :a, 'a+b-c')
|
410
|
+
grammar SetAsRuleRootInLoop;
|
411
|
+
options {language=Ruby;output=AST;}
|
412
|
+
a : ID (('+'|'-')^ ID)* ;
|
413
|
+
ID : 'a'..'z'+ ;
|
414
|
+
INT : '0'..'9'+;
|
415
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
416
|
+
|
417
|
+
END
|
418
|
+
result.should == '(- (+ a b) c)'
|
419
|
+
end
|
420
|
+
|
421
|
+
example "an `~' inverted token-type set element" do
|
422
|
+
result = parse(<<-'END', :a, '34+2')
|
423
|
+
grammar NotSet;
|
424
|
+
options {language=Ruby;output=AST;}
|
425
|
+
a : ~ID '+' INT ;
|
426
|
+
ID : 'a'..'z'+ ;
|
427
|
+
INT : '0'..'9'+;
|
428
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
429
|
+
|
430
|
+
END
|
431
|
+
result.should == '34 + 2'
|
432
|
+
end
|
433
|
+
|
434
|
+
example "a `~' inverted token-type set in a rule (with a label)" do
|
435
|
+
result = parse(<<-'END', :a, '34+2')
|
436
|
+
grammar NotSetWithLabel;
|
437
|
+
options {language=Ruby;output=AST;}
|
438
|
+
a : x=~ID '+' INT ;
|
439
|
+
ID : 'a'..'z'+ ;
|
440
|
+
INT : '0'..'9'+;
|
441
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
442
|
+
|
443
|
+
END
|
444
|
+
result.should == '34 + 2'
|
445
|
+
end
|
446
|
+
|
447
|
+
example "a `~' inverted token-type set element in a rule (with a list += label)" do
|
448
|
+
result = parse(<<-'END', :a, '34+2')
|
449
|
+
grammar NotSetWithListLabel;
|
450
|
+
options {language=Ruby;output=AST;}
|
451
|
+
a : x=~ID '+' INT ;
|
452
|
+
ID : 'a'..'z'+ ;
|
453
|
+
INT : '0'..'9'+;
|
454
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
455
|
+
|
456
|
+
END
|
457
|
+
result.should == '34 + 2'
|
458
|
+
end
|
459
|
+
|
460
|
+
example "a `~' inverted token-type set element hoisted to root via `^'" do
|
461
|
+
result = parse(<<-'END', :a, '34 55')
|
462
|
+
grammar NotSetRoot;
|
463
|
+
options {language=Ruby;output=AST;}
|
464
|
+
a : ~'+'^ INT ;
|
465
|
+
ID : 'a'..'z'+ ;
|
466
|
+
INT : '0'..'9'+;
|
467
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
468
|
+
|
469
|
+
END
|
470
|
+
result.should == '(34 55)'
|
471
|
+
end
|
472
|
+
|
473
|
+
# FIXME: no label actually in the grammar
|
474
|
+
|
475
|
+
example "hoisting a `~' inverted token-type set to root using `^' (with label)" do
|
476
|
+
result = parse(<<-'END', :a, '34 55')
|
477
|
+
grammar NotSetRootWithLabel;
|
478
|
+
options {language=Ruby;output=AST;}
|
479
|
+
a : x=~'+'^ INT ;
|
480
|
+
ID : 'a'..'z'+ ;
|
481
|
+
INT : '0'..'9'+;
|
482
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
483
|
+
END
|
484
|
+
result.should == '(34 55)'
|
485
|
+
end
|
486
|
+
|
487
|
+
# FIXME: no label here either
|
488
|
+
|
489
|
+
example "hoisting a `~' inverted token-type set to root using `^' (with list += label)" do
|
490
|
+
result = parse(<<-'END', :a, '34 55')
|
491
|
+
grammar NotSetRootWithListLabel;
|
492
|
+
options {language=Ruby;output=AST;}
|
493
|
+
a : x+=~'+'^ INT ;
|
494
|
+
ID : 'a'..'z'+ ;
|
495
|
+
INT : '0'..'9'+;
|
496
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
497
|
+
|
498
|
+
END
|
499
|
+
result.should == '(34 55)'
|
500
|
+
end
|
501
|
+
|
502
|
+
example "hoisting a `~' inverted token-type set to root from within a (...)* loop" do
|
503
|
+
result = parse(<<-'END', :a, '3+4+5')
|
504
|
+
grammar NotSetRuleRootInLoop;
|
505
|
+
options {language=Ruby;output=AST;}
|
506
|
+
a : INT (~INT^ INT)* ;
|
507
|
+
blort : '+' ;
|
508
|
+
ID : 'a'..'z'+ ;
|
509
|
+
INT : '0'..'9'+;
|
510
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
511
|
+
|
512
|
+
END
|
513
|
+
result.should == '(+ (+ 3 4) 5)'
|
514
|
+
end
|
515
|
+
|
516
|
+
example "multiple tokens with the same label in a rule" do
|
517
|
+
result = parse(<<-'END', :a, 'a b')
|
518
|
+
grammar TokenLabelReuse;
|
519
|
+
options {language=Ruby;output=AST;}
|
520
|
+
a returns [result] : id=ID id=ID {
|
521
|
+
$result = "2nd id=\%s," \% $id.text
|
522
|
+
} ;
|
523
|
+
ID : 'a'..'z'+ ;
|
524
|
+
INT : '0'..'9'+;
|
525
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
526
|
+
|
527
|
+
END
|
528
|
+
result.should == '2nd id=b,a b'
|
529
|
+
end
|
530
|
+
|
531
|
+
example "multiple tokens with the same label in a rule (with a `^' root hoist)" do
|
532
|
+
result = parse(<<-'END', :a, 'a b')
|
533
|
+
grammar TokenLabelReuse2;
|
534
|
+
options {language=Ruby;output=AST;}
|
535
|
+
a returns [result]: id=ID id=ID^ {$result = "2nd id=#{$id.text},"} ;
|
536
|
+
ID : 'a'..'z'+ ;
|
537
|
+
INT : '0'..'9'+;
|
538
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
539
|
+
|
540
|
+
END
|
541
|
+
result.should == '2nd id=b,(b a)'
|
542
|
+
end
|
543
|
+
|
544
|
+
example "extra token in a simple declaration" do
|
545
|
+
result, errors = parse(<<-'END', :decl, 'int 34 x=1;', true)
|
546
|
+
grammar ExtraTokenInSimpleDecl;
|
547
|
+
options {language=Ruby;output=AST;}
|
548
|
+
decl : type^ ID '='! INT ';'! ;
|
549
|
+
type : 'int' | 'float' ;
|
550
|
+
ID : 'a'..'z'+ ;
|
551
|
+
INT : '0'..'9'+;
|
552
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
553
|
+
|
554
|
+
END
|
555
|
+
errors.should == ["line 1:4 extraneous input \"34\" expecting ID"]
|
556
|
+
result.should == '(int x 1)'
|
557
|
+
end
|
558
|
+
|
559
|
+
example "missing ID in a simple declaration" do
|
560
|
+
result, errors = parse(<<-'END', :decl, 'int =1;', true)
|
561
|
+
grammar MissingIDInSimpleDecl;
|
562
|
+
options {language=Ruby;output=AST;}
|
563
|
+
tokens {EXPR;}
|
564
|
+
decl : type^ ID '='! INT ';'! ;
|
565
|
+
type : 'int' | 'float' ;
|
566
|
+
ID : 'a'..'z'+ ;
|
567
|
+
INT : '0'..'9'+;
|
568
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
569
|
+
END
|
570
|
+
errors.should == ["line 1:4 missing ID at \"=\""]
|
571
|
+
result.should == '(int <missing ID> 1)'
|
572
|
+
end
|
573
|
+
|
574
|
+
example "missing token of a token-type set in a simple declaration" do
|
575
|
+
result, errors = parse(<<-'END', :decl, 'x=1;', true)
|
576
|
+
grammar MissingSetInSimpleDecl;
|
577
|
+
options {language=Ruby;output=AST;}
|
578
|
+
tokens {EXPR;}
|
579
|
+
decl : type^ ID '='! INT ';'! ;
|
580
|
+
type : 'int' | 'float' ;
|
581
|
+
ID : 'a'..'z'+ ;
|
582
|
+
INT : '0'..'9'+;
|
583
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
584
|
+
|
585
|
+
END
|
586
|
+
errors.should == ["line 1:0 mismatched input \"x\" expecting set nil"]
|
587
|
+
result.should == '(<error: x> x 1)'
|
588
|
+
end
|
589
|
+
|
590
|
+
example "missing INT token simulated with a `<missing INT>' error node" do
|
591
|
+
result, errors = parse(<<-'END', :a, 'abc', true)
|
592
|
+
grammar MissingTokenGivesErrorNode;
|
593
|
+
options {language=Ruby;output=AST;}
|
594
|
+
a : ID INT ; // follow is EOF
|
595
|
+
ID : 'a'..'z'+ ;
|
596
|
+
INT : '0'..'9'+;
|
597
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
598
|
+
|
599
|
+
END
|
600
|
+
errors.should == ["line 0:-1 missing INT at \"<EOF>\""]
|
601
|
+
result.should == 'abc <missing INT>'
|
602
|
+
end
|
603
|
+
|
604
|
+
example "missing token from invoked rule results in error node with a resync attribute" do
|
605
|
+
result, errors = parse(<<-'END', :a, 'abc', true)
|
606
|
+
grammar MissingTokenGivesErrorNodeInInvokedRule;
|
607
|
+
options {language=Ruby;output=AST;}
|
608
|
+
a : b ;
|
609
|
+
b : ID INT ; // follow should see EOF
|
610
|
+
ID : 'a'..'z'+ ;
|
611
|
+
INT : '0'..'9'+;
|
612
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
613
|
+
|
614
|
+
END
|
615
|
+
errors.should == ["line 0:-1 mismatched input \"<EOF>\" expecting INT"]
|
616
|
+
result.should == '<mismatched token: <EOF>, resync = abc>'
|
617
|
+
end
|
618
|
+
|
619
|
+
example "extraneous ID token displays error and is ignored in AST output" do
|
620
|
+
result, errors = parse(<<-'END', :a, 'abc ick 34', true)
|
621
|
+
grammar ExtraTokenGivesErrorNode;
|
622
|
+
options {language=Ruby;output=AST;}
|
623
|
+
a : b c ;
|
624
|
+
b : ID ;
|
625
|
+
c : INT ;
|
626
|
+
ID : 'a'..'z'+ ;
|
627
|
+
INT : '0'..'9'+;
|
628
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
629
|
+
|
630
|
+
END
|
631
|
+
errors.should == ["line 1:4 extraneous input \"ick\" expecting INT"]
|
632
|
+
result.should == 'abc 34'
|
633
|
+
end
|
634
|
+
|
635
|
+
example "missing ID token simulated with a `<missing ID>' error node" do
|
636
|
+
result, errors = parse(<<-'END', :a, '34', true)
|
637
|
+
grammar MissingFirstTokenGivesErrorNode;
|
638
|
+
options {language=Ruby;output=AST;}
|
639
|
+
a : ID INT ;
|
640
|
+
ID : 'a'..'z'+ ;
|
641
|
+
INT : '0'..'9'+;
|
642
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
643
|
+
|
644
|
+
END
|
645
|
+
errors.should == ["line 1:0 missing ID at \"34\""]
|
646
|
+
result.should == '<missing ID> 34'
|
647
|
+
end
|
648
|
+
|
649
|
+
example "another case where a missing ID token is simulated with a `<missing ID>' error node" do
|
650
|
+
result, errors = parse(<<-'END', :a, '34', true)
|
651
|
+
grammar MissingFirstTokenGivesErrorNode2;
|
652
|
+
options {language=Ruby;output=AST;}
|
653
|
+
a : b c ;
|
654
|
+
b : ID ;
|
655
|
+
c : INT ;
|
656
|
+
ID : 'a'..'z'+ ;
|
657
|
+
INT : '0'..'9'+;
|
658
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
659
|
+
|
660
|
+
END
|
661
|
+
errors.should == ["line 1:0 missing ID at \"34\""]
|
662
|
+
result.should == '<missing ID> 34'
|
663
|
+
end
|
664
|
+
|
665
|
+
example "no viable alternative for rule is represented as a single `<unexpected: ...>' error node" do
|
666
|
+
result, errors = parse(<<-'END', :a, '*', true)
|
667
|
+
grammar NoViableAltGivesErrorNode;
|
668
|
+
options {language=Ruby;output=AST;}
|
669
|
+
a : b | c ;
|
670
|
+
b : ID ;
|
671
|
+
c : INT ;
|
672
|
+
ID : 'a'..'z'+ ;
|
673
|
+
S : '*' ;
|
674
|
+
INT : '0'..'9'+;
|
675
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
676
|
+
END
|
677
|
+
errors.should == ["line 1:0 no viable alternative at input \"*\""]
|
678
|
+
result.should == "<unexpected: 0 S[\"*\"] @ line 1 col 0 (0..0), resync = *>"
|
679
|
+
end
|
680
|
+
|
681
|
+
example "token with a `+=' list label hoisted to root with `^'" do
|
682
|
+
result = parse(<<-'END', :a, 'a')
|
683
|
+
grammar TokenListLabelRuleRoot;
|
684
|
+
options {language=Ruby;output=AST;}
|
685
|
+
a : id+=ID^ ;
|
686
|
+
ID : 'a'..'z'+ ;
|
687
|
+
INT : '0'..'9'+;
|
688
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
689
|
+
|
690
|
+
END
|
691
|
+
result.should == 'a'
|
692
|
+
end
|
693
|
+
|
694
|
+
example "token with a list `+=' label trashed with `!'" do
|
695
|
+
result = parse(<<-'END', :a, 'a')
|
696
|
+
grammar TokenListLabelBang;
|
697
|
+
options {language=Ruby;output=AST;}
|
698
|
+
a : id+=ID! ;
|
699
|
+
ID : 'a'..'z'+ ;
|
700
|
+
INT : '0'..'9'+;
|
701
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
702
|
+
|
703
|
+
END
|
704
|
+
result.should == ''
|
705
|
+
end
|
706
|
+
|
707
|
+
example "using list `+=' labels to collect trees of invoked rules" do
|
708
|
+
result = parse(<<-'END', :a, 'a b')
|
709
|
+
grammar RuleListLabel;
|
710
|
+
options {language=Ruby;output=AST;}
|
711
|
+
a returns [result]: x+=b x+=b {
|
712
|
+
t = $x[1]
|
713
|
+
$result = "2nd x=#{t.to_string_tree},"
|
714
|
+
};
|
715
|
+
b : ID;
|
716
|
+
ID : 'a'..'z'+ ;
|
717
|
+
INT : '0'..'9'+;
|
718
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
719
|
+
|
720
|
+
END
|
721
|
+
result.should == '2nd x=b,a b'
|
722
|
+
end
|
723
|
+
|
724
|
+
example "using a list `+=' label to collect the trees of invoked rules within a (...)+ block" do
|
725
|
+
result = parse(<<-'END', :a, 'a b')
|
726
|
+
grammar RuleListLabelRuleRoot;
|
727
|
+
options {language=Ruby;output=AST;}
|
728
|
+
a returns [result] : ( x+=b^ )+ {
|
729
|
+
$result = "x=%s," \% $x[1].to_string_tree
|
730
|
+
} ;
|
731
|
+
b : ID;
|
732
|
+
ID : 'a'..'z'+ ;
|
733
|
+
INT : '0'..'9'+;
|
734
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
735
|
+
|
736
|
+
END
|
737
|
+
result.should == 'x=(b a),(b a)'
|
738
|
+
end
|
739
|
+
|
740
|
+
example "trashing the tree of an invoked rule with `!' while collecting the tree with a list `+=' label" do
|
741
|
+
result = parse(<<-'END', :a, 'a b')
|
742
|
+
grammar RuleListLabelBang;
|
743
|
+
options {language=Ruby;output=AST;}
|
744
|
+
a returns [result] : x+=b! x+=b {
|
745
|
+
$result = "1st x=#{$x[0].to_string_tree},"
|
746
|
+
} ;
|
747
|
+
b : ID;
|
748
|
+
ID : 'a'..'z'+ ;
|
749
|
+
INT : '0'..'9'+;
|
750
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
751
|
+
|
752
|
+
END
|
753
|
+
result.should == '1st x=a,b'
|
754
|
+
end
|
755
|
+
|
756
|
+
example "a whole bunch of different elements" do
|
757
|
+
result = parse(<<-'END', :a, 'a b b c c d')
|
758
|
+
grammar ComplicatedMelange;
|
759
|
+
options {language=Ruby;output=AST;}
|
760
|
+
a : A b=B b=B c+=C c+=C D {s = $D.text} ;
|
761
|
+
A : 'a' ;
|
762
|
+
B : 'b' ;
|
763
|
+
C : 'c' ;
|
764
|
+
D : 'd' ;
|
765
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
766
|
+
END
|
767
|
+
result.should == 'a b b c c d'
|
768
|
+
end
|
769
|
+
|
770
|
+
example "rule return values in addition to AST output" do
|
771
|
+
result = parse(<<-'END', :a, 'abc 34')
|
772
|
+
grammar ReturnValueWithAST;
|
773
|
+
options {language=Ruby;output=AST;}
|
774
|
+
a returns [result] : ID b { $result = $b.i.to_s + "\n" } ;
|
775
|
+
b returns [i] : INT {$i=$INT.text.to_i};
|
776
|
+
ID : 'a'..'z'+ ;
|
777
|
+
INT : '0'..'9'+;
|
778
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
779
|
+
|
780
|
+
END
|
781
|
+
result.should == "34\nabc 34"
|
782
|
+
end
|
783
|
+
|
784
|
+
example "a (...)+ loop containing a token-type set" do
|
785
|
+
result = parse(<<-'END', :r, 'abc 34 d')
|
786
|
+
grammar SetLoop;
|
787
|
+
options { language=Ruby;output=AST; }
|
788
|
+
r : (INT|ID)+ ;
|
789
|
+
ID : 'a'..'z' + ;
|
790
|
+
INT : '0'..'9' +;
|
791
|
+
WS: (' ' | '\n' | '\t')+ {$channel = HIDDEN;};
|
792
|
+
|
793
|
+
END
|
794
|
+
result.should == 'abc 34 d'
|
795
|
+
end
|
796
|
+
|
797
|
+
end
|