1 /*
2  * [The "BSD license"]
3  *  Copyright (c) 2010 Terence Parr
4  *  All rights reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions
8  *  are met:
9  *  1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in the
13  *      documentation and/or other materials provided with the distribution.
14  *  3. The name of the author may not be used to endorse or promote products
15  *      derived from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 package org.antlr.test;
29 
30 import org.junit.Test;
31 
32 public class TestTreeParsing extends BaseTest {
testFlatList()33 	@Test public void testFlatList() throws Exception {
34 		String grammar =
35 			"grammar T;\n" +
36 			"options {output=AST;}\n" +
37 			"a : ID INT;\n" +
38 			"ID : 'a'..'z'+ ;\n" +
39 			"INT : '0'..'9'+;\n" +
40 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
41 
42 		String treeGrammar =
43 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
44 			"a : ID INT\n" +
45 			"    {System.out.println($ID+\", \"+$INT);}\n" +
46 			"  ;\n";
47 
48 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
49 				    treeGrammar, "TP", "TLexer", "a", "a", "abc 34");
50 		assertEquals("abc, 34\n", found);
51 	}
52 
testSimpleTree()53 	@Test public void testSimpleTree() throws Exception {
54 		String grammar =
55 			"grammar T;\n" +
56 			"options {output=AST;}\n" +
57 			"a : ID INT -> ^(ID INT);\n" +
58 			"ID : 'a'..'z'+ ;\n" +
59 			"INT : '0'..'9'+;\n" +
60 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
61 
62 		String treeGrammar =
63 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
64 			"a : ^(ID INT)\n" +
65 			"    {System.out.println($ID+\", \"+$INT);}\n" +
66 			"  ;\n";
67 
68 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
69 				    treeGrammar, "TP", "TLexer", "a", "a", "abc 34");
70 		assertEquals("abc, 34\n", found);
71 	}
72 
testFlatVsTreeDecision()73 	@Test public void testFlatVsTreeDecision() throws Exception {
74 		String grammar =
75 			"grammar T;\n" +
76 			"options {output=AST;}\n" +
77 			"a : b c ;\n" +
78 			"b : ID INT -> ^(ID INT);\n" +
79 			"c : ID INT;\n" +
80 			"ID : 'a'..'z'+ ;\n" +
81 			"INT : '0'..'9'+;\n" +
82 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
83 
84 		String treeGrammar =
85 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
86 			"a : b b ;\n" +
87 			"b : ID INT    {System.out.print($ID+\" \"+$INT);}\n" +
88 			"  | ^(ID INT) {System.out.print(\"^(\"+$ID+\" \"+$INT+')');}\n" +
89 			"  ;\n";
90 
91 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
92 				    treeGrammar, "TP", "TLexer", "a", "a", "a 1 b 2");
93 		assertEquals("^(a 1)b 2\n", found);
94 	}
95 
testFlatVsTreeDecision2()96 	@Test public void testFlatVsTreeDecision2() throws Exception {
97 		String grammar =
98 			"grammar T;\n" +
99 			"options {output=AST;}\n" +
100 			"a : b c ;\n" +
101 			"b : ID INT+ -> ^(ID INT+);\n" +
102 			"c : ID INT+;\n" +
103 			"ID : 'a'..'z'+ ;\n" +
104 			"INT : '0'..'9'+;\n" +
105 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
106 
107 		String treeGrammar =
108 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
109 			"a : b b ;\n" +
110 			"b : ID INT+    {System.out.print($ID+\" \"+$INT);}\n" +
111 			"  | ^(x=ID (y=INT)+) {System.out.print(\"^(\"+$x+' '+$y+')');}\n" +
112 			"  ;\n";
113 
114 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
115 				    treeGrammar, "TP", "TLexer", "a", "a",
116 				    "a 1 2 3 b 4 5");
117 		assertEquals("^(a 3)b 5\n", found);
118 	}
119 
testCyclicDFALookahead()120 	@Test public void testCyclicDFALookahead() throws Exception {
121 		String grammar =
122 			"grammar T;\n" +
123 			"options {output=AST;}\n" +
124 			"a : ID INT+ PERIOD;\n" +
125 			"ID : 'a'..'z'+ ;\n" +
126 			"INT : '0'..'9'+;\n" +
127 			"SEMI : ';' ;\n"+
128 			"PERIOD : '.' ;\n"+
129 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
130 
131 		String treeGrammar =
132 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
133 			"a : ID INT+ PERIOD {System.out.print(\"alt 1\");}"+
134 			"  | ID INT+ SEMI   {System.out.print(\"alt 2\");}\n" +
135 			"  ;\n";
136 
137 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
138 				    treeGrammar, "TP", "TLexer", "a", "a", "a 1 2 3.");
139 		assertEquals("alt 1\n", found);
140 	}
141 
testTemplateOutput()142 	@Test public void testTemplateOutput() throws Exception {
143 		String grammar =
144 			"grammar T;\n" +
145 			"options {output=AST;}\n" +
146 			"a : ID INT;\n" +
147 			"ID : 'a'..'z'+ ;\n" +
148 			"INT : '0'..'9'+;\n" +
149 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
150 
151 		String treeGrammar =
152 			"tree grammar TP;\n" +
153 			"options {output=template; ASTLabelType=CommonTree;}\n" +
154 			"s : a {System.out.println($a.st);};\n" +
155 			"a : ID INT -> {new StringTemplate($INT.text)}\n" +
156 			"  ;\n";
157 
158 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
159 				    treeGrammar, "TP", "TLexer", "a", "s", "abc 34");
160 		assertEquals("34\n", found);
161 	}
162 
testNullableChildList()163 	@Test public void testNullableChildList() throws Exception {
164 		String grammar =
165 			"grammar T;\n" +
166 			"options {output=AST;}\n" +
167 			"a : ID INT? -> ^(ID INT?);\n" +
168 			"ID : 'a'..'z'+ ;\n" +
169 			"INT : '0'..'9'+;\n" +
170 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
171 
172 		String treeGrammar =
173 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
174 			"a : ^(ID INT?)\n" +
175 			"    {System.out.println($ID);}\n" +
176 			"  ;\n";
177 
178 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
179 				    treeGrammar, "TP", "TLexer", "a", "a", "abc");
180 		assertEquals("abc\n", found);
181 	}
182 
testNullableChildList2()183 	@Test public void testNullableChildList2() throws Exception {
184 		String grammar =
185 			"grammar T;\n" +
186 			"options {output=AST;}\n" +
187 			"a : ID INT? SEMI -> ^(ID INT?) SEMI ;\n" +
188 			"ID : 'a'..'z'+ ;\n" +
189 			"INT : '0'..'9'+;\n" +
190 			"SEMI : ';' ;\n"+
191 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
192 
193 		String treeGrammar =
194 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
195 			"a : ^(ID INT?) SEMI\n" +
196 			"    {System.out.println($ID);}\n" +
197 			"  ;\n";
198 
199 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
200 				    treeGrammar, "TP", "TLexer", "a", "a", "abc;");
201 		assertEquals("abc\n", found);
202 	}
203 
testNullableChildList3()204 	@Test public void testNullableChildList3() throws Exception {
205 		String grammar =
206 			"grammar T;\n" +
207 			"options {output=AST;}\n" +
208 			"a : x=ID INT? (y=ID)? SEMI -> ^($x INT? $y?) SEMI ;\n" +
209 			"ID : 'a'..'z'+ ;\n" +
210 			"INT : '0'..'9'+;\n" +
211 			"SEMI : ';' ;\n"+
212 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
213 
214 		String treeGrammar =
215 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
216 			"a : ^(ID INT? b) SEMI\n" +
217 			"    {System.out.println($ID+\", \"+$b.text);}\n" +
218 			"  ;\n"+
219 			"b : ID? ;\n";
220 
221 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
222 				    treeGrammar, "TP", "TLexer", "a", "a", "abc def;");
223 		assertEquals("abc, def\n", found);
224 	}
225 
testActionsAfterRoot()226 	@Test public void testActionsAfterRoot() throws Exception {
227 		String grammar =
228 			"grammar T;\n" +
229 			"options {output=AST;}\n" +
230 			"a : x=ID INT? SEMI -> ^($x INT?) ;\n" +
231 			"ID : 'a'..'z'+ ;\n" +
232 			"INT : '0'..'9'+;\n" +
233 			"SEMI : ';' ;\n"+
234 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
235 
236 		String treeGrammar =
237 			"tree grammar TP; options {ASTLabelType=CommonTree;}\n" +
238 			"a @init {int x=0;} : ^(ID {x=1;} {x=2;} INT?)\n" +
239 			"    {System.out.println($ID+\", \"+x);}\n" +
240 			"  ;\n";
241 
242 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
243 				    treeGrammar, "TP", "TLexer", "a", "a", "abc;");
244 		assertEquals("abc, 2\n", found);
245 	}
246 
testWildcardLookahead()247     @Test public void testWildcardLookahead() throws Exception {
248         String grammar =
249             "grammar T;\n" +
250             "options {output=AST;}\n" +
251             "a : ID '+'^ INT;\n" +
252             "ID : 'a'..'z'+ ;\n" +
253             "INT : '0'..'9'+;\n" +
254             "SEMI : ';' ;\n"+
255             "PERIOD : '.' ;\n"+
256             "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
257 
258         String treeGrammar =
259             "tree grammar TP; options {tokenVocab=T; ASTLabelType=CommonTree;}\n" +
260             "a : ^('+' . INT) {System.out.print(\"alt 1\");}"+
261             "  ;\n";
262 
263         String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
264                     treeGrammar, "TP", "TLexer", "a", "a", "a + 2");
265         assertEquals("alt 1\n", found);
266     }
267 
testWildcardLookahead2()268     @Test public void testWildcardLookahead2() throws Exception {
269         String grammar =
270             "grammar T;\n" +
271             "options {output=AST;}\n" +
272             "a : ID '+'^ INT;\n" +
273             "ID : 'a'..'z'+ ;\n" +
274             "INT : '0'..'9'+;\n" +
275             "SEMI : ';' ;\n"+
276             "PERIOD : '.' ;\n"+
277             "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
278 
279         String treeGrammar =
280             "tree grammar TP; options {tokenVocab=T; ASTLabelType=CommonTree;}\n" +
281             "a : ^('+' . INT) {System.out.print(\"alt 1\");}"+
282             "  | ^('+' . .)   {System.out.print(\"alt 2\");}\n" +
283             "  ;\n";
284 
285         // AMBIG upon '+' DOWN INT UP etc.. but so what.
286 
287         String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
288                     treeGrammar, "TP", "TLexer", "a", "a", "a + 2");
289         assertEquals("alt 1\n", found);
290     }
291 
testWildcardLookahead3()292     @Test public void testWildcardLookahead3() throws Exception {
293         String grammar =
294             "grammar T;\n" +
295             "options {output=AST;}\n" +
296             "a : ID '+'^ INT;\n" +
297             "ID : 'a'..'z'+ ;\n" +
298             "INT : '0'..'9'+;\n" +
299             "SEMI : ';' ;\n"+
300             "PERIOD : '.' ;\n"+
301             "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
302 
303         String treeGrammar =
304             "tree grammar TP; options {tokenVocab=T; ASTLabelType=CommonTree;}\n" +
305             "a : ^('+' ID INT) {System.out.print(\"alt 1\");}"+
306             "  | ^('+' . .)   {System.out.print(\"alt 2\");}\n" +
307             "  ;\n";
308 
309         // AMBIG upon '+' DOWN INT UP etc.. but so what.
310 
311         String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
312                     treeGrammar, "TP", "TLexer", "a", "a", "a + 2");
313         assertEquals("alt 1\n", found);
314     }
315 
testWildcardPlusLookahead()316     @Test public void testWildcardPlusLookahead() throws Exception {
317         String grammar =
318             "grammar T;\n" +
319             "options {output=AST;}\n" +
320             "a : ID '+'^ INT;\n" +
321             "ID : 'a'..'z'+ ;\n" +
322             "INT : '0'..'9'+;\n" +
323             "SEMI : ';' ;\n"+
324             "PERIOD : '.' ;\n"+
325             "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
326 
327         String treeGrammar =
328             "tree grammar TP; options {tokenVocab=T; ASTLabelType=CommonTree;}\n" +
329             "a : ^('+' INT INT ) {System.out.print(\"alt 1\");}"+
330             "  | ^('+' .+)   {System.out.print(\"alt 2\");}\n" +
331             "  ;\n";
332 
333         // AMBIG upon '+' DOWN INT UP etc.. but so what.
334 
335         String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
336                     treeGrammar, "TP", "TLexer", "a", "a", "a + 2");
337         assertEquals("alt 2\n", found);
338     }
339 
340 }
341