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,318 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'antlr3/test/functional'
|
5
|
+
|
6
|
+
class TestRewritingLexerOutputDirectly < ANTLR3::Test::Functional
|
7
|
+
inline_grammar(<<-'END')
|
8
|
+
lexer grammar SimpleRewriting;
|
9
|
+
options {
|
10
|
+
language = Ruby;
|
11
|
+
}
|
12
|
+
|
13
|
+
A: 'a';
|
14
|
+
B: 'b';
|
15
|
+
C: 'c';
|
16
|
+
END
|
17
|
+
|
18
|
+
def rewrite(input, expected)
|
19
|
+
lexer = SimpleRewriting::Lexer.new(input)
|
20
|
+
tokens = ANTLR3::TokenRewriteStream.new(lexer)
|
21
|
+
yield(tokens)
|
22
|
+
tokens.render.should == expected
|
23
|
+
return(tokens)
|
24
|
+
end
|
25
|
+
|
26
|
+
example 'insert before' do
|
27
|
+
rewrite( 'abc', '0abc' ) do |stream|
|
28
|
+
stream.insert_before(0, '0')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
example 'insert after last index' do
|
33
|
+
rewrite( 'abc', 'abcx' ) do |stream|
|
34
|
+
stream.insert_after(2, 'x')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
example 'insert before after middle index' do
|
39
|
+
rewrite( 'abc', 'axbxc' ) do |stream|
|
40
|
+
stream.insert_before 1, 'x'
|
41
|
+
stream.insert_after 1, 'x'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
example 'replace index 0' do
|
46
|
+
rewrite( 'abc', 'xbc' ) do |stream|
|
47
|
+
stream.replace(0, 'x')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
example 'replace last index' do
|
52
|
+
rewrite( 'abc', 'abx' ) do |stream|
|
53
|
+
stream.replace 2, 'x'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
example 'replace last index' do
|
58
|
+
rewrite( 'abc', 'abx' ) do |stream|
|
59
|
+
stream.replace(2, 'x')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
example 'replace middle index' do
|
64
|
+
rewrite( 'abc', 'axc' ) do |stream|
|
65
|
+
stream.replace 1, 'x'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
example 'replace middle index' do
|
70
|
+
rewrite( 'abc', 'ayc' ) do |stream|
|
71
|
+
stream.replace 1, 'x'
|
72
|
+
stream.replace 1, 'y'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
example 'replace middle index 1 insert before' do
|
77
|
+
rewrite( 'abc', '_ayc' ) do |stream|
|
78
|
+
stream.insert_before 0, '_'
|
79
|
+
stream.replace 1, 'x'
|
80
|
+
stream.replace 1, 'y'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
example 'replace then delete middle index' do
|
85
|
+
rewrite( 'abc', 'ac' ) do |stream|
|
86
|
+
stream.replace 1, 'x'
|
87
|
+
stream.delete 1
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
example 'insert then replace same index' do
|
92
|
+
rewrite 'abc', 'xbc' do |stream|
|
93
|
+
stream.insert_before 0, '0'
|
94
|
+
stream.replace 0, 'x'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
example 'insert middle index' do
|
99
|
+
rewrite( "abc", "ayxbc" ) do |stream|
|
100
|
+
stream.insert_before(1, "x")
|
101
|
+
stream.insert_before(1, "y")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
example 'insert then replace index0' do
|
106
|
+
rewrite( "abc", "zbc" ) do |stream|
|
107
|
+
stream.insert_before(0, "x")
|
108
|
+
stream.insert_before(0, "y")
|
109
|
+
stream.replace(0, "z")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
example 'replace then insert before last index' do
|
114
|
+
rewrite( "abc", "abyx" ) do |stream|
|
115
|
+
stream.replace(2, "x")
|
116
|
+
stream.insert_before(2, "y")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
example 'insert then replace last index' do
|
121
|
+
rewrite( "abc", "abx" ) do |stream|
|
122
|
+
stream.insert_before(2, "y")
|
123
|
+
stream.replace(2, "x")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
example 'replace then insert after last index' do
|
128
|
+
rewrite( "abc", "abxy" ) do |stream|
|
129
|
+
stream.replace(2, "x")
|
130
|
+
stream.insert_after(2, "y")
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
example 'replace range then insert at left edge' do
|
135
|
+
rewrite( "abcccba", "abyxba" ) do |stream|
|
136
|
+
stream.replace(2, 4, "x")
|
137
|
+
stream.insert_before(2, "y")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
example 'replace range then insert after right edge' do
|
142
|
+
rewrite( "abcccba", "abxyba" ) do |stream|
|
143
|
+
stream.replace(2, 4, "x")
|
144
|
+
stream.insert_after(4, "y")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
example 'replace all' do
|
149
|
+
rewrite( "abcccba", "x" ) do |stream|
|
150
|
+
stream.replace(0, 6, "x")
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
example 'replace single middle then overlapping superset' do
|
155
|
+
rewrite( "abcba", "fooa" ) do |stream|
|
156
|
+
stream.replace(2, 2, "xyz")
|
157
|
+
stream.replace(0, 3, "foo")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
example 'combine inserts' do
|
162
|
+
rewrite( "abc", "yxabc" ) do |stream|
|
163
|
+
stream.insert_before(0, "x")
|
164
|
+
stream.insert_before(0, "y")
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
example 'combine3 inserts' do
|
169
|
+
rewrite( "abc", "yazxbc" ) do |stream|
|
170
|
+
stream.insert_before(1, "x")
|
171
|
+
stream.insert_before(0, "y")
|
172
|
+
stream.insert_before(1, "z")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
example 'disjoint inserts' do
|
177
|
+
rewrite( "abc", "zaxbyc" ) do |stream|
|
178
|
+
stream.insert_before(1, "x")
|
179
|
+
stream.insert_before(2, "y")
|
180
|
+
stream.insert_before(0, "z")
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
example 'leave alone disjoint insert' do
|
185
|
+
rewrite( "abcc", "axbfoo" ) do |stream|
|
186
|
+
stream.insert_before(1, "x")
|
187
|
+
stream.replace(2, 3, "foo")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
example 'leave alone disjoint insert2' do
|
192
|
+
rewrite( "abcc", "axbfoo" ) do |stream|
|
193
|
+
stream.replace(2, 3, "foo")
|
194
|
+
stream.insert_before(1, "x")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
example 'combine insert on left with delete' do
|
199
|
+
rewrite( "abc", "z" ) do |stream|
|
200
|
+
stream.delete(0, 2)
|
201
|
+
stream.insert_before(0, "z")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
example 'overlapping replace' do
|
206
|
+
rewrite( "abcc", "bar" ) do |stream|
|
207
|
+
stream.replace(1, 2, "foo")
|
208
|
+
stream.replace(0, 3, "bar")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
example 'overlapping replace3' do
|
213
|
+
rewrite( "abcc", "barc" ) do |stream|
|
214
|
+
stream.replace(1, 2, "foo")
|
215
|
+
stream.replace(0, 2, "bar")
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
example 'overlapping replace 4' do
|
220
|
+
rewrite( "abcc", "abar" ) do |stream|
|
221
|
+
stream.replace(1, 2, "foo")
|
222
|
+
stream.replace(1, 3, "bar")
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
example 'overlapping replace 2' do
|
227
|
+
lexer = SimpleRewriting::Lexer.new( 'abcc' )
|
228
|
+
stream = ANTLR3::TokenRewriteStream.new( lexer )
|
229
|
+
stream.replace 0, 3, 'bar'
|
230
|
+
stream.replace 1, 2, 'foo'
|
231
|
+
|
232
|
+
lambda { stream.render }.
|
233
|
+
should raise_error { |error|
|
234
|
+
error.to_s.should == %q<operation (replace @ 1..2 : "foo") overlaps with previous operation (replace @ 0..3 : "bar")>
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
example 'replace range then insert at right edge' do
|
239
|
+
lexer = SimpleRewriting::Lexer.new( 'abcccba' )
|
240
|
+
stream = ANTLR3::TokenRewriteStream.new( lexer )
|
241
|
+
stream.replace 2, 4, 'x'
|
242
|
+
stream.insert_before 4, 'y'
|
243
|
+
lambda { stream.render }.
|
244
|
+
should raise_error { |error|
|
245
|
+
error.to_s.should == %q<operation (insert-before @ 4 : "y") overlaps with previous operation (replace @ 2..4 : "x")>
|
246
|
+
}
|
247
|
+
end
|
248
|
+
|
249
|
+
example 'replace then replace superset' do
|
250
|
+
lexer = SimpleRewriting::Lexer.new( 'abcccba' )
|
251
|
+
stream = ANTLR3::TokenRewriteStream.new( lexer )
|
252
|
+
stream.replace 2, 4, 'xyz'
|
253
|
+
stream.replace 3, 5, 'foo'
|
254
|
+
lambda { stream.render }.
|
255
|
+
should raise_error { |error|
|
256
|
+
error.to_s.should == %q<operation (replace @ 3..5 : "foo") overlaps with previous operation (replace @ 2..4 : "xyz")>
|
257
|
+
}
|
258
|
+
end
|
259
|
+
|
260
|
+
example 'replace then replace lower indexed superset' do
|
261
|
+
lexer = SimpleRewriting::Lexer.new( 'abcccba' )
|
262
|
+
stream = ANTLR3::TokenRewriteStream.new( lexer )
|
263
|
+
stream.replace 2, 4, 'xyz'
|
264
|
+
stream.replace 1, 3, 'foo'
|
265
|
+
lambda { stream.render }.
|
266
|
+
should raise_error { |error|
|
267
|
+
error.to_s.should == %q<operation (replace @ 1..3 : "foo") overlaps with previous operation (replace @ 2..4 : "xyz")>
|
268
|
+
}
|
269
|
+
end
|
270
|
+
|
271
|
+
end
|
272
|
+
|
273
|
+
class TestRewritingWithTokenStream2 < ANTLR3::Test::Functional
|
274
|
+
inline_grammar( <<-END )
|
275
|
+
lexer grammar SimpleRewriting2;
|
276
|
+
options {
|
277
|
+
language = Ruby;
|
278
|
+
}
|
279
|
+
|
280
|
+
ID : 'a'..'z'+;
|
281
|
+
INT : '0'..'9'+;
|
282
|
+
SEMI : ';';
|
283
|
+
PLUS : '+';
|
284
|
+
MUL : '*';
|
285
|
+
ASSIGN : '=';
|
286
|
+
WS : ' '+;
|
287
|
+
END
|
288
|
+
|
289
|
+
def rewrite(input)
|
290
|
+
lexer = SimpleRewriting2::Lexer.new(input)
|
291
|
+
ANTLR3::TokenRewriteStream.new(lexer)
|
292
|
+
end
|
293
|
+
|
294
|
+
example 'rendering over a range' do
|
295
|
+
stream = rewrite 'x = 3 * 0;'
|
296
|
+
stream.replace 4, 8, '0'
|
297
|
+
stream.original_string.should == 'x = 3 * 0;'
|
298
|
+
stream.render.should == 'x = 0;'
|
299
|
+
stream.render(0, 9).should == 'x = 0;'
|
300
|
+
stream.render(4, 8).should == '0'
|
301
|
+
end
|
302
|
+
|
303
|
+
example 'more rendering over a range' do
|
304
|
+
stream = rewrite 'x = 3 * 0 + 2 * 0;'
|
305
|
+
stream.original_string.should == 'x = 3 * 0 + 2 * 0;'
|
306
|
+
stream.replace 4, 8, '0'
|
307
|
+
stream.render.should == 'x = 0 + 2 * 0;'
|
308
|
+
stream.render(0, 17).should == 'x = 0 + 2 * 0;'
|
309
|
+
stream.render(4, 8).should == '0'
|
310
|
+
stream.render(0, 8).should == 'x = 0'
|
311
|
+
stream.render(12, 16).should == '2 * 0'
|
312
|
+
stream.insert_after(17, '// comment')
|
313
|
+
stream.render(12, 17).should == '2 * 0;// comment'
|
314
|
+
stream.render(0, 8).should == 'x = 0'
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|
318
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'antlr3/test/functional'
|
5
|
+
|
6
|
+
class TestRewritingWhileParsing < ANTLR3::Test::Functional
|
7
|
+
|
8
|
+
inline_grammar(<<-'END')
|
9
|
+
grammar TokenRewrites;
|
10
|
+
options { language = Ruby; }
|
11
|
+
|
12
|
+
program
|
13
|
+
@after {
|
14
|
+
@input.insert_before($start,"public class Wrapper {\n")
|
15
|
+
@input.insert_after($stop, "\n}\n")
|
16
|
+
}
|
17
|
+
: method+
|
18
|
+
;
|
19
|
+
|
20
|
+
method
|
21
|
+
: m='method' ID '(' ')' body
|
22
|
+
{@input.replace($m, "public void");}
|
23
|
+
;
|
24
|
+
|
25
|
+
body
|
26
|
+
scope {
|
27
|
+
decls
|
28
|
+
}
|
29
|
+
@init {
|
30
|
+
$body::decls = []
|
31
|
+
}
|
32
|
+
: lcurly='{' stat* '}'
|
33
|
+
{
|
34
|
+
$body::decls.uniq!
|
35
|
+
for it in $body::decls
|
36
|
+
@input.insert_after($lcurly, "\nint "+it+";")
|
37
|
+
end
|
38
|
+
}
|
39
|
+
;
|
40
|
+
|
41
|
+
stat: ID '=' expr ';' {$body::decls << $ID.text.to_s}
|
42
|
+
;
|
43
|
+
|
44
|
+
expr: mul ('+' mul)*
|
45
|
+
;
|
46
|
+
|
47
|
+
mul : atom ('*' atom)*
|
48
|
+
;
|
49
|
+
|
50
|
+
atom: ID
|
51
|
+
| INT
|
52
|
+
;
|
53
|
+
|
54
|
+
ID : ('a'..'z'|'A'..'Z')+ ;
|
55
|
+
|
56
|
+
INT : ('0'..'9')+ ;
|
57
|
+
|
58
|
+
WS : (' '|'\t'|'\n')+ {$channel=HIDDEN;}
|
59
|
+
;
|
60
|
+
END
|
61
|
+
|
62
|
+
example 'using a TokenRewriteStream to rewrite input text while parsing' do
|
63
|
+
input = <<-END.fixed_indent(0)
|
64
|
+
method foo() {
|
65
|
+
i = 3;
|
66
|
+
k = i;
|
67
|
+
i = k*4;
|
68
|
+
}
|
69
|
+
|
70
|
+
method bar() {
|
71
|
+
j = i*2;
|
72
|
+
}
|
73
|
+
END
|
74
|
+
expected_output = <<-END.fixed_indent(0).strip!
|
75
|
+
public class Wrapper {
|
76
|
+
public void foo() {
|
77
|
+
int k;
|
78
|
+
int i;
|
79
|
+
i = 3;
|
80
|
+
k = i;
|
81
|
+
i = k*4;
|
82
|
+
}
|
83
|
+
|
84
|
+
public void bar() {
|
85
|
+
int j;
|
86
|
+
j = i*2;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
END
|
90
|
+
|
91
|
+
lexer = TokenRewrites::Lexer.new( input )
|
92
|
+
tokens = ANTLR3::TokenRewriteStream.new( lexer )
|
93
|
+
parser = TokenRewrites::Parser.new( tokens )
|
94
|
+
parser.program
|
95
|
+
|
96
|
+
tokens.render.strip.should == expected_output
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,750 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'antlr3/test/functional'
|
5
|
+
|
6
|
+
class TestTreeParser1 < ANTLR3::Test::Functional
|
7
|
+
|
8
|
+
example "flat list" do
|
9
|
+
compile_and_load inline_grammar(<<-'END')
|
10
|
+
grammar FlatList;
|
11
|
+
options {
|
12
|
+
language=Ruby;
|
13
|
+
output=AST;
|
14
|
+
}
|
15
|
+
a : ID INT;
|
16
|
+
ID : 'a'..'z'+ ;
|
17
|
+
INT : '0'..'9'+;
|
18
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
19
|
+
END
|
20
|
+
compile_and_load inline_grammar(<<-'END')
|
21
|
+
tree grammar FlatListWalker;
|
22
|
+
options {
|
23
|
+
language=Ruby;
|
24
|
+
ASTLabelType=CommonTree;
|
25
|
+
}
|
26
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
27
|
+
a : ID INT
|
28
|
+
{self.capture("\%s, \%s" \% [$ID, $INT])}
|
29
|
+
;
|
30
|
+
END
|
31
|
+
|
32
|
+
lexer = FlatList::Lexer.new( "abc 34" )
|
33
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
34
|
+
parser = FlatList::Parser.new( tokens )
|
35
|
+
|
36
|
+
result = parser.a
|
37
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
38
|
+
nodes.token_stream = tokens
|
39
|
+
walker = FlatListWalker::TreeParser.new( nodes )
|
40
|
+
walker.a
|
41
|
+
walker.output.should == "abc, 34"
|
42
|
+
end
|
43
|
+
|
44
|
+
example "simple tree" do
|
45
|
+
compile_and_load inline_grammar(<<-'END')
|
46
|
+
grammar SimpleTree;
|
47
|
+
options {
|
48
|
+
language=Ruby;
|
49
|
+
output=AST;
|
50
|
+
}
|
51
|
+
a : ID INT -> ^(ID INT);
|
52
|
+
ID : 'a'..'z'+ ;
|
53
|
+
INT : '0'..'9'+;
|
54
|
+
WS : (' '|'\\n') {$channel=HIDDEN;} ;
|
55
|
+
END
|
56
|
+
compile_and_load inline_grammar(<<-'END')
|
57
|
+
tree grammar SimpleTreeWalker;
|
58
|
+
options {
|
59
|
+
language=Ruby;
|
60
|
+
ASTLabelType=CommonTree;
|
61
|
+
}
|
62
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
63
|
+
|
64
|
+
a : ^(ID INT)
|
65
|
+
{capture('\%s, \%s' \% [$ID, $INT])}
|
66
|
+
;
|
67
|
+
END
|
68
|
+
lexer = SimpleTree::Lexer.new( "abc 34" )
|
69
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
70
|
+
parser = SimpleTree::Parser.new( tokens )
|
71
|
+
|
72
|
+
result = parser.a
|
73
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
74
|
+
nodes.token_stream = tokens
|
75
|
+
walker = SimpleTreeWalker::TreeParser.new( nodes )
|
76
|
+
walker.a
|
77
|
+
walker.output.should == "abc, 34"
|
78
|
+
end
|
79
|
+
|
80
|
+
example "flat vs tree decision" do
|
81
|
+
compile_and_load inline_grammar(<<-'END')
|
82
|
+
grammar FlatVsTreeDecision;
|
83
|
+
options {
|
84
|
+
language=Ruby;
|
85
|
+
output=AST;
|
86
|
+
}
|
87
|
+
a : b c ;
|
88
|
+
b : ID INT -> ^(ID INT);
|
89
|
+
c : ID INT;
|
90
|
+
ID : 'a'..'z'+ ;
|
91
|
+
INT : '0'..'9'+;
|
92
|
+
WS : (' '|'\\n') {$channel=HIDDEN;} ;
|
93
|
+
END
|
94
|
+
compile_and_load inline_grammar(<<-'END')
|
95
|
+
tree grammar FlatVsTreeDecisionWalker;
|
96
|
+
options {
|
97
|
+
language=Ruby;
|
98
|
+
ASTLabelType=CommonTree;
|
99
|
+
}
|
100
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
101
|
+
|
102
|
+
a : b b ;
|
103
|
+
b : ID INT {capture("\%s \%s\n" \% [$ID, $INT])}
|
104
|
+
| ^(ID INT) {capture("^(\%s \%s)" \% [$ID, $INT])}
|
105
|
+
;
|
106
|
+
END
|
107
|
+
lexer = FlatVsTreeDecision::Lexer.new( "a 1 b 2" )
|
108
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
109
|
+
parser = FlatVsTreeDecision::Parser.new( tokens )
|
110
|
+
|
111
|
+
result = parser.a
|
112
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
113
|
+
nodes.token_stream = tokens
|
114
|
+
walker = FlatVsTreeDecisionWalker::TreeParser.new( nodes )
|
115
|
+
walker.a
|
116
|
+
walker.output.should == "^(a 1)b 2\n"
|
117
|
+
end
|
118
|
+
|
119
|
+
example "flat vs tree decision2" do
|
120
|
+
compile_and_load inline_grammar(<<-'END')
|
121
|
+
grammar FlatVsTreeDecision2;
|
122
|
+
options {
|
123
|
+
language=Ruby;
|
124
|
+
output=AST;
|
125
|
+
}
|
126
|
+
a : b c ;
|
127
|
+
b : ID INT+ -> ^(ID INT+);
|
128
|
+
c : ID INT+;
|
129
|
+
ID : 'a'..'z'+ ;
|
130
|
+
INT : '0'..'9'+;
|
131
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
132
|
+
END
|
133
|
+
compile_and_load inline_grammar(<<-'END')
|
134
|
+
tree grammar FlatVsTreeDecision2Walker;
|
135
|
+
options {
|
136
|
+
language=Ruby;
|
137
|
+
ASTLabelType=CommonTree;
|
138
|
+
}
|
139
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
140
|
+
a : b b ;
|
141
|
+
b : ID INT+ {say("#{$ID} #{$INT}")}
|
142
|
+
| ^(x=ID (y=INT)+) {capture("^(#{$x} #{$y})")}
|
143
|
+
;
|
144
|
+
END
|
145
|
+
lexer = FlatVsTreeDecision2::Lexer.new( "a 1 2 3 b 4 5" )
|
146
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
147
|
+
parser = FlatVsTreeDecision2::Parser.new( tokens )
|
148
|
+
|
149
|
+
result = parser.a
|
150
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
151
|
+
nodes.token_stream = tokens
|
152
|
+
walker = FlatVsTreeDecision2Walker::TreeParser.new( nodes )
|
153
|
+
walker.a
|
154
|
+
walker.output.should == "^(a 3)b 5\n"
|
155
|
+
end
|
156
|
+
|
157
|
+
example "cyclic dfa lookahead" do
|
158
|
+
compile_and_load inline_grammar(<<-'END')
|
159
|
+
grammar CyclicDFALookahead;
|
160
|
+
options {
|
161
|
+
language=Ruby;
|
162
|
+
output=AST;
|
163
|
+
}
|
164
|
+
a : ID INT+ PERIOD;
|
165
|
+
ID : 'a'..'z'+ ;
|
166
|
+
INT : '0'..'9'+;
|
167
|
+
SEMI : ';' ;
|
168
|
+
PERIOD : '.' ;
|
169
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
170
|
+
END
|
171
|
+
compile_and_load inline_grammar(<<-'END')
|
172
|
+
tree grammar CyclicDFALookaheadWalker;
|
173
|
+
options {
|
174
|
+
language=Ruby;
|
175
|
+
ASTLabelType=CommonTree;
|
176
|
+
}
|
177
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
178
|
+
a : ID INT+ PERIOD {capture("alt 1")}
|
179
|
+
| ID INT+ SEMI {capture("alt 2")}
|
180
|
+
;
|
181
|
+
END
|
182
|
+
lexer = CyclicDFALookahead::Lexer.new( "a 1 2 3." )
|
183
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
184
|
+
parser = CyclicDFALookahead::Parser.new( tokens )
|
185
|
+
|
186
|
+
result = parser.a
|
187
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
188
|
+
nodes.token_stream = tokens
|
189
|
+
walker = CyclicDFALookaheadWalker::TreeParser.new( nodes )
|
190
|
+
walker.a
|
191
|
+
walker.output.should == "alt 1"
|
192
|
+
end
|
193
|
+
|
194
|
+
example "nullable child list" do
|
195
|
+
compile_and_load inline_grammar(<<-'END')
|
196
|
+
grammar NullableChildList;
|
197
|
+
options {
|
198
|
+
language=Ruby;
|
199
|
+
output=AST;
|
200
|
+
}
|
201
|
+
a : ID INT? -> ^(ID INT?);
|
202
|
+
ID : 'a'..'z'+ ;
|
203
|
+
INT : '0'..'9'+;
|
204
|
+
WS : (' '|'\\n') {$channel=HIDDEN;} ;
|
205
|
+
END
|
206
|
+
compile_and_load inline_grammar(<<-'END')
|
207
|
+
tree grammar NullableChildListWalker;
|
208
|
+
options {
|
209
|
+
language=Ruby;
|
210
|
+
ASTLabelType=CommonTree;
|
211
|
+
}
|
212
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
213
|
+
a : ^(ID INT?)
|
214
|
+
{capture($ID.to_s)}
|
215
|
+
;
|
216
|
+
END
|
217
|
+
lexer = NullableChildList::Lexer.new( "abc" )
|
218
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
219
|
+
parser = NullableChildList::Parser.new( tokens )
|
220
|
+
|
221
|
+
result = parser.a
|
222
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
223
|
+
nodes.token_stream = tokens
|
224
|
+
walker = NullableChildListWalker::TreeParser.new( nodes )
|
225
|
+
walker.a
|
226
|
+
walker.output.should == "abc"
|
227
|
+
end
|
228
|
+
|
229
|
+
example "nullable child list2" do
|
230
|
+
compile_and_load inline_grammar(<<-'END')
|
231
|
+
grammar NullableChildList2;
|
232
|
+
options {
|
233
|
+
language=Ruby;
|
234
|
+
output=AST;
|
235
|
+
}
|
236
|
+
a : ID INT? SEMI -> ^(ID INT?) SEMI ;
|
237
|
+
ID : 'a'..'z'+ ;
|
238
|
+
INT : '0'..'9'+;
|
239
|
+
SEMI : ';' ;
|
240
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
241
|
+
END
|
242
|
+
compile_and_load inline_grammar(<<-'END')
|
243
|
+
tree grammar NullableChildList2Walker;
|
244
|
+
options {
|
245
|
+
language=Ruby;
|
246
|
+
ASTLabelType=CommonTree;
|
247
|
+
}
|
248
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
249
|
+
a : ^(ID INT?) SEMI
|
250
|
+
{capture($ID.to_s)}
|
251
|
+
;
|
252
|
+
END
|
253
|
+
lexer = NullableChildList2::Lexer.new( "abc;" )
|
254
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
255
|
+
parser = NullableChildList2::Parser.new( tokens )
|
256
|
+
|
257
|
+
result = parser.a
|
258
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
259
|
+
nodes.token_stream = tokens
|
260
|
+
walker = NullableChildList2Walker::TreeParser.new( nodes )
|
261
|
+
walker.a
|
262
|
+
walker.output.should == "abc"
|
263
|
+
end
|
264
|
+
|
265
|
+
example "nullable child list3" do
|
266
|
+
compile_and_load inline_grammar(<<-'END')
|
267
|
+
grammar NullableChildList3;
|
268
|
+
options {
|
269
|
+
language=Ruby;
|
270
|
+
output=AST;
|
271
|
+
}
|
272
|
+
a : x=ID INT? (y=ID)? SEMI -> ^($x INT? $y?) SEMI ;
|
273
|
+
ID : 'a'..'z'+ ;
|
274
|
+
INT : '0'..'9'+;
|
275
|
+
SEMI : ';' ;
|
276
|
+
WS : (' '|'\\n') {$channel=HIDDEN;} ;
|
277
|
+
END
|
278
|
+
compile_and_load inline_grammar(<<-'END')
|
279
|
+
tree grammar NullableChildList3Walker;
|
280
|
+
options {
|
281
|
+
language=Ruby;
|
282
|
+
ASTLabelType=CommonTree;
|
283
|
+
}
|
284
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
285
|
+
a : ^(ID INT? b) SEMI
|
286
|
+
{self.capture($ID.to_s + ", " + $b.text.to_s)}
|
287
|
+
;
|
288
|
+
b : ID? ;
|
289
|
+
END
|
290
|
+
lexer = NullableChildList3::Lexer.new( "abc def;" )
|
291
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
292
|
+
parser = NullableChildList3::Parser.new( tokens )
|
293
|
+
|
294
|
+
result = parser.a
|
295
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
296
|
+
nodes.token_stream = tokens
|
297
|
+
walker = NullableChildList3Walker::TreeParser.new( nodes )
|
298
|
+
walker.a
|
299
|
+
walker.output.should == "abc, def"
|
300
|
+
end
|
301
|
+
|
302
|
+
example "actions after root" do
|
303
|
+
compile_and_load inline_grammar(<<-'END')
|
304
|
+
grammar ActionsAfterRoot;
|
305
|
+
options {
|
306
|
+
language=Ruby;
|
307
|
+
output=AST;
|
308
|
+
}
|
309
|
+
a : x=ID INT? SEMI -> ^($x INT?) ;
|
310
|
+
ID : 'a'..'z'+ ;
|
311
|
+
INT : '0'..'9'+;
|
312
|
+
SEMI : ';' ;
|
313
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
314
|
+
END
|
315
|
+
compile_and_load inline_grammar(<<-'END')
|
316
|
+
tree grammar ActionsAfterRootWalker;
|
317
|
+
options {
|
318
|
+
language=Ruby;
|
319
|
+
ASTLabelType=CommonTree;
|
320
|
+
}
|
321
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
322
|
+
a @init {x=0} : ^(ID {x=1} {x=2} INT?)
|
323
|
+
{say( $ID.to_s + ", " + x.to_s )}
|
324
|
+
;
|
325
|
+
END
|
326
|
+
lexer = ActionsAfterRoot::Lexer.new( "abc;" )
|
327
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
328
|
+
parser = ActionsAfterRoot::Parser.new( tokens )
|
329
|
+
|
330
|
+
result = parser.a
|
331
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
332
|
+
nodes.token_stream = tokens
|
333
|
+
walker = ActionsAfterRootWalker::TreeParser.new( nodes )
|
334
|
+
walker.a
|
335
|
+
walker.output.should == "abc, 2\n"
|
336
|
+
end
|
337
|
+
|
338
|
+
example "wildcard lookahead" do
|
339
|
+
compile_and_load inline_grammar(<<-'END')
|
340
|
+
grammar WildcardLookahead;
|
341
|
+
options {language=Ruby; output=AST;}
|
342
|
+
a : ID '+'^ INT;
|
343
|
+
ID : 'a'..'z'+ ;
|
344
|
+
INT : '0'..'9'+;
|
345
|
+
SEMI : ';' ;
|
346
|
+
PERIOD : '.' ;
|
347
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
348
|
+
END
|
349
|
+
compile_and_load inline_grammar(<<-'END')
|
350
|
+
tree grammar WildcardLookaheadWalker;
|
351
|
+
options {language=Ruby; tokenVocab=WildcardLookahead; ASTLabelType=CommonTree;}
|
352
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
353
|
+
a : ^('+' . INT) { capture("alt 1") }
|
354
|
+
;
|
355
|
+
END
|
356
|
+
lexer = WildcardLookahead::Lexer.new( "a + 2" )
|
357
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
358
|
+
parser = WildcardLookahead::Parser.new( tokens )
|
359
|
+
|
360
|
+
result = parser.a
|
361
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
362
|
+
nodes.token_stream = tokens
|
363
|
+
walker = WildcardLookaheadWalker::TreeParser.new( nodes )
|
364
|
+
walker.a
|
365
|
+
walker.output.should == "alt 1"
|
366
|
+
end
|
367
|
+
|
368
|
+
example "wildcard lookahead2" do
|
369
|
+
compile_and_load inline_grammar(<<-'END')
|
370
|
+
grammar WildcardLookahead2;
|
371
|
+
options {language=Ruby; output=AST;}
|
372
|
+
a : ID '+'^ INT;
|
373
|
+
ID : 'a'..'z'+ ;
|
374
|
+
INT : '0'..'9'+;
|
375
|
+
SEMI : ';' ;
|
376
|
+
PERIOD : '.' ;
|
377
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
378
|
+
END
|
379
|
+
compile_and_load inline_grammar(<<-'END')
|
380
|
+
tree grammar WildcardLookahead2Walker;
|
381
|
+
options {language=Ruby; tokenVocab=WildcardLookahead2; ASTLabelType=CommonTree;}
|
382
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
383
|
+
a : ^('+' . INT) { capture("alt 1") }
|
384
|
+
| ^('+' . .) { capture("alt 2") }
|
385
|
+
;
|
386
|
+
END
|
387
|
+
lexer = WildcardLookahead2::Lexer.new( "a + 2" )
|
388
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
389
|
+
parser = WildcardLookahead2::Parser.new( tokens )
|
390
|
+
|
391
|
+
result = parser.a
|
392
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
393
|
+
nodes.token_stream = tokens
|
394
|
+
walker = WildcardLookahead2Walker::TreeParser.new( nodes )
|
395
|
+
walker.a
|
396
|
+
walker.output.should == "alt 1"
|
397
|
+
end
|
398
|
+
|
399
|
+
example "wildcard lookahead3" do
|
400
|
+
compile_and_load inline_grammar(<<-'END')
|
401
|
+
grammar WildcardLookahead3;
|
402
|
+
options {language=Ruby; output=AST;}
|
403
|
+
a : ID '+'^ INT;
|
404
|
+
ID : 'a'..'z'+ ;
|
405
|
+
INT : '0'..'9'+;
|
406
|
+
SEMI : ';' ;
|
407
|
+
PERIOD : '.' ;
|
408
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
409
|
+
END
|
410
|
+
compile_and_load inline_grammar(<<-'END')
|
411
|
+
tree grammar WildcardLookahead3Walker;
|
412
|
+
options {language=Ruby; tokenVocab=WildcardLookahead3; ASTLabelType=CommonTree;}
|
413
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
414
|
+
a : ^('+' ID INT) { capture("alt 1") }
|
415
|
+
| ^('+' . .) { capture("alt 2") }
|
416
|
+
;
|
417
|
+
END
|
418
|
+
lexer = WildcardLookahead3::Lexer.new( "a + 2" )
|
419
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
420
|
+
parser = WildcardLookahead3::Parser.new( tokens )
|
421
|
+
|
422
|
+
result = parser.a
|
423
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
424
|
+
nodes.token_stream = tokens
|
425
|
+
walker = WildcardLookahead3Walker::TreeParser.new( nodes )
|
426
|
+
walker.a
|
427
|
+
walker.output.should == "alt 1"
|
428
|
+
end
|
429
|
+
|
430
|
+
example "wildcard plus lookahead" do
|
431
|
+
compile_and_load inline_grammar(<<-'END')
|
432
|
+
grammar WildcardPlusLookahead;
|
433
|
+
options {language=Ruby; output=AST;}
|
434
|
+
a : ID '+'^ INT;
|
435
|
+
ID : 'a'..'z'+ ;
|
436
|
+
INT : '0'..'9'+;
|
437
|
+
SEMI : ';' ;
|
438
|
+
PERIOD : '.' ;
|
439
|
+
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
440
|
+
END
|
441
|
+
compile_and_load inline_grammar(<<-'END')
|
442
|
+
tree grammar WildcardPlusLookaheadWalker;
|
443
|
+
options {language=Ruby; tokenVocab=WildcardPlusLookahead; ASTLabelType=CommonTree;}
|
444
|
+
@members { include ANTLR3::Test::CaptureOutput }
|
445
|
+
a : ^('+' INT INT ) { capture("alt 1") }
|
446
|
+
| ^('+' .+) { capture("alt 2") }
|
447
|
+
;
|
448
|
+
END
|
449
|
+
lexer = WildcardPlusLookahead::Lexer.new( "a + 2" )
|
450
|
+
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
451
|
+
parser = WildcardPlusLookahead::Parser.new( tokens )
|
452
|
+
|
453
|
+
result = parser.a
|
454
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
455
|
+
nodes.token_stream = tokens
|
456
|
+
walker = WildcardPlusLookaheadWalker::TreeParser.new( nodes )
|
457
|
+
walker.a
|
458
|
+
walker.output.should == "alt 2"
|
459
|
+
end
|
460
|
+
|
461
|
+
end
|
462
|
+
|
463
|
+
|
464
|
+
class TestTreeParser2 < ANTLR3::Test::Functional
|
465
|
+
inline_grammar(<<-'END')
|
466
|
+
grammar GenericLanguage;
|
467
|
+
options {
|
468
|
+
language = Ruby;
|
469
|
+
output=AST;
|
470
|
+
}
|
471
|
+
|
472
|
+
tokens {
|
473
|
+
VAR_DEF;
|
474
|
+
ARG_DEF;
|
475
|
+
FUNC_HDR;
|
476
|
+
FUNC_DECL;
|
477
|
+
FUNC_DEF;
|
478
|
+
BLOCK;
|
479
|
+
}
|
480
|
+
|
481
|
+
program
|
482
|
+
: declaration+
|
483
|
+
;
|
484
|
+
|
485
|
+
declaration
|
486
|
+
: variable
|
487
|
+
| functionHeader ';' -> ^(FUNC_DECL functionHeader)
|
488
|
+
| functionHeader block -> ^(FUNC_DEF functionHeader block)
|
489
|
+
;
|
490
|
+
|
491
|
+
variable
|
492
|
+
: type declarator ';' -> ^(VAR_DEF type declarator)
|
493
|
+
;
|
494
|
+
|
495
|
+
declarator
|
496
|
+
: ID
|
497
|
+
;
|
498
|
+
|
499
|
+
functionHeader
|
500
|
+
: type ID '(' ( formalParameter ( ',' formalParameter )* )? ')'
|
501
|
+
-> ^(FUNC_HDR type ID formalParameter+)
|
502
|
+
;
|
503
|
+
|
504
|
+
formalParameter
|
505
|
+
: type declarator -> ^(ARG_DEF type declarator)
|
506
|
+
;
|
507
|
+
|
508
|
+
type
|
509
|
+
: 'int'
|
510
|
+
| 'char'
|
511
|
+
| 'void'
|
512
|
+
| ID
|
513
|
+
;
|
514
|
+
|
515
|
+
block
|
516
|
+
: lc='{'
|
517
|
+
variable*
|
518
|
+
stat*
|
519
|
+
'}'
|
520
|
+
-> ^(BLOCK[$lc,"BLOCK"] variable* stat*)
|
521
|
+
;
|
522
|
+
|
523
|
+
stat: forStat
|
524
|
+
| expr ';'!
|
525
|
+
| block
|
526
|
+
| assignStat ';'!
|
527
|
+
| ';'!
|
528
|
+
;
|
529
|
+
|
530
|
+
forStat
|
531
|
+
: 'for' '(' start=assignStat ';' expr ';' next=assignStat ')' block
|
532
|
+
-> ^('for' $start expr $next block)
|
533
|
+
;
|
534
|
+
|
535
|
+
assignStat
|
536
|
+
: ID EQ expr -> ^(EQ ID expr)
|
537
|
+
;
|
538
|
+
|
539
|
+
expr: condExpr
|
540
|
+
;
|
541
|
+
|
542
|
+
condExpr
|
543
|
+
: aexpr ( ('=='^ | '<'^) aexpr )?
|
544
|
+
;
|
545
|
+
|
546
|
+
aexpr
|
547
|
+
: atom ( '+'^ atom )*
|
548
|
+
;
|
549
|
+
|
550
|
+
atom
|
551
|
+
: ID
|
552
|
+
| INT
|
553
|
+
| '(' expr ')' -> expr
|
554
|
+
;
|
555
|
+
|
556
|
+
FOR : 'for' ;
|
557
|
+
INT_TYPE : 'int' ;
|
558
|
+
CHAR: 'char';
|
559
|
+
VOID: 'void';
|
560
|
+
|
561
|
+
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
|
562
|
+
;
|
563
|
+
|
564
|
+
INT : ('0'..'9')+
|
565
|
+
;
|
566
|
+
|
567
|
+
EQ : '=' ;
|
568
|
+
EQEQ : '==' ;
|
569
|
+
LT : '<' ;
|
570
|
+
PLUS : '+' ;
|
571
|
+
|
572
|
+
WS : ( ' '
|
573
|
+
| '\t'
|
574
|
+
| '\r'
|
575
|
+
| '\n'
|
576
|
+
)+
|
577
|
+
{ $channel=HIDDEN }
|
578
|
+
;
|
579
|
+
END
|
580
|
+
|
581
|
+
inline_grammar(<<-'END')
|
582
|
+
tree grammar GenericLanguageWalker;
|
583
|
+
options {
|
584
|
+
language = Ruby;
|
585
|
+
tokenVocab = GenericLanguage;
|
586
|
+
ASTLabelType = CommonTree;
|
587
|
+
}
|
588
|
+
|
589
|
+
@init { @traces = [] }
|
590
|
+
@members {
|
591
|
+
attr_reader :traces
|
592
|
+
|
593
|
+
def trace_in(rule_name, rule_index)
|
594
|
+
@traces << ">#{rule_name}"
|
595
|
+
end
|
596
|
+
|
597
|
+
def trace_out(rule_name, rule_index)
|
598
|
+
@traces << "<#{rule_name}"
|
599
|
+
end
|
600
|
+
}
|
601
|
+
|
602
|
+
program
|
603
|
+
: declaration+
|
604
|
+
;
|
605
|
+
|
606
|
+
declaration
|
607
|
+
: variable
|
608
|
+
| ^(FUNC_DECL functionHeader)
|
609
|
+
| ^(FUNC_DEF functionHeader block)
|
610
|
+
;
|
611
|
+
|
612
|
+
variable returns [res]
|
613
|
+
: ^(VAR_DEF type declarator)
|
614
|
+
{
|
615
|
+
$res = $declarator.text;
|
616
|
+
}
|
617
|
+
;
|
618
|
+
|
619
|
+
declarator
|
620
|
+
: ID
|
621
|
+
;
|
622
|
+
|
623
|
+
functionHeader
|
624
|
+
: ^(FUNC_HDR type ID formalParameter+)
|
625
|
+
;
|
626
|
+
|
627
|
+
formalParameter
|
628
|
+
: ^(ARG_DEF type declarator)
|
629
|
+
;
|
630
|
+
|
631
|
+
type
|
632
|
+
: 'int'
|
633
|
+
| 'char'
|
634
|
+
| 'void'
|
635
|
+
| ID
|
636
|
+
;
|
637
|
+
|
638
|
+
block
|
639
|
+
: ^(BLOCK variable* stat*)
|
640
|
+
;
|
641
|
+
|
642
|
+
stat: forStat
|
643
|
+
| expr
|
644
|
+
| block
|
645
|
+
;
|
646
|
+
|
647
|
+
forStat
|
648
|
+
: ^('for' expr expr expr block)
|
649
|
+
;
|
650
|
+
|
651
|
+
expr: ^(EQEQ expr expr)
|
652
|
+
| ^(LT expr expr)
|
653
|
+
| ^(PLUS expr expr)
|
654
|
+
| ^(EQ ID expr)
|
655
|
+
| atom
|
656
|
+
;
|
657
|
+
|
658
|
+
atom
|
659
|
+
: ID
|
660
|
+
| INT
|
661
|
+
;
|
662
|
+
END
|
663
|
+
|
664
|
+
compile_options :trace => true
|
665
|
+
|
666
|
+
example "processing AST output from a parser with a tree parser" do
|
667
|
+
input_source = <<-END.fixed_indent(0)
|
668
|
+
char c;
|
669
|
+
int x;
|
670
|
+
|
671
|
+
void bar(int x);
|
672
|
+
|
673
|
+
int foo(int y, char d) {
|
674
|
+
int i;
|
675
|
+
for (i=0; i<3; i=i+1) {
|
676
|
+
x=3;
|
677
|
+
y=5;
|
678
|
+
}
|
679
|
+
}
|
680
|
+
END
|
681
|
+
|
682
|
+
lexer = GenericLanguage::Lexer.new( input_source )
|
683
|
+
parser = GenericLanguage::Parser.new( lexer )
|
684
|
+
|
685
|
+
expected_tree = <<-END.strip!.gsub!(/\s+/, ' ')
|
686
|
+
(VAR_DEF char c)
|
687
|
+
(VAR_DEF int x)
|
688
|
+
(FUNC_DECL (FUNC_HDR void bar (ARG_DEF int x)))
|
689
|
+
(FUNC_DEF
|
690
|
+
(FUNC_HDR int foo (ARG_DEF int y) (ARG_DEF char d))
|
691
|
+
(BLOCK
|
692
|
+
(VAR_DEF int i)
|
693
|
+
(for (= i 0) (< i 3) (= i (+ i 1))
|
694
|
+
(BLOCK (= x 3) (= y 5)))))
|
695
|
+
END
|
696
|
+
|
697
|
+
result = parser.program
|
698
|
+
result.tree.inspect.should == expected_tree
|
699
|
+
|
700
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
701
|
+
nodes.token_stream = parser.input
|
702
|
+
tree_parser = GenericLanguageWalker::TreeParser.new( nodes )
|
703
|
+
|
704
|
+
tree_parser.program
|
705
|
+
tree_parser.traces.should == %w(
|
706
|
+
>program >declaration >variable >type
|
707
|
+
<type >declarator <declarator <variable
|
708
|
+
<declaration >declaration >variable >type
|
709
|
+
<type >declarator <declarator <variable
|
710
|
+
<declaration >declaration >functionHeader >type
|
711
|
+
<type >formalParameter >type <type
|
712
|
+
>declarator <declarator <formalParameter <functionHeader
|
713
|
+
<declaration >declaration >functionHeader >type
|
714
|
+
<type >formalParameter >type <type
|
715
|
+
>declarator <declarator <formalParameter >formalParameter
|
716
|
+
>type <type >declarator <declarator
|
717
|
+
<formalParameter <functionHeader >block >variable
|
718
|
+
>type <type >declarator <declarator
|
719
|
+
<variable >stat >forStat >expr
|
720
|
+
>expr >atom <atom <expr
|
721
|
+
<expr >expr >expr >atom
|
722
|
+
<atom <expr >expr >atom
|
723
|
+
<atom <expr <expr >expr
|
724
|
+
>expr >expr >atom <atom
|
725
|
+
<expr >expr >atom <atom
|
726
|
+
<expr <expr <expr >block
|
727
|
+
>stat >expr >expr >atom
|
728
|
+
<atom <expr <expr <stat
|
729
|
+
>stat >expr >expr >atom
|
730
|
+
<atom <expr <expr <stat
|
731
|
+
<block <forStat <stat <block
|
732
|
+
<declaration <program
|
733
|
+
)
|
734
|
+
end
|
735
|
+
|
736
|
+
example 'tree parser rule label property references' do
|
737
|
+
input = "char c;\n"
|
738
|
+
lexer = GenericLanguage::Lexer.new( "char c;\n" )
|
739
|
+
parser = GenericLanguage::Parser.new( lexer )
|
740
|
+
|
741
|
+
result = parser.variable
|
742
|
+
nodes = ANTLR3::AST::CommonTreeNodeStream.new( result.tree )
|
743
|
+
nodes.token_stream = parser.input
|
744
|
+
|
745
|
+
tree_parser = GenericLanguageWalker::TreeParser.new( nodes )
|
746
|
+
tree_parser.variable.should == 'c'
|
747
|
+
end
|
748
|
+
|
749
|
+
end
|
750
|
+
|