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 import static org.junit.Assert.*; 33 34 public class TestTreeParsing extends BaseTest { testFlatList()35 @Test public void testFlatList() throws Exception { 36 String grammar = 37 "grammar T;\n" + 38 "options {output=AST;}\n" + 39 "a : ID INT;\n" + 40 "ID : 'a'..'z'+ ;\n" + 41 "INT : '0'..'9'+;\n" + 42 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 43 44 String treeGrammar = 45 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 46 "a : ID INT\n" + 47 " {System.out.println($ID+\", \"+$INT);}\n" + 48 " ;\n"; 49 50 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 51 treeGrammar, "TP", "TLexer", "a", "a", "abc 34"); 52 assertEquals("abc, 34\n", found); 53 } 54 testSimpleTree()55 @Test public void testSimpleTree() throws Exception { 56 String grammar = 57 "grammar T;\n" + 58 "options {output=AST;}\n" + 59 "a : ID INT -> ^(ID INT);\n" + 60 "ID : 'a'..'z'+ ;\n" + 61 "INT : '0'..'9'+;\n" + 62 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 63 64 String treeGrammar = 65 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 66 "a : ^(ID INT)\n" + 67 " {System.out.println($ID+\", \"+$INT);}\n" + 68 " ;\n"; 69 70 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 71 treeGrammar, "TP", "TLexer", "a", "a", "abc 34"); 72 assertEquals("abc, 34\n", found); 73 } 74 testFlatVsTreeDecision()75 @Test public void testFlatVsTreeDecision() throws Exception { 76 String grammar = 77 "grammar T;\n" + 78 "options {output=AST;}\n" + 79 "a : b c ;\n" + 80 "b : ID INT -> ^(ID INT);\n" + 81 "c : ID INT;\n" + 82 "ID : 'a'..'z'+ ;\n" + 83 "INT : '0'..'9'+;\n" + 84 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 85 86 String treeGrammar = 87 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 88 "a : b b ;\n" + 89 "b : ID INT {System.out.print($ID+\" \"+$INT);}\n" + 90 " | ^(ID INT) {System.out.print(\"^(\"+$ID+\" \"+$INT+')');}\n" + 91 " ;\n"; 92 93 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 94 treeGrammar, "TP", "TLexer", "a", "a", "a 1 b 2"); 95 assertEquals("^(a 1)b 2\n", found); 96 } 97 testFlatVsTreeDecision2()98 @Test public void testFlatVsTreeDecision2() throws Exception { 99 String grammar = 100 "grammar T;\n" + 101 "options {output=AST;}\n" + 102 "a : b c ;\n" + 103 "b : ID INT+ -> ^(ID INT+);\n" + 104 "c : ID INT+;\n" + 105 "ID : 'a'..'z'+ ;\n" + 106 "INT : '0'..'9'+;\n" + 107 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 108 109 String treeGrammar = 110 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 111 "a : b b ;\n" + 112 "b : ID INT+ {System.out.print($ID+\" \"+$INT);}\n" + 113 " | ^(x=ID (y=INT)+) {System.out.print(\"^(\"+$x+' '+$y+')');}\n" + 114 " ;\n"; 115 116 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 117 treeGrammar, "TP", "TLexer", "a", "a", 118 "a 1 2 3 b 4 5"); 119 assertEquals("^(a 3)b 5\n", found); 120 } 121 testCyclicDFALookahead()122 @Test public void testCyclicDFALookahead() throws Exception { 123 String grammar = 124 "grammar T;\n" + 125 "options {output=AST;}\n" + 126 "a : ID INT+ PERIOD;\n" + 127 "ID : 'a'..'z'+ ;\n" + 128 "INT : '0'..'9'+;\n" + 129 "SEMI : ';' ;\n"+ 130 "PERIOD : '.' ;\n"+ 131 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 132 133 String treeGrammar = 134 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 135 "a : ID INT+ PERIOD {System.out.print(\"alt 1\");}"+ 136 " | ID INT+ SEMI {System.out.print(\"alt 2\");}\n" + 137 " ;\n"; 138 139 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 140 treeGrammar, "TP", "TLexer", "a", "a", "a 1 2 3."); 141 assertEquals("alt 1\n", found); 142 } 143 testTemplateOutput()144 @Test public void testTemplateOutput() throws Exception { 145 String grammar = 146 "grammar T;\n" + 147 "options {output=AST;}\n" + 148 "a : ID INT;\n" + 149 "ID : 'a'..'z'+ ;\n" + 150 "INT : '0'..'9'+;\n" + 151 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 152 153 String treeGrammar = 154 "tree grammar TP;\n" + 155 "options {output=template; ASTLabelType=CommonTree;}\n" + 156 "s : a {System.out.println($a.st);};\n" + 157 "a : ID INT -> {new StringTemplate($INT.text)}\n" + 158 " ;\n"; 159 160 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 161 treeGrammar, "TP", "TLexer", "a", "s", "abc 34"); 162 assertEquals("34\n", found); 163 } 164 testNullableChildList()165 @Test public void testNullableChildList() throws Exception { 166 String grammar = 167 "grammar T;\n" + 168 "options {output=AST;}\n" + 169 "a : ID INT? -> ^(ID INT?);\n" + 170 "ID : 'a'..'z'+ ;\n" + 171 "INT : '0'..'9'+;\n" + 172 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 173 174 String treeGrammar = 175 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 176 "a : ^(ID INT?)\n" + 177 " {System.out.println($ID);}\n" + 178 " ;\n"; 179 180 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 181 treeGrammar, "TP", "TLexer", "a", "a", "abc"); 182 assertEquals("abc\n", found); 183 } 184 testNullableChildList2()185 @Test public void testNullableChildList2() throws Exception { 186 String grammar = 187 "grammar T;\n" + 188 "options {output=AST;}\n" + 189 "a : ID INT? SEMI -> ^(ID INT?) SEMI ;\n" + 190 "ID : 'a'..'z'+ ;\n" + 191 "INT : '0'..'9'+;\n" + 192 "SEMI : ';' ;\n"+ 193 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 194 195 String treeGrammar = 196 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 197 "a : ^(ID INT?) SEMI\n" + 198 " {System.out.println($ID);}\n" + 199 " ;\n"; 200 201 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 202 treeGrammar, "TP", "TLexer", "a", "a", "abc;"); 203 assertEquals("abc\n", found); 204 } 205 testNullableChildList3()206 @Test public void testNullableChildList3() throws Exception { 207 String grammar = 208 "grammar T;\n" + 209 "options {output=AST;}\n" + 210 "a : x=ID INT? (y=ID)? SEMI -> ^($x INT? $y?) SEMI ;\n" + 211 "ID : 'a'..'z'+ ;\n" + 212 "INT : '0'..'9'+;\n" + 213 "SEMI : ';' ;\n"+ 214 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 215 216 String treeGrammar = 217 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 218 "a : ^(ID INT? b) SEMI\n" + 219 " {System.out.println($ID+\", \"+$b.text);}\n" + 220 " ;\n"+ 221 "b : ID? ;\n"; 222 223 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 224 treeGrammar, "TP", "TLexer", "a", "a", "abc def;"); 225 assertEquals("abc, def\n", found); 226 } 227 testActionsAfterRoot()228 @Test public void testActionsAfterRoot() throws Exception { 229 String grammar = 230 "grammar T;\n" + 231 "options {output=AST;}\n" + 232 "a : x=ID INT? SEMI -> ^($x INT?) ;\n" + 233 "ID : 'a'..'z'+ ;\n" + 234 "INT : '0'..'9'+;\n" + 235 "SEMI : ';' ;\n"+ 236 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 237 238 String treeGrammar = 239 "tree grammar TP; options {ASTLabelType=CommonTree;}\n" + 240 "a @init {int x=0;} : ^(ID {x=1;} {x=2;} INT?)\n" + 241 " {System.out.println($ID+\", \"+x);}\n" + 242 " ;\n"; 243 244 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 245 treeGrammar, "TP", "TLexer", "a", "a", "abc;"); 246 assertEquals("abc, 2\n", found); 247 } 248 testWildcardLookahead()249 @Test public void testWildcardLookahead() throws Exception { 250 String grammar = 251 "grammar T;\n" + 252 "options {output=AST;}\n" + 253 "a : ID '+'^ INT;\n" + 254 "ID : 'a'..'z'+ ;\n" + 255 "INT : '0'..'9'+;\n" + 256 "SEMI : ';' ;\n"+ 257 "PERIOD : '.' ;\n"+ 258 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 259 260 String treeGrammar = 261 "tree grammar TP; options {tokenVocab=T; ASTLabelType=CommonTree;}\n" + 262 "a : ^('+' . INT) {System.out.print(\"alt 1\");}"+ 263 " ;\n"; 264 265 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 266 treeGrammar, "TP", "TLexer", "a", "a", "a + 2"); 267 assertEquals("alt 1\n", found); 268 } 269 testWildcardLookahead2()270 @Test public void testWildcardLookahead2() throws Exception { 271 String grammar = 272 "grammar T;\n" + 273 "options {output=AST;}\n" + 274 "a : ID '+'^ INT;\n" + 275 "ID : 'a'..'z'+ ;\n" + 276 "INT : '0'..'9'+;\n" + 277 "SEMI : ';' ;\n"+ 278 "PERIOD : '.' ;\n"+ 279 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 280 281 String treeGrammar = 282 "tree grammar TP; options {tokenVocab=T; ASTLabelType=CommonTree;}\n" + 283 "a : ^('+' . INT) {System.out.print(\"alt 1\");}"+ 284 " | ^('+' . .) {System.out.print(\"alt 2\");}\n" + 285 " ;\n"; 286 287 // AMBIG upon '+' DOWN INT UP etc.. but so what. 288 289 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 290 treeGrammar, "TP", "TLexer", "a", "a", "a + 2"); 291 assertEquals("alt 1\n", found); 292 } 293 testWildcardLookahead3()294 @Test public void testWildcardLookahead3() throws Exception { 295 String grammar = 296 "grammar T;\n" + 297 "options {output=AST;}\n" + 298 "a : ID '+'^ INT;\n" + 299 "ID : 'a'..'z'+ ;\n" + 300 "INT : '0'..'9'+;\n" + 301 "SEMI : ';' ;\n"+ 302 "PERIOD : '.' ;\n"+ 303 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 304 305 String treeGrammar = 306 "tree grammar TP; options {tokenVocab=T; ASTLabelType=CommonTree;}\n" + 307 "a : ^('+' ID INT) {System.out.print(\"alt 1\");}"+ 308 " | ^('+' . .) {System.out.print(\"alt 2\");}\n" + 309 " ;\n"; 310 311 // AMBIG upon '+' DOWN INT UP etc.. but so what. 312 313 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 314 treeGrammar, "TP", "TLexer", "a", "a", "a + 2"); 315 assertEquals("alt 1\n", found); 316 } 317 testWildcardPlusLookahead()318 @Test public void testWildcardPlusLookahead() throws Exception { 319 String grammar = 320 "grammar T;\n" + 321 "options {output=AST;}\n" + 322 "a : ID '+'^ INT;\n" + 323 "ID : 'a'..'z'+ ;\n" + 324 "INT : '0'..'9'+;\n" + 325 "SEMI : ';' ;\n"+ 326 "PERIOD : '.' ;\n"+ 327 "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; 328 329 String treeGrammar = 330 "tree grammar TP; options {tokenVocab=T; ASTLabelType=CommonTree;}\n" + 331 "a : ^('+' INT INT ) {System.out.print(\"alt 1\");}"+ 332 " | ^('+' .+) {System.out.print(\"alt 2\");}\n" + 333 " ;\n"; 334 335 // AMBIG upon '+' DOWN INT UP etc.. but so what. 336 337 String found = execTreeParser("T.g", grammar, "TParser", "TP.g", 338 treeGrammar, "TP", "TLexer", "a", "a", "a + 2"); 339 assertEquals("alt 2\n", found); 340 } 341 342 } 343