Home | History | Annotate | Download | only in test
      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.antlr.Tool;
     31 import org.antlr.codegen.CodeGenerator;
     32 import org.antlr.tool.*;
     33 import org.junit.Test;
     34 
     35 public class TestRewriteTemplates extends BaseTest {
     36 	protected boolean debug = false;
     37 
     38 	@Test public void testDelete() throws Exception {
     39 		String grammar =
     40 			"grammar T;\n" +
     41 			"options {output=template;}\n" +
     42 			"a : ID INT -> ;\n" +
     43 			"ID : 'a'..'z'+ ;\n" +
     44 			"INT : '0'..'9'+;\n" +
     45 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     46 		String found = execParser("T.g", grammar, "TParser", "TLexer",
     47 								  "a", "abc 34", debug);
     48 		assertEquals("", found);
     49 	}
     50 
     51 	@Test public void testAction() throws Exception {
     52 		String grammar =
     53 			"grammar T;\n" +
     54 			"options {output=template;}\n" +
     55 			"a : ID INT -> {new StringTemplate($ID.text)} ;\n" +
     56 			"ID : 'a'..'z'+ ;\n" +
     57 			"INT : '0'..'9'+;\n" +
     58 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     59 		String found = execParser("T.g", grammar, "TParser", "TLexer",
     60 								  "a", "abc 34", debug);
     61 		assertEquals("abc\n", found);
     62 	}
     63 
     64 	@Test public void testEmbeddedLiteralConstructor() throws Exception {
     65 		String grammar =
     66 			"grammar T;\n" +
     67 			"options {output=template;}\n" +
     68 			"a : ID INT -> {%{$ID.text}} ;\n" +
     69 			"ID : 'a'..'z'+ ;\n" +
     70 			"INT : '0'..'9'+;\n" +
     71 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     72 		String found = execParser("T.g", grammar, "TParser", "TLexer",
     73 								  "a", "abc 34", debug);
     74 		assertEquals("abc\n", found);
     75 	}
     76 
     77 	@Test public void testInlineTemplate() throws Exception {
     78 		String grammar =
     79 			"grammar T;\n" +
     80 			"options {output=template;}\n" +
     81 			"a : ID INT -> template(x={$ID},y={$INT}) <<x:<x.text>, y:<y.text>;>> ;\n" +
     82 			"ID : 'a'..'z'+ ;\n" +
     83 			"INT : '0'..'9'+;\n" +
     84 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
     85 		String found = execParser("T.g", grammar, "TParser", "TLexer",
     86 								  "a", "abc 34", debug);
     87 		assertEquals("x:abc, y:34;\n", found);
     88 	}
     89 
     90 	@Test public void testNamedTemplate() throws Exception {
     91 		// the support code adds template group in it's output Test.java
     92 		// that defines template foo.
     93 		String grammar =
     94 			"grammar T;\n" +
     95 			"options {output=template;}\n" +
     96 			"a : ID INT -> foo(x={$ID.text},y={$INT.text}) ;\n" +
     97 			"ID : 'a'..'z'+ ;\n" +
     98 			"INT : '0'..'9'+;\n" +
     99 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    100 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    101 								  "a", "abc 34", debug);
    102 		assertEquals("abc 34\n", found);
    103 	}
    104 
    105 	@Test public void testIndirectTemplate() throws Exception {
    106 		// the support code adds template group in it's output Test.java
    107 		// that defines template foo.
    108 		String grammar =
    109 			"grammar T;\n" +
    110 			"options {output=template;}\n" +
    111 			"a : ID INT -> ({\"foo\"})(x={$ID.text},y={$INT.text}) ;\n" +
    112 			"ID : 'a'..'z'+ ;\n" +
    113 			"INT : '0'..'9'+;\n" +
    114 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    115 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    116 								  "a", "abc 34", debug);
    117 		assertEquals("abc 34\n", found);
    118 	}
    119 
    120 	@Test public void testInlineTemplateInvokingLib() throws Exception {
    121 		String grammar =
    122 			"grammar T;\n" +
    123 			"options {output=template;}\n" +
    124 			"a : ID INT -> template(x={$ID.text},y={$INT.text}) \"<foo(...)>\" ;\n" +
    125 			"ID : 'a'..'z'+ ;\n" +
    126 			"INT : '0'..'9'+;\n" +
    127 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    128 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    129 								  "a", "abc 34", debug);
    130 		assertEquals("abc 34\n", found);
    131 	}
    132 
    133 	@Test public void testPredicatedAlts() throws Exception {
    134 		// the support code adds template group in it's output Test.java
    135 		// that defines template foo.
    136 		String grammar =
    137 			"grammar T;\n" +
    138 			"options {output=template;}\n" +
    139 			"a : ID INT -> {false}? foo(x={$ID.text},y={$INT.text})\n" +
    140 			"           -> foo(x={\"hi\"}, y={$ID.text})\n" +
    141 			"  ;\n" +
    142 			"ID : 'a'..'z'+ ;\n" +
    143 			"INT : '0'..'9'+;\n" +
    144 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    145 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    146 								  "a", "abc 34", debug);
    147 		assertEquals("hi abc\n", found);
    148 	}
    149 
    150 	@Test public void testTemplateReturn() throws Exception {
    151 		String grammar =
    152 			"grammar T;\n" +
    153 			"options {output=template;}\n" +
    154 			"a : b {System.out.println($b.st);} ;\n" +
    155 			"b : ID INT -> foo(x={$ID.text},y={$INT.text}) ;\n" +
    156 			"ID : 'a'..'z'+ ;\n" +
    157 			"INT : '0'..'9'+;\n" +
    158 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    159 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    160 								  "a", "abc 34", debug);
    161 		assertEquals("abc 34\n", found);
    162 	}
    163 
    164 	@Test public void testReturnValueWithTemplate() throws Exception {
    165 		String grammar =
    166 			"grammar T;\n" +
    167 			"options {output=template;}\n" +
    168 			"a : b {System.out.println($b.i);} ;\n" +
    169 			"b returns [int i] : ID INT {$i=8;} ;\n" +
    170 			"ID : 'a'..'z'+ ;\n" +
    171 			"INT : '0'..'9'+;\n" +
    172 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    173 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    174 								  "a", "abc 34", debug);
    175 		assertEquals("8\n", found);
    176 	}
    177 
    178 	@Test public void testTemplateRefToDynamicAttributes() throws Exception {
    179 		String grammar =
    180 			"grammar T;\n" +
    181 			"options {output=template;}\n" +
    182 			"a scope {String id;} : ID {$a::id=$ID.text;} b\n" +
    183 			"	{System.out.println($b.st.toString());}\n" +
    184 			"   ;\n" +
    185 			"b : INT -> foo(x={$a::id}) ;\n" +
    186 			"ID : 'a'..'z'+ ;\n" +
    187 			"INT : '0'..'9'+;\n" +
    188 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    189 		String found = execParser("T.g", grammar, "TParser", "TLexer",
    190 								  "a", "abc 34", debug);
    191 		assertEquals("abc \n", found);
    192 	}
    193 
    194 	// tests for rewriting templates in tree parsers
    195 
    196 	@Test public void testSingleNode() throws Exception {
    197 		String grammar =
    198 			"grammar T;\n" +
    199 			"options {output=AST;}\n" +
    200 			"a : ID ;\n" +
    201 			"ID : 'a'..'z'+ ;\n" +
    202 			"INT : '0'..'9'+;\n" +
    203 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    204 
    205 		String treeGrammar =
    206 			"tree grammar TP;\n"+
    207 			"options {ASTLabelType=CommonTree; output=template;}\n" +
    208 			"s : a {System.out.println($a.st);} ;\n" +
    209 			"a : ID -> template(x={$ID.text}) <<|<x>|>> ;\n";
    210 
    211 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
    212 									  treeGrammar, "TP", "TLexer", "a", "s", "abc");
    213 		assertEquals("|abc|\n", found);
    214 	}
    215 
    216 	@Test public void testSingleNodeRewriteMode() throws Exception {
    217 		String grammar =
    218 			"grammar T;\n" +
    219 			"options {output=AST;}\n" +
    220 			"a : ID ;\n" +
    221 			"ID : 'a'..'z'+ ;\n" +
    222 			"INT : '0'..'9'+;\n" +
    223 			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
    224 
    225 		String treeGrammar =
    226 			"tree grammar TP;\n"+
    227 			"options {ASTLabelType=CommonTree; output=template; rewrite=true;}\n" +
    228 			"s : a {System.out.println(input.getTokenStream().toString(0,0));} ;\n" +
    229 			"a : ID -> template(x={$ID.text}) <<|<x>|>> ;\n";
    230 
    231 		String found = execTreeParser("T.g", grammar, "TParser", "TP.g",
    232 									  treeGrammar, "TP", "TLexer", "a", "s", "abc");
    233 		assertEquals("|abc|\n", found);
    234 	}
    235 
    236 	@Test public void testRewriteRuleAndRewriteModeOnSimpleElements() throws Exception {
    237 		ErrorQueue equeue = new ErrorQueue();
    238 		ErrorManager.setErrorListener(equeue);
    239 		Grammar g = new Grammar(
    240 			"tree grammar TP;\n"+
    241 			"options {ASTLabelType=CommonTree; output=template; rewrite=true;}\n" +
    242 			"a: ^(A B) -> {ick}\n" +
    243 			" | y+=INT -> {ick}\n" +
    244 			" | x=ID -> {ick}\n" +
    245 			" | BLORT -> {ick}\n" +
    246 			" ;\n"
    247 		);
    248 		Tool antlr = newTool();
    249 		antlr.setOutputDirectory(null); // write to /dev/null
    250 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    251 		g.setCodeGenerator(generator);
    252 		generator.genRecognizer();
    253 
    254 		assertEquals("unexpected errors: "+equeue, 0, equeue.warnings.size());
    255 	}
    256 
    257 	@Test public void testRewriteRuleAndRewriteModeIgnoreActionsPredicates() throws Exception {
    258 		ErrorQueue equeue = new ErrorQueue();
    259 		ErrorManager.setErrorListener(equeue);
    260 		Grammar g = new Grammar(
    261 			"tree grammar TP;\n"+
    262 			"options {ASTLabelType=CommonTree; output=template; rewrite=true;}\n" +
    263 			"a: {action} {action2} x=A -> {ick}\n" +
    264 			" | {pred1}? y+=B -> {ick}\n" +
    265 			" | C {action} -> {ick}\n" +
    266 			" | {pred2}?=> z+=D -> {ick}\n" +
    267 			" | (E)=> ^(F G) -> {ick}\n" +
    268 			" ;\n"
    269 		);
    270 		Tool antlr = newTool();
    271 		antlr.setOutputDirectory(null); // write to /dev/null
    272 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    273 		g.setCodeGenerator(generator);
    274 		generator.genRecognizer();
    275 
    276 		assertEquals("unexpected errors: "+equeue, 0, equeue.warnings.size());
    277 	}
    278 
    279 	@Test public void testRewriteRuleAndRewriteModeNotSimple() throws Exception {
    280 		ErrorQueue equeue = new ErrorQueue();
    281 		ErrorManager.setErrorListener(equeue);
    282 		Grammar g = new Grammar(
    283 			"tree grammar TP;\n"+
    284 			"options {ASTLabelType=CommonTree; output=template; rewrite=true;}\n" +
    285 			"a  : ID+ -> {ick}\n" +
    286 			"   | INT INT -> {ick}\n" +
    287 			"   ;\n"
    288 		);
    289 		Tool antlr = newTool();
    290 		antlr.setOutputDirectory(null); // write to /dev/null
    291 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    292 		g.setCodeGenerator(generator);
    293 		generator.genRecognizer();
    294 
    295 		assertEquals("unexpected errors: "+equeue, 0, equeue.warnings.size());
    296 	}
    297 
    298 	@Test public void testRewriteRuleAndRewriteModeRefRule() throws Exception {
    299 		ErrorQueue equeue = new ErrorQueue();
    300 		ErrorManager.setErrorListener(equeue);
    301 		Grammar g = new Grammar(
    302 			"tree grammar TP;\n"+
    303 			"options {ASTLabelType=CommonTree; output=template; rewrite=true;}\n" +
    304 			"a  : b+ -> {ick}\n" +
    305 			"   | b b A -> {ick}\n" +
    306 			"   ;\n" +
    307 			"b  : B ;\n"
    308 		);
    309 		Tool antlr = newTool();
    310 		antlr.setOutputDirectory(null); // write to /dev/null
    311 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    312 		g.setCodeGenerator(generator);
    313 		generator.genRecognizer();
    314 
    315 		assertEquals("unexpected errors: "+equeue, 0, equeue.warnings.size());
    316 	}
    317 
    318 }
    319