antlr3 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
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