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.grammar.v3.ANTLRParser; 33 import org.antlr.grammar.v3.ActionTranslator; 34 import org.antlr.runtime.CommonToken; 35 import org.stringtemplate.v4.ST; 36 import org.stringtemplate.v4.STGroup; 37 import org.antlr.tool.ErrorManager; 38 import org.antlr.tool.Grammar; 39 import org.antlr.tool.GrammarSemanticsMessage; 40 import org.antlr.tool.Message; 41 import org.junit.Test; 42 43 /** Test templates in actions; %... shorthands */ 44 public class TestTemplates extends BaseTest { 45 private static final String LINE_SEP = System.getProperty("line.separator"); 46 47 @Test testTemplateConstructor()48 public void testTemplateConstructor() throws Exception { 49 String action = "x = %foo(name={$ID.text});"; 50 String expecting = "x = templateLib.getInstanceOf(\"foo\"," + 51 "new STAttrMap().put(\"name\", (ID1!=null?ID1.getText():null)));"; 52 53 ErrorQueue equeue = new ErrorQueue(); 54 ErrorManager.setErrorListener(equeue); 55 Grammar g = new Grammar( 56 "grammar t;\n" + 57 "options {\n" + 58 " output=template;\n" + 59 "}\n" + 60 "\n" + 61 "a : ID {"+action+"}\n" + 62 " ;\n" + 63 "\n" + 64 "ID : 'a';\n"); 65 Tool antlr = newTool(); 66 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 67 g.setCodeGenerator(generator); 68 generator.genRecognizer(); // forces load of templates 69 ActionTranslator translator = 70 new ActionTranslator(generator, 71 "a", 72 new CommonToken(ANTLRParser.ACTION,action),1); 73 String rawTranslation = 74 translator.translate(); 75 STGroup templates = 76 new STGroup(); 77 ST actionST = new ST(templates, rawTranslation); 78 String found = actionST.render(); 79 80 assertNoErrors(equeue); 81 82 assertEquals(expecting, found); 83 } 84 85 @Test testTemplateConstructorNoArgs()86 public void testTemplateConstructorNoArgs() throws Exception { 87 String action = "x = %foo();"; 88 String expecting = "x = templateLib.getInstanceOf(\"foo\");"; 89 90 ErrorQueue equeue = new ErrorQueue(); 91 ErrorManager.setErrorListener(equeue); 92 Grammar g = new Grammar( 93 "grammar t;\n" + 94 "options {\n" + 95 " output=template;\n" + 96 "}\n" + 97 "\n" + 98 "a : ID {"+action+"}\n" + 99 " ;\n" + 100 "\n" + 101 "ID : 'a';\n"); 102 Tool antlr = newTool(); 103 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 104 g.setCodeGenerator(generator); 105 generator.genRecognizer(); // forces load of templates 106 ActionTranslator translator = 107 new ActionTranslator(generator, 108 "a", 109 new CommonToken(ANTLRParser.ACTION,action),1); 110 String rawTranslation = 111 translator.translate(); 112 STGroup templates = 113 new STGroup(); 114 ST actionST = new ST(templates, rawTranslation); 115 String found = actionST.render(); 116 117 assertNoErrors(equeue); 118 119 assertEquals(expecting, found); 120 } 121 122 @Test testIndirectTemplateConstructor()123 public void testIndirectTemplateConstructor() throws Exception { 124 String action = "x = %({\"foo\"})(name={$ID.text});"; 125 String expecting = "x = templateLib.getInstanceOf(\"foo\"," + 126 "new STAttrMap().put(\"name\", (ID1!=null?ID1.getText():null)));"; 127 128 ErrorQueue equeue = new ErrorQueue(); 129 ErrorManager.setErrorListener(equeue); 130 Grammar g = new Grammar( 131 "grammar t;\n" + 132 "options {\n" + 133 " output=template;\n" + 134 "}\n" + 135 "\n" + 136 "a : ID {"+action+"}\n" + 137 " ;\n" + 138 "\n" + 139 "ID : 'a';\n"); 140 Tool antlr = newTool(); 141 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 142 g.setCodeGenerator(generator); 143 generator.genRecognizer(); // forces load of templates 144 ActionTranslator translator = 145 new ActionTranslator(generator, 146 "a", 147 new CommonToken(ANTLRParser.ACTION,action),1); 148 String rawTranslation = 149 translator.translate(); 150 STGroup templates = 151 new STGroup(); 152 ST actionST = new ST(templates, rawTranslation); 153 String found = actionST.render(); 154 155 assertNoErrors(equeue); 156 157 assertEquals(expecting, found); 158 } 159 testStringConstructor()160 @Test public void testStringConstructor() throws Exception { 161 String action = "x = %{$ID.text};"; 162 String expecting = "x = new StringTemplate(templateLib,(ID1!=null?ID1.getText():null));"; 163 164 ErrorQueue equeue = new ErrorQueue(); 165 ErrorManager.setErrorListener(equeue); 166 Grammar g = new Grammar( 167 "grammar t;\n" + 168 "options {\n" + 169 " output=template;\n" + 170 "}\n" + 171 "\n" + 172 "a : ID {"+action+"}\n" + 173 " ;\n" + 174 "\n" + 175 "ID : 'a';\n"); 176 Tool antlr = newTool(); 177 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 178 g.setCodeGenerator(generator); 179 generator.genRecognizer(); // forces load of templates 180 ActionTranslator translator = new ActionTranslator(generator, 181 "a", 182 new CommonToken(ANTLRParser.ACTION,action),1); 183 String rawTranslation = 184 translator.translate(); 185 STGroup templates = 186 new STGroup(); 187 ST actionST = new ST(templates, rawTranslation); 188 String found = actionST.render(); 189 190 assertNoErrors(equeue); 191 192 assertEquals(expecting, found); 193 } 194 testSetAttr()195 @Test public void testSetAttr() throws Exception { 196 String action = "%x.y = z;"; 197 String expecting = "(x).setAttribute(\"y\", z);"; 198 199 ErrorQueue equeue = new ErrorQueue(); 200 ErrorManager.setErrorListener(equeue); 201 Grammar g = new Grammar( 202 "grammar t;\n" + 203 "options {\n" + 204 " output=template;\n" + 205 "}\n" + 206 "\n" + 207 "a : ID {"+action+"}\n" + 208 " ;\n" + 209 "\n" + 210 "ID : 'a';\n"); 211 Tool antlr = newTool(); 212 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 213 g.setCodeGenerator(generator); 214 generator.genRecognizer(); // forces load of templates 215 ActionTranslator translator = 216 new ActionTranslator(generator, 217 "a", 218 new CommonToken(ANTLRParser.ACTION,action),1); 219 String rawTranslation = 220 translator.translate(); 221 STGroup templates = 222 new STGroup(); 223 ST actionST = new ST(templates, rawTranslation); 224 String found = actionST.render(); 225 226 assertNoErrors(equeue); 227 228 assertEquals(expecting, found); 229 } 230 testSetAttrOfExpr()231 @Test public void testSetAttrOfExpr() throws Exception { 232 String action = "%{foo($ID.text).getST()}.y = z;"; 233 String expecting = "(foo((ID1!=null?ID1.getText():null)).getST()).setAttribute(\"y\", z);"; 234 235 ErrorQueue equeue = new ErrorQueue(); 236 ErrorManager.setErrorListener(equeue); 237 Grammar g = new Grammar( 238 "grammar t;\n" + 239 "options {\n" + 240 " output=template;\n" + 241 "}\n" + 242 "\n" + 243 "a : ID {"+action+"}\n" + 244 " ;\n" + 245 "\n" + 246 "ID : 'a';\n"); 247 Tool antlr = newTool(); 248 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 249 g.setCodeGenerator(generator); 250 generator.genRecognizer(); // forces load of templates 251 ActionTranslator translator = new ActionTranslator(generator, 252 "a", 253 new CommonToken(ANTLRParser.ACTION,action),1); 254 String rawTranslation = 255 translator.translate(); 256 STGroup templates = 257 new STGroup(); 258 ST actionST = new ST(templates, rawTranslation); 259 String found = actionST.render(); 260 261 assertNoErrors(equeue); 262 263 assertEquals(expecting, found); 264 } 265 testSetAttrOfExprInMembers()266 @Test public void testSetAttrOfExprInMembers() throws Exception { 267 ErrorQueue equeue = new ErrorQueue(); 268 ErrorManager.setErrorListener(equeue); 269 Grammar g = new Grammar( 270 "grammar t;\n" + 271 "options {\n" + 272 " output=template;\n" + 273 "}\n" + 274 "@members {\n" + 275 "%code.instr = o;" + // must not get null ptr! 276 "}\n" + 277 "a : ID\n" + 278 " ;\n" + 279 "\n" + 280 "ID : 'a';\n"); 281 Tool antlr = newTool(); 282 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 283 g.setCodeGenerator(generator); 284 generator.genRecognizer(); // forces load of templates 285 286 assertNoErrors(equeue); 287 } 288 testCannotHaveSpaceBeforeDot()289 @Test public void testCannotHaveSpaceBeforeDot() throws Exception { 290 String action = "%x .y = z;"; 291 String expecting = null; 292 293 ErrorQueue equeue = new ErrorQueue(); 294 ErrorManager.setErrorListener(equeue); 295 Grammar g = new Grammar( 296 "grammar t;\n" + 297 "options {\n" + 298 " output=template;\n" + 299 "}\n" + 300 "\n" + 301 "a : ID {"+action+"}\n" + 302 " ;\n" + 303 "\n" + 304 "ID : 'a';\n"); 305 Tool antlr = newTool(); 306 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 307 g.setCodeGenerator(generator); 308 generator.genRecognizer(); // forces load of templates 309 310 int expectedMsgID = ErrorManager.MSG_INVALID_TEMPLATE_ACTION; 311 Object expectedArg = "%x"; 312 GrammarSemanticsMessage expectedMessage = 313 new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); 314 checkError(equeue, expectedMessage); 315 } 316 testCannotHaveSpaceAfterDot()317 @Test public void testCannotHaveSpaceAfterDot() throws Exception { 318 String action = "%x. y = z;"; 319 String expecting = null; 320 321 ErrorQueue equeue = new ErrorQueue(); 322 ErrorManager.setErrorListener(equeue); 323 Grammar g = new Grammar( 324 "grammar t;\n" + 325 "options {\n" + 326 " output=template;\n" + 327 "}\n" + 328 "\n" + 329 "a : ID {"+action+"}\n" + 330 " ;\n" + 331 "\n" + 332 "ID : 'a';\n"); 333 Tool antlr = newTool(); 334 CodeGenerator generator = new CodeGenerator(antlr, g, "Java"); 335 g.setCodeGenerator(generator); 336 generator.genRecognizer(); // forces load of templates 337 338 int expectedMsgID = ErrorManager.MSG_INVALID_TEMPLATE_ACTION; 339 Object expectedArg = "%x."; 340 GrammarSemanticsMessage expectedMessage = 341 new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg); 342 checkError(equeue, expectedMessage); 343 } 344 checkError(ErrorQueue equeue, GrammarSemanticsMessage expectedMessage)345 protected void checkError(ErrorQueue equeue, 346 GrammarSemanticsMessage expectedMessage) 347 throws Exception 348 { 349 /* 350 System.out.println(equeue.infos); 351 System.out.println(equeue.warnings); 352 System.out.println(equeue.errors); 353 */ 354 Message foundMsg = null; 355 for (int i = 0; i < equeue.errors.size(); i++) { 356 Message m = (Message)equeue.errors.get(i); 357 if (m.msgID==expectedMessage.msgID ) { 358 foundMsg = m; 359 } 360 } 361 assertTrue("no error; "+expectedMessage.msgID+" expected", equeue.errors.size()>0); 362 assertTrue("too many errors; "+equeue.errors, equeue.errors.size()<=1); 363 assertTrue("couldn't find expected error: "+expectedMessage.msgID, foundMsg!=null); 364 assertTrue("error is not a GrammarSemanticsMessage", 365 foundMsg instanceof GrammarSemanticsMessage); 366 assertEquals(expectedMessage.arg, foundMsg.arg); 367 assertEquals(expectedMessage.arg2, foundMsg.arg2); 368 } 369 370 // S U P P O R T assertNoErrors(ErrorQueue equeue)371 private void assertNoErrors(ErrorQueue equeue) { 372 assertTrue("unexpected errors: "+equeue, equeue.errors.size()==0); 373 } 374 } 375