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.
Files changed (85) hide show
  1. data/ANTLR-LICENSE.txt +26 -0
  2. data/History.txt +66 -0
  3. data/README.txt +139 -0
  4. data/bin/antlr4ruby +33 -0
  5. data/java/RubyTarget.java +524 -0
  6. data/java/antlr-full-3.2.1.jar +0 -0
  7. data/lib/antlr3.rb +176 -0
  8. data/lib/antlr3/constants.rb +88 -0
  9. data/lib/antlr3/debug.rb +701 -0
  10. data/lib/antlr3/debug/event-hub.rb +210 -0
  11. data/lib/antlr3/debug/record-event-listener.rb +25 -0
  12. data/lib/antlr3/debug/rule-tracer.rb +55 -0
  13. data/lib/antlr3/debug/socket.rb +360 -0
  14. data/lib/antlr3/debug/trace-event-listener.rb +92 -0
  15. data/lib/antlr3/dfa.rb +247 -0
  16. data/lib/antlr3/dot.rb +174 -0
  17. data/lib/antlr3/error.rb +657 -0
  18. data/lib/antlr3/main.rb +561 -0
  19. data/lib/antlr3/modes/ast-builder.rb +41 -0
  20. data/lib/antlr3/modes/filter.rb +56 -0
  21. data/lib/antlr3/profile.rb +322 -0
  22. data/lib/antlr3/recognizers.rb +1280 -0
  23. data/lib/antlr3/streams.rb +985 -0
  24. data/lib/antlr3/streams/interactive.rb +91 -0
  25. data/lib/antlr3/streams/rewrite.rb +412 -0
  26. data/lib/antlr3/test/call-stack.rb +57 -0
  27. data/lib/antlr3/test/config.rb +23 -0
  28. data/lib/antlr3/test/core-extensions.rb +269 -0
  29. data/lib/antlr3/test/diff.rb +165 -0
  30. data/lib/antlr3/test/functional.rb +207 -0
  31. data/lib/antlr3/test/grammar.rb +371 -0
  32. data/lib/antlr3/token.rb +592 -0
  33. data/lib/antlr3/tree.rb +1415 -0
  34. data/lib/antlr3/tree/debug.rb +163 -0
  35. data/lib/antlr3/tree/visitor.rb +84 -0
  36. data/lib/antlr3/tree/wizard.rb +481 -0
  37. data/lib/antlr3/util.rb +149 -0
  38. data/lib/antlr3/version.rb +27 -0
  39. data/samples/ANTLRv3Grammar.g +621 -0
  40. data/samples/Cpp.g +749 -0
  41. data/templates/AST.stg +335 -0
  42. data/templates/ASTDbg.stg +40 -0
  43. data/templates/ASTParser.stg +153 -0
  44. data/templates/ASTTreeParser.stg +272 -0
  45. data/templates/Dbg.stg +192 -0
  46. data/templates/Ruby.stg +1514 -0
  47. data/test/functional/ast-output/auto-ast.rb +797 -0
  48. data/test/functional/ast-output/construction.rb +555 -0
  49. data/test/functional/ast-output/hetero-nodes.rb +753 -0
  50. data/test/functional/ast-output/rewrites.rb +1327 -0
  51. data/test/functional/ast-output/tree-rewrite.rb +1662 -0
  52. data/test/functional/debugging/debug-mode.rb +689 -0
  53. data/test/functional/debugging/profile-mode.rb +165 -0
  54. data/test/functional/debugging/rule-tracing.rb +74 -0
  55. data/test/functional/delegation/import.rb +379 -0
  56. data/test/functional/lexer/basic.rb +559 -0
  57. data/test/functional/lexer/filter-mode.rb +245 -0
  58. data/test/functional/lexer/nuances.rb +47 -0
  59. data/test/functional/lexer/properties.rb +104 -0
  60. data/test/functional/lexer/syn-pred.rb +32 -0
  61. data/test/functional/lexer/xml.rb +206 -0
  62. data/test/functional/main/main-scripts.rb +245 -0
  63. data/test/functional/parser/actions.rb +224 -0
  64. data/test/functional/parser/backtracking.rb +244 -0
  65. data/test/functional/parser/basic.rb +282 -0
  66. data/test/functional/parser/calc.rb +98 -0
  67. data/test/functional/parser/ll-star.rb +143 -0
  68. data/test/functional/parser/nuances.rb +165 -0
  69. data/test/functional/parser/predicates.rb +103 -0
  70. data/test/functional/parser/properties.rb +242 -0
  71. data/test/functional/parser/rule-methods.rb +132 -0
  72. data/test/functional/parser/scopes.rb +274 -0
  73. data/test/functional/token-rewrite/basic.rb +318 -0
  74. data/test/functional/token-rewrite/via-parser.rb +100 -0
  75. data/test/functional/tree-parser/basic.rb +750 -0
  76. data/test/unit/sample-input/file-stream-1 +2 -0
  77. data/test/unit/sample-input/teststreams.input2 +2 -0
  78. data/test/unit/test-dfa.rb +52 -0
  79. data/test/unit/test-exceptions.rb +44 -0
  80. data/test/unit/test-recognizers.rb +55 -0
  81. data/test/unit/test-scheme.rb +62 -0
  82. data/test/unit/test-streams.rb +459 -0
  83. data/test/unit/test-tree-wizard.rb +535 -0
  84. data/test/unit/test-trees.rb +854 -0
  85. 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