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.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.*;
     38 import org.junit.Test;
     39 
     40 import java.io.StringReader;
     41 import java.util.ArrayList;
     42 import java.util.List;
     43 
     44 /** Check the $x, $x.y attributes.  For checking the actual
     45  *  translation, assume the Java target.  This is still a great test
     46  *  for the semantics of the $x.y stuff regardless of the target.
     47  */
     48 public class TestAttributes extends BaseTest {
     49 
     50 	/** Public default constructor used by TestRig */
     51 	public TestAttributes() {
     52 	}
     53 
     54 	@Test public void testEscapedLessThanInAction() throws Exception {
     55 		Grammar g = new Grammar();
     56 		Tool antlr = newTool();
     57 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
     58 		String action = "i<3; '<xmltag>'";
     59 		ActionTranslator translator = new ActionTranslator(generator,"a",
     60 			new CommonToken(ANTLRParser.ACTION,action),0);
     61 		String expecting = action;
     62 		String rawTranslation =
     63 			translator.translate();
     64 		STGroup templates =
     65 			new STGroup();
     66 		ST actionST = new ST(templates, "<action>");
     67 		actionST.add("action", rawTranslation);
     68 		String found = actionST.render();
     69 		assertEquals(expecting, found);
     70 	}
     71 
     72 	@Test public void testEscaped$InAction() throws Exception {
     73 		String action = "int \\$n; \"\\$in string\\$\"";
     74 		String expecting = "int $n; \"$in string$\"";
     75 		Grammar g = new Grammar(
     76 			"parser grammar t;\n"+
     77 				"@members {"+action+"}\n"+
     78 				"a[User u, int i]\n" +
     79 				"        : {"+action+"}\n" +
     80 				"        ;");
     81 		Tool antlr = newTool();
     82 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
     83 		g.setCodeGenerator(generator);
     84 		generator.genRecognizer(); // forces load of templates
     85 		ActionTranslator translator =
     86 			new ActionTranslator(generator,
     87 				"a",
     88 				new CommonToken(ANTLRParser.ACTION,action),0);
     89 		String found = translator.translate();		assertEquals(expecting, found);
     90 	}
     91 
     92 	@Test public void testArguments() throws Exception {
     93 		String action = "$i; $i.x; $u; $u.x";
     94 		String expecting = "i; i.x; u; u.x";
     95 
     96 		ErrorQueue equeue = new ErrorQueue();
     97 		ErrorManager.setErrorListener(equeue);
     98 		Grammar g = new Grammar(
     99 			"parser grammar t;\n"+
    100 				"a[User u, int i]\n" +
    101 				"        : {"+action+"}\n" +
    102 				"        ;");
    103 		Tool antlr = newTool();
    104 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    105 		g.setCodeGenerator(generator);
    106 		generator.genRecognizer(); // forces load of templates
    107 		ActionTranslator translator = new ActionTranslator(generator,"a",
    108 			new CommonToken(ANTLRParser.ACTION,action),1);
    109 		String found = translator.translate();		assertEquals(expecting, found);
    110 
    111 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    112 	}
    113 
    114 	@Test public void testComplicatedArgParsing() throws Exception {
    115 		String action = "x, (*a).foo(21,33), 3.2+1, '\\n', "+
    116 			"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
    117 		String expecting = "x, (*a).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
    118 
    119 		ErrorQueue equeue = new ErrorQueue();
    120 		ErrorManager.setErrorListener(equeue);
    121 
    122 		// now check in actual grammar.
    123 		Grammar g = new Grammar(
    124 			"parser grammar t;\n"+
    125 				"a[User u, int i]\n" +
    126 				"        : A a["+action+"] B\n" +
    127 				"        ;");
    128 		Tool antlr = newTool();
    129 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    130 		g.setCodeGenerator(generator);
    131 		generator.genRecognizer(); // forces load of templates
    132 		ActionTranslator translator = new ActionTranslator(generator,"a",
    133 			new CommonToken(ANTLRParser.ACTION,action),1);
    134 		String rawTranslation =	translator.translate();
    135 		assertEquals(expecting, rawTranslation);
    136 
    137 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    138 	}
    139 
    140 	@Test public void testBracketArgParsing() throws Exception {
    141 		ErrorQueue equeue = new ErrorQueue();
    142 		ErrorManager.setErrorListener(equeue);
    143 
    144 		// now check in actual grammar.
    145 		Grammar g = new Grammar(
    146 			"parser grammar t;\n"+
    147 				"a[String[\\] ick, int i]\n" +
    148 				"        : A \n"+
    149 				"        ;");
    150 		Tool antlr = newTool();
    151 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    152 		g.setCodeGenerator(generator);
    153 		generator.genRecognizer(); // forces load of templates
    154 		Rule r = g.getRule("a");
    155 		AttributeScope parameters = r.parameterScope;
    156 		List<Attribute> attrs = parameters.getAttributes();
    157 		assertEquals("attribute mismatch","String[] ick",attrs.get(0).decl.toString());
    158 		assertEquals("parameter name mismatch","ick",attrs.get(0).name);
    159 		assertEquals("declarator mismatch", "String[]", attrs.get(0).type);
    160 
    161 		assertEquals("attribute mismatch","int i",attrs.get(1).decl.toString());
    162 		assertEquals("parameter name mismatch","i",attrs.get(1).name);
    163 		assertEquals("declarator mismatch", "int", attrs.get(1).type);
    164 
    165 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    166 	}
    167 
    168 	@Test public void testStringArgParsing() throws Exception {
    169 		String action = "34, '{', \"it's<\", '\"', \"\\\"\", 19";
    170 		String expecting = "34, '{', \"it's<\", '\"', \"\\\"\", 19";
    171 
    172 		ErrorQueue equeue = new ErrorQueue();
    173 		ErrorManager.setErrorListener(equeue);
    174 
    175 		// now check in actual grammar.
    176 		Grammar g = new Grammar(
    177 			"parser grammar t;\n"+
    178 				"a[User u, int i]\n" +
    179 				"        : A a["+action+"] B\n" +
    180 				"        ;");
    181 		Tool antlr = newTool();
    182 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    183 		g.setCodeGenerator(generator);
    184 		generator.genRecognizer(); // forces load of templates
    185 		ActionTranslator translator = new ActionTranslator(generator,"a",
    186 			new CommonToken(ANTLRParser.ACTION,action),1);
    187 		String rawTranslation =	translator.translate();
    188 		assertEquals(expecting, rawTranslation);
    189 
    190 		List<String> expectArgs = new ArrayList<String>() {
    191 			{add("34");}
    192 			{add("'{'");}
    193 			{add("\"it's<\"");}
    194 			{add("'\"'");}
    195 			{add("\"\\\"\"");} // that's "\""
    196 			{add("19");}
    197 		};
    198 		List<String> actualArgs = CodeGenerator.getListOfArgumentsFromAction(action, ',');
    199 		assertEquals("args mismatch", expectArgs, actualArgs);
    200 
    201 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    202 	}
    203 
    204 	@Test public void testComplicatedSingleArgParsing() throws Exception {
    205 		String action = "(*a).foo(21,33,\",\")";
    206 		String expecting = "(*a).foo(21,33,\",\")";
    207 
    208 		ErrorQueue equeue = new ErrorQueue();
    209 		ErrorManager.setErrorListener(equeue);
    210 
    211 		// now check in actual grammar.
    212 		Grammar g = new Grammar(
    213 			"parser grammar t;\n"+
    214 				"a[User u, int i]\n" +
    215 				"        : A a["+action+"] B\n" +
    216 				"        ;");
    217 		Tool antlr = newTool();
    218 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    219 		g.setCodeGenerator(generator);
    220 		generator.genRecognizer(); // forces load of templates
    221 		ActionTranslator translator = new ActionTranslator(generator,"a",
    222 			new CommonToken(ANTLRParser.ACTION,action),1);
    223 		String rawTranslation =	translator.translate();
    224 		assertEquals(expecting, rawTranslation);
    225 
    226 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    227 	}
    228 
    229 	@Test public void testArgWithLT() throws Exception {
    230 		String action = "34<50";
    231 		String expecting = "34<50";
    232 
    233 		ErrorQueue equeue = new ErrorQueue();
    234 		ErrorManager.setErrorListener(equeue);
    235 
    236 		// now check in actual grammar.
    237 		Grammar g = new Grammar(
    238 			"parser grammar t;\n"+
    239 				"a[boolean b]\n" +
    240 				"        : A a["+action+"] B\n" +
    241 				"        ;");
    242 		Tool antlr = newTool();
    243 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    244 		g.setCodeGenerator(generator);
    245 		generator.genRecognizer(); // forces load of templates
    246 		ActionTranslator translator = new ActionTranslator(generator,"a",
    247 			new CommonToken(ANTLRParser.ACTION,action),1);
    248 		String rawTranslation =
    249 			translator.translate();
    250 		assertEquals(expecting, rawTranslation);
    251 
    252 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    253 	}
    254 
    255 	@Test public void testGenericsAsArgumentDefinition() throws Exception {
    256 		String action = "$foo.get(\"ick\");";
    257 		String expecting = "foo.get(\"ick\");";
    258 
    259 		ErrorQueue equeue = new ErrorQueue();
    260 		ErrorManager.setErrorListener(equeue);
    261 		String grammar =
    262 			"parser grammar T;\n"+
    263 				"a[HashMap<String,String> foo]\n" +
    264 				"        : {"+action+"}\n" +
    265 				"        ;";
    266 		Grammar g = new Grammar(grammar);
    267 		Rule ra = g.getRule("a");
    268 		List<Attribute> attrs = ra.parameterScope.getAttributes();
    269 		assertEquals("attribute mismatch","HashMap<String,String> foo",attrs.get(0).decl.toString());
    270 		assertEquals("parameter name mismatch","foo",attrs.get(0).name);
    271 		assertEquals("declarator mismatch", "HashMap<String,String>", attrs.get(0).type);
    272 
    273 		Tool antlr = newTool();
    274 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    275 		g.setCodeGenerator(generator);
    276 		generator.genRecognizer(); // forces load of templates
    277 		ActionTranslator translator = new ActionTranslator(generator,"a",
    278 			new CommonToken(ANTLRParser.ACTION,action),1);
    279 		String found = translator.translate();		assertEquals(expecting, found);
    280 
    281 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    282 	}
    283 
    284 	@Test public void testGenericsAsArgumentDefinition2() throws Exception {
    285 		String action = "$foo.get(\"ick\"); x=3;";
    286 		String expecting = "foo.get(\"ick\"); x=3;";
    287 
    288 		ErrorQueue equeue = new ErrorQueue();
    289 		ErrorManager.setErrorListener(equeue);
    290 		String grammar =
    291 			"parser grammar T;\n"+
    292 				"a[HashMap<String,String> foo, int x, List<String> duh]\n" +
    293 				"        : {"+action+"}\n" +
    294 				"        ;";
    295 		Grammar g = new Grammar(grammar);
    296 		Rule ra = g.getRule("a");
    297 		List<Attribute> attrs = ra.parameterScope.getAttributes();
    298 
    299 		assertEquals("attribute mismatch","HashMap<String,String> foo",attrs.get(0).decl.toString().trim());
    300 		assertEquals("parameter name mismatch","foo",attrs.get(0).name);
    301 		assertEquals("declarator mismatch", "HashMap<String,String>", attrs.get(0).type);
    302 
    303 		assertEquals("attribute mismatch","int x",attrs.get(1).decl.toString().trim());
    304 		assertEquals("parameter name mismatch","x",attrs.get(1).name);
    305 		assertEquals("declarator mismatch", "int", attrs.get(1).type);
    306 
    307 		assertEquals("attribute mismatch","List<String> duh",attrs.get(2).decl.toString().trim());
    308 		assertEquals("parameter name mismatch","duh",attrs.get(2).name);
    309 		assertEquals("declarator mismatch", "List<String>", attrs.get(2).type);
    310 
    311 		Tool antlr = newTool();
    312 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    313 		g.setCodeGenerator(generator);
    314 		generator.genRecognizer(); // forces load of templates
    315 		ActionTranslator translator = new ActionTranslator(generator,"a",
    316 			new CommonToken(ANTLRParser.ACTION,action),1);
    317 		String found = translator.translate();		assertEquals(expecting, found);
    318 
    319 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    320 	}
    321 
    322 	@Test public void testGenericsAsReturnValue() throws Exception {
    323 		ErrorQueue equeue = new ErrorQueue();
    324 		ErrorManager.setErrorListener(equeue);
    325 		String grammar =
    326 			"parser grammar T;\n"+
    327 				"a returns [HashMap<String,String> foo] : ;\n";
    328 		Grammar g = new Grammar(grammar);
    329 		Rule ra = g.getRule("a");
    330 		List<Attribute> attrs = ra.returnScope.getAttributes();
    331 		assertEquals("attribute mismatch","HashMap<String,String> foo",attrs.get(0).decl.toString());
    332 		assertEquals("parameter name mismatch","foo",attrs.get(0).name);
    333 		assertEquals("declarator mismatch", "HashMap<String,String>", attrs.get(0).type);
    334 
    335 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    336 	}
    337 
    338 	@Test public void testComplicatedArgParsingWithTranslation() throws Exception {
    339 		String action = "x, $A.text+\"3242\", (*$A).foo(21,33), 3.2+1, '\\n', "+
    340 			"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
    341 		String expecting = "x, (A1!=null?A1.getText():null)+\"3242\", (*A1).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
    342 
    343 		ErrorQueue equeue = new ErrorQueue();
    344 		ErrorManager.setErrorListener(equeue);
    345 
    346 		// now check in actual grammar.
    347 		Grammar g = new Grammar(
    348 			"parser grammar t;\n"+
    349 				"a[User u, int i]\n" +
    350 				"        : A a["+action+"] B\n" +
    351 				"        ;");
    352 		Tool antlr = newTool();
    353 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    354 		g.setCodeGenerator(generator);
    355 		generator.genRecognizer(); // forces load of templates
    356 		ActionTranslator translator = new ActionTranslator(generator,"a",
    357 			new CommonToken(ANTLRParser.ACTION,action),1);
    358 		String found = translator.translate();		assertEquals(expecting, found);
    359 
    360 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    361 	}
    362 
    363 	/** $x.start refs are checked during translation not before so ANTLR misses
    364 	 the fact that rule r has refs to predefined attributes if the ref is after
    365 	 the def of the method or self-referential.  Actually would be ok if I didn't
    366 	 convert actions to strings; keep as templates.
    367 	 June 9, 2006: made action translation leave templates not strings
    368 	 */
    369 	@Test public void testRefToReturnValueBeforeRefToPredefinedAttr() throws Exception {
    370 		String action = "$x.foo";
    371 		String expecting = "(x!=null?x.foo:0)";
    372 
    373 		ErrorQueue equeue = new ErrorQueue();
    374 		ErrorManager.setErrorListener(equeue);
    375 		Grammar g = new Grammar(
    376 			"parser grammar t;\n"+
    377 				"a : x=b {"+action+"} ;\n" +
    378 				"b returns [int foo] : B {$b.start} ;\n");
    379 		Tool antlr = newTool();
    380 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    381 		g.setCodeGenerator(generator);
    382 		generator.genRecognizer(); // forces load of templates
    383 		ActionTranslator translator = new ActionTranslator(generator,"a",
    384 			new CommonToken(ANTLRParser.ACTION,action),1);
    385 		String found = translator.translate();
    386 		assertEquals(expecting, found);
    387 
    388 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    389 	}
    390 
    391 	@Test public void testRuleLabelBeforeRefToPredefinedAttr() throws Exception {
    392 		// As of Mar 2007, I'm removing unused labels.  Unfortunately,
    393 		// the action is not seen until code gen.  Can't see $x.text
    394 		// before stripping unused labels.  We really need to translate
    395 		// actions first so code gen logic can use info.
    396 		String action = "$x.text";
    397 		String expecting = "(x!=null?input.toString(x.start,x.stop):null)";
    398 
    399 		ErrorQueue equeue = new ErrorQueue();
    400 		ErrorManager.setErrorListener(equeue);
    401 		Grammar g = new Grammar(
    402 			"parser grammar t;\n"+
    403 				"a : x=b {###"+action+"!!!} ;\n" +
    404 				"b : B ;\n");
    405 		Tool antlr = newTool();
    406 
    407 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    408 		g.setCodeGenerator(generator);
    409 		generator.genRecognizer(); // codegen phase sets some vars we need
    410 		ST codeST = generator.getRecognizerST();
    411 		String code = codeST.render();
    412 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
    413 		assertEquals(expecting, found);
    414 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    415 	}
    416 
    417 	@Test public void testInvalidArguments() throws Exception {
    418 		String action = "$x";
    419 		String expecting = action;
    420 
    421 		ErrorQueue equeue = new ErrorQueue();
    422 		ErrorManager.setErrorListener(equeue);
    423 		Grammar g = new Grammar(
    424 			"parser grammar t;\n"+
    425 				"a[User u, int i]\n" +
    426 				"        : {"+action+"}\n" +
    427 				"        ;");
    428 		Tool antlr = newTool();
    429 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    430 		ActionTranslator translator = new ActionTranslator(generator,
    431 			"a",
    432 			new CommonToken(ANTLRParser.ACTION,action),1);
    433 		String found = translator.translate();
    434 		assertEquals(expecting, found);
    435 
    436 		int expectedMsgID = ErrorManager.MSG_UNKNOWN_SIMPLE_ATTRIBUTE;
    437 		Object expectedArg = "x";
    438 		GrammarSemanticsMessage expectedMessage =
    439 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
    440 		checkError(equeue, expectedMessage);
    441 	}
    442 
    443 	@Test public void testReturnValue() throws Exception {
    444 		String action = "$x.i";
    445 		String expecting = "x";
    446 
    447 		ErrorQueue equeue = new ErrorQueue();
    448 		ErrorManager.setErrorListener(equeue);
    449 		Grammar g = new Grammar(
    450 			"grammar t;\n"+
    451 				"a returns [int i]\n" +
    452 				"        : 'a'\n" +
    453 				"        ;\n" +
    454 				"b : x=a {"+action+"} ;\n");
    455 		Tool antlr = newTool();
    456 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    457 		g.setCodeGenerator(generator);
    458 		generator.genRecognizer(); // forces load of templates
    459 		ActionTranslator translator =
    460 			new ActionTranslator(generator,
    461 				"b",
    462 				new CommonToken(ANTLRParser.ACTION,action),1);
    463 		String found =	translator.translate();
    464 		assertEquals(expecting, found);
    465 
    466 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    467 	}
    468 
    469 	@Test public void testActionNotMovedToSynPred() throws Exception {
    470 		String action = "$b = true;";
    471 		String expecting = "retval.b = true;";
    472 
    473 		ErrorQueue equeue = new ErrorQueue();
    474 		ErrorManager.setErrorListener(equeue);
    475 		Grammar g = new Grammar(
    476 			"grammar t;\n"+
    477 			"options {output=AST;}\n" + // push b into retval struct
    478 			"a returns [boolean b]\n" +
    479 			"options {backtrack=true;}\n" +
    480 			"   : 'a' {"+action+"}\n" +
    481 			"   | 'a'\n" +
    482 			"   ;\n");
    483 		Tool antlr = newTool();
    484 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    485 		g.setCodeGenerator(generator);
    486 		generator.genRecognizer(); // forces load of templates
    487 		ActionTranslator translator =
    488 			new ActionTranslator(generator,
    489 				"a",
    490 				new CommonToken(ANTLRParser.ACTION,action),1);
    491 		String found =	translator.translate();
    492 		assertEquals(expecting, found);
    493 
    494 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    495 	}
    496 
    497 	@Test public void testReturnValueWithNumber() throws Exception {
    498 		String action = "$x.i1";
    499 		String expecting = "x";
    500 
    501 		ErrorQueue equeue = new ErrorQueue();
    502 		ErrorManager.setErrorListener(equeue);
    503 		Grammar g = new Grammar(
    504 			"grammar t;\n"+
    505 				"a returns [int i1]\n" +
    506 				"        : 'a'\n" +
    507 				"        ;\n" +
    508 				"b : x=a {"+action+"} ;\n");
    509 		Tool antlr = newTool();
    510 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    511 		g.setCodeGenerator(generator);
    512 		generator.genRecognizer(); // forces load of templates
    513 		ActionTranslator translator =
    514 			new ActionTranslator(generator,
    515 				"b",
    516 				new CommonToken(ANTLRParser.ACTION,action),1);
    517 		String found = translator.translate();
    518 		assertEquals(expecting, found);
    519 
    520 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    521 	}
    522 
    523 	@Test public void testReturnValues() throws Exception {
    524 		String action = "$i; $i.x; $u; $u.x";
    525 		String expecting = "retval.i; retval.i.x; retval.u; retval.u.x";
    526 
    527 		ErrorQueue equeue = new ErrorQueue();
    528 		ErrorManager.setErrorListener(equeue);
    529 		Grammar g = new Grammar(
    530 			"parser grammar t;\n"+
    531 				"a returns [User u, int i]\n" +
    532 				"        : {"+action+"}\n" +
    533 				"        ;");
    534 		Tool antlr = newTool();
    535 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    536 		g.setCodeGenerator(generator);
    537 		generator.genRecognizer(); // forces load of templates
    538 		ActionTranslator translator = new ActionTranslator(generator,"a",
    539 			new CommonToken(ANTLRParser.ACTION,action),1);
    540 		String found = translator.translate();
    541 		assertEquals(expecting, found);
    542 
    543 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    544 	}
    545 
    546 	/* regression test for ANTLR-46 */
    547 	@Test public void testReturnWithMultipleRuleRefs() throws Exception {
    548 		String action1 = "$obj = $rule2.obj;";
    549 		String action2 = "$obj = $rule3.obj;";
    550 		String expecting1 = "obj = rule21;";
    551 		String expecting2 = "obj = rule32;";
    552 
    553 		ErrorQueue equeue = new ErrorQueue();
    554 		ErrorManager.setErrorListener(equeue);
    555 		Grammar g = new Grammar(
    556 			"grammar t;\n" +
    557 				"rule1 returns [ Object obj ]\n" +
    558 				":	rule2 { "+action1+" }\n" +
    559 				"|	rule3 { "+action2+" }\n" +
    560 				";\n"+
    561 				"rule2 returns [ Object obj ]\n"+
    562 				":	foo='foo' { $obj = $foo.text; }\n"+
    563 				";\n"+
    564 				"rule3 returns [ Object obj ]\n"+
    565 				":	bar='bar' { $obj = $bar.text; }\n"+
    566 				";");
    567 		Tool antlr = newTool();
    568 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    569 		g.setCodeGenerator(generator);
    570 		generator.genRecognizer(); // forces load of templates
    571 		int i = 0;
    572 		String action = action1;
    573 		String expecting = expecting1;
    574 		do {
    575 			ActionTranslator translator = new ActionTranslator(generator,"rule1",
    576 				new CommonToken(ANTLRParser.ACTION,action),i+1);
    577 			String found = translator.translate();
    578 			assertEquals(expecting, found);
    579 			action = action2;
    580 			expecting = expecting2;
    581 		} while (i++ < 1);
    582 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    583 	}
    584 
    585 	@Test public void testInvalidReturnValues() throws Exception {
    586 		String action = "$x";
    587 		String expecting = action;
    588 
    589 		ErrorQueue equeue = new ErrorQueue();
    590 		ErrorManager.setErrorListener(equeue);
    591 		Grammar g = new Grammar(
    592 			"parser grammar t;\n"+
    593 				"a returns [User u, int i]\n" +
    594 				"        : {"+action+"}\n" +
    595 				"        ;");
    596 		Tool antlr = newTool();
    597 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    598 		ActionTranslator translator = new ActionTranslator(generator,"a",
    599 			new CommonToken(ANTLRParser.ACTION,action),1);
    600 		String found = translator.translate();
    601 		assertEquals(expecting, found);
    602 
    603 		int expectedMsgID = ErrorManager.MSG_UNKNOWN_SIMPLE_ATTRIBUTE;
    604 		Object expectedArg = "x";
    605 		GrammarSemanticsMessage expectedMessage =
    606 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
    607 		checkError(equeue, expectedMessage);
    608 	}
    609 
    610 	@Test public void testTokenLabels() throws Exception {
    611 		String action = "$id; $f; $id.text; $id.getText(); $id.dork " +
    612 			"$id.type; $id.line; $id.pos; " +
    613 			"$id.channel; $id.index;";
    614 		String expecting = "id; f; (id!=null?id.getText():null); id.getText(); id.dork (id!=null?id.getType():0); (id!=null?id.getLine():0); (id!=null?id.getCharPositionInLine():0); (id!=null?id.getChannel():0); (id!=null?id.getTokenIndex():0);";
    615 
    616 		ErrorQueue equeue = new ErrorQueue();
    617 		ErrorManager.setErrorListener(equeue);
    618 		Grammar g = new Grammar(
    619 			"parser grammar t;\n"+
    620 				"a : id=ID f=FLOAT {"+action+"}\n" +
    621 				"  ;");
    622 		Tool antlr = newTool();
    623 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    624 		g.setCodeGenerator(generator);
    625 		generator.genRecognizer(); // forces load of templates
    626 		ActionTranslator translator = new ActionTranslator(generator,"a",
    627 			new CommonToken(ANTLRParser.ACTION,action),1);
    628 		String found = translator.translate();
    629 		assertEquals(expecting, found);
    630 
    631 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    632 	}
    633 
    634 	@Test public void testRuleLabels() throws Exception {
    635 		String action = "$r.x; $r.start;\n $r.stop;\n $r.tree; $a.x; $a.stop;";
    636 		String expecting = "(r!=null?r.x:0); (r!=null?((Token)r.start):null);" + newline +
    637 			"             (r!=null?((Token)r.stop):null);" + newline +
    638 			"             (r!=null?((Object)r.tree):null); (r!=null?r.x:0); (r!=null?((Token)r.stop):null);";
    639 
    640 		ErrorQueue equeue = new ErrorQueue();
    641 		ErrorManager.setErrorListener(equeue);
    642 		Grammar g = new Grammar(
    643 			"parser grammar t;\n"+
    644 				"a returns [int x]\n" +
    645 				"  :\n" +
    646 				"  ;\n"+
    647 				"b : r=a {###"+action+"!!!}\n" +
    648 				"  ;");
    649 		Tool antlr = newTool();
    650 		antlr.setOutputDirectory(null); // write to /dev/null
    651 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    652 		g.setCodeGenerator(generator);
    653 		generator.genRecognizer(); // codegen phase sets some vars we need
    654 		ST codeST = generator.getRecognizerST();
    655 		String code = codeST.render();
    656 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
    657 		assertEquals(expecting, found);
    658 
    659 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    660 	}
    661 
    662 	@Test public void testAmbiguRuleRef() throws Exception {
    663 		ErrorQueue equeue = new ErrorQueue();
    664 		ErrorManager.setErrorListener(equeue);
    665 		Grammar g = new Grammar(
    666 			"parser grammar t;\n"+
    667 				"a : A a {$a.text} | B ;");
    668 		Tool antlr = newTool();
    669 		antlr.setOutputDirectory(null); // write to /dev/null
    670 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    671 		g.setCodeGenerator(generator);
    672 		generator.genRecognizer();
    673 
    674 		// error(132): <string>:2:9: reference $a is ambiguous; rule a is enclosing rule and referenced in the production
    675 		assertEquals("unexpected errors: "+equeue, 1, equeue.errors.size());
    676 	}
    677 
    678 	@Test public void testRuleLabelsWithSpecialToken() throws Exception {
    679 		String action = "$r.x; $r.start; $r.stop; $r.tree; $a.x; $a.stop;";
    680 		String expecting = "(r!=null?r.x:0); (r!=null?((MYTOKEN)r.start):null); (r!=null?((MYTOKEN)r.stop):null); (r!=null?((Object)r.tree):null); (r!=null?r.x:0); (r!=null?((MYTOKEN)r.stop):null);";
    681 
    682 		ErrorQueue equeue = new ErrorQueue();
    683 		ErrorManager.setErrorListener(equeue);
    684 		Grammar g = new Grammar(
    685 			"parser grammar t;\n"+
    686 				"options {TokenLabelType=MYTOKEN;}\n"+
    687 				"a returns [int x]\n" +
    688 				"  :\n" +
    689 				"  ;\n"+
    690 				"b : r=a {###"+action+"!!!}\n" +
    691 				"  ;");
    692 		Tool antlr = newTool();
    693 		antlr.setOutputDirectory(null); // write to /dev/null
    694 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    695 		g.setCodeGenerator(generator);
    696 		generator.genRecognizer(); // codegen phase sets some vars we need
    697 
    698 		ST codeST = generator.getRecognizerST();
    699 		String code = codeST.render();
    700 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
    701 		assertEquals(expecting, found);
    702 
    703 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    704 	}
    705 
    706 	@Test public void testForwardRefRuleLabels() throws Exception {
    707 		String action = "$r.x; $r.start; $r.stop; $r.tree; $a.x; $a.tree;";
    708 		String expecting = "(r!=null?r.x:0); (r!=null?((Token)r.start):null); (r!=null?((Token)r.stop):null); (r!=null?((Object)r.tree):null); (r!=null?r.x:0); (r!=null?((Object)r.tree):null);";
    709 
    710 		ErrorQueue equeue = new ErrorQueue();
    711 		ErrorManager.setErrorListener(equeue);
    712 		Grammar g = new Grammar(
    713 			"parser grammar t;\n"+
    714 				"b : r=a {###"+action+"!!!}\n" +
    715 				"  ;\n" +
    716 				"a returns [int x]\n" +
    717 				"  : ;\n");
    718 		Tool antlr = newTool();
    719 		antlr.setOutputDirectory(null); // write to /dev/null
    720 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    721 		g.setCodeGenerator(generator);
    722 		generator.genRecognizer(); // codegen phase sets some vars we need
    723 
    724 		ST codeST = generator.getRecognizerST();
    725 		String code = codeST.render();
    726 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
    727 		assertEquals(expecting, found);
    728 
    729 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    730 	}
    731 
    732 	@Test public void testInvalidRuleLabelAccessesParameter() throws Exception {
    733 		String action = "$r.z";
    734 		String expecting = action;
    735 
    736 		ErrorQueue equeue = new ErrorQueue();
    737 		ErrorManager.setErrorListener(equeue);
    738 		Grammar g = new Grammar(
    739 			"parser grammar t;\n"+
    740 				"a[int z] returns [int x]\n" +
    741 				"  :\n" +
    742 				"  ;\n"+
    743 				"b : r=a[3] {"+action+"}\n" +
    744 				"  ;");
    745 		Tool antlr = newTool();
    746 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    747 		ActionTranslator translator = new ActionTranslator(generator, "b",
    748 			new CommonToken(ANTLRParser.ACTION,action),1);
    749 		String found = translator.translate();		assertEquals(expecting, found);
    750 
    751 		int expectedMsgID = ErrorManager.MSG_INVALID_RULE_PARAMETER_REF;
    752 		Object expectedArg = "a";
    753 		Object expectedArg2 = "z";
    754 		GrammarSemanticsMessage expectedMessage =
    755 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
    756 		checkError(equeue, expectedMessage);
    757 	}
    758 
    759 	@Test public void testInvalidRuleLabelAccessesScopeAttribute() throws Exception {
    760 		String action = "$r.n";
    761 		String expecting = action;
    762 
    763 		ErrorQueue equeue = new ErrorQueue();
    764 		ErrorManager.setErrorListener(equeue);
    765 		Grammar g = new Grammar(
    766 			"parser grammar t;\n"+
    767 				"a\n" +
    768 				"scope { int n; }\n" +
    769 				"  :\n" +
    770 				"  ;\n"+
    771 				"b : r=a[3] {"+action+"}\n" +
    772 				"  ;");
    773 		Tool antlr = newTool();
    774 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    775 		ActionTranslator translator = new ActionTranslator(generator, "b",
    776 			new CommonToken(ANTLRParser.ACTION,action),1);
    777 		String found = translator.translate();
    778 		assertEquals(expecting, found);
    779 
    780 		int expectedMsgID = ErrorManager.MSG_INVALID_RULE_SCOPE_ATTRIBUTE_REF;
    781 		Object expectedArg = "a";
    782 		Object expectedArg2 = "n";
    783 		GrammarSemanticsMessage expectedMessage =
    784 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
    785 		checkError(equeue, expectedMessage);
    786 	}
    787 
    788 	@Test public void testInvalidRuleAttribute() throws Exception {
    789 		String action = "$r.blort";
    790 		String expecting = action;
    791 
    792 		ErrorQueue equeue = new ErrorQueue();
    793 		ErrorManager.setErrorListener(equeue);
    794 		Grammar g = new Grammar(
    795 			"parser grammar t;\n"+
    796 				"a[int z] returns [int x]\n" +
    797 				"  :\n" +
    798 				"  ;\n"+
    799 				"b : r=a[3] {"+action+"}\n" +
    800 				"  ;");
    801 		Tool antlr = newTool();
    802 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    803 		ActionTranslator translator = new ActionTranslator(generator, "b",
    804 			new CommonToken(ANTLRParser.ACTION,action),1);
    805 		String found = translator.translate();
    806 		assertEquals(expecting, found);
    807 
    808 		int expectedMsgID = ErrorManager.MSG_UNKNOWN_RULE_ATTRIBUTE;
    809 		Object expectedArg = "a";
    810 		Object expectedArg2 = "blort";
    811 		GrammarSemanticsMessage expectedMessage =
    812 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
    813 		checkError(equeue, expectedMessage);
    814 	}
    815 
    816 	@Test public void testMissingRuleAttribute() throws Exception {
    817 		String action = "$r";
    818 		String expecting = action;
    819 
    820 		ErrorQueue equeue = new ErrorQueue();
    821 		ErrorManager.setErrorListener(equeue);
    822 		Grammar g = new Grammar(
    823 			"parser grammar t;\n"+
    824 				"a[int z] returns [int x]\n" +
    825 				"  :\n" +
    826 				"  ;\n"+
    827 				"b : r=a[3] {"+action+"}\n" +
    828 				"  ;");
    829 		Tool antlr = newTool();
    830 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    831 		ActionTranslator translator = new ActionTranslator(generator, "b",
    832 			new CommonToken(ANTLRParser.ACTION,action),1);
    833 		String rawTranslation =
    834 			translator.translate();
    835 
    836 		int expectedMsgID = ErrorManager.MSG_ISOLATED_RULE_SCOPE;
    837 		Object expectedArg = "r";
    838 		Object expectedArg2 = null;
    839 		GrammarSemanticsMessage expectedMessage =
    840 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
    841 		checkError(equeue, expectedMessage);
    842 	}
    843 
    844 	@Test public void testMissingUnlabeledRuleAttribute() throws Exception {
    845 		String action = "$a";
    846 		String expecting = action;
    847 
    848 		ErrorQueue equeue = new ErrorQueue();
    849 		ErrorManager.setErrorListener(equeue);
    850 		Grammar g = new Grammar(
    851 			"parser grammar t;\n"+
    852 				"a returns [int x]:\n" +
    853 				"  ;\n"+
    854 				"b : a {"+action+"}\n" +
    855 				"  ;");
    856 		Tool antlr = newTool();
    857 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    858 		ActionTranslator translator = new ActionTranslator(generator, "b",
    859 			new CommonToken(ANTLRParser.ACTION,action),1);
    860 		String rawTranslation =
    861 			translator.translate();
    862 
    863 		int expectedMsgID = ErrorManager.MSG_ISOLATED_RULE_SCOPE;
    864 		Object expectedArg = "a";
    865 		GrammarSemanticsMessage expectedMessage =
    866 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
    867 		checkError(equeue, expectedMessage);
    868 	}
    869 
    870 	@Test public void testNonDynamicAttributeOutsideRule() throws Exception {
    871 		String action = "public void foo() { $x; }";
    872 		String expecting = action;
    873 
    874 		ErrorQueue equeue = new ErrorQueue();
    875 		ErrorManager.setErrorListener(equeue);
    876 		Grammar g = new Grammar(
    877 			"parser grammar t;\n"+
    878 				"@members {'+action+'}\n" +
    879 				"a : ;\n");
    880 		Tool antlr = newTool();
    881 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    882 		ActionTranslator translator = new ActionTranslator(generator,
    883 			null,
    884 			new CommonToken(ANTLRParser.ACTION,action),0);
    885 		String found = translator.translate();		assertEquals(expecting, found);
    886 
    887 		int expectedMsgID = ErrorManager.MSG_ATTRIBUTE_REF_NOT_IN_RULE;
    888 		Object expectedArg = "x";
    889 		GrammarSemanticsMessage expectedMessage =
    890 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
    891 		checkError(equeue, expectedMessage);
    892 	}
    893 
    894 	@Test public void testNonDynamicAttributeOutsideRule2() throws Exception {
    895 		String action = "public void foo() { $x.y; }";
    896 		String expecting = action;
    897 
    898 		ErrorQueue equeue = new ErrorQueue();
    899 		ErrorManager.setErrorListener(equeue);
    900 		Grammar g = new Grammar(
    901 			"parser grammar t;\n"+
    902 				"@members {'+action+'}\n" +
    903 				"a : ;\n");
    904 		Tool antlr = newTool();
    905 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    906 		ActionTranslator translator = new ActionTranslator(generator,
    907 			null,
    908 			new CommonToken(ANTLRParser.ACTION,action),0);
    909 		String found = translator.translate();
    910 		assertEquals(expecting, found);
    911 
    912 		int expectedMsgID = ErrorManager.MSG_ATTRIBUTE_REF_NOT_IN_RULE;
    913 		Object expectedArg = "x";
    914 		Object expectedArg2 = "y";
    915 		GrammarSemanticsMessage expectedMessage =
    916 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
    917 		checkError(equeue, expectedMessage);
    918 	}
    919 
    920 	// D Y N A M I C A L L Y  S C O P E D  A T T R I B U T E S
    921 
    922 	@Test public void testBasicGlobalScope() throws Exception {
    923 		String action = "$Symbols::names.add($id.text);";
    924 		String expecting = "((Symbols_scope)Symbols_stack.peek()).names.add((id!=null?id.getText():null));";
    925 
    926 		ErrorQueue equeue = new ErrorQueue();
    927 		ErrorManager.setErrorListener(equeue);
    928 		Grammar g = new Grammar(
    929 			"grammar t;\n"+
    930 				"scope Symbols {\n" +
    931 				"  int n;\n" +
    932 				"  List names;\n" +
    933 				"}\n" +
    934 				"a scope Symbols; : (id=ID ';' {"+action+"} )+\n" +
    935 				"  ;\n" +
    936 				"ID : 'a';\n");
    937 		Tool antlr = newTool();
    938 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    939 		g.setCodeGenerator(generator);
    940 		generator.genRecognizer(); // forces load of templates
    941 		ActionTranslator translator = new ActionTranslator(generator,"a",
    942 			new CommonToken(ANTLRParser.ACTION,action),1);
    943 		String found = translator.translate();
    944 		assertEquals(expecting, found);
    945 
    946 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
    947 	}
    948 
    949 	@Test public void testUnknownGlobalScope() throws Exception {
    950 		String action = "$Symbols::names.add($id.text);";
    951 
    952 		ErrorQueue equeue = new ErrorQueue();
    953 		ErrorManager.setErrorListener(equeue);
    954 		Grammar g = new Grammar(
    955 			"grammar t;\n"+
    956 				"a scope Symbols; : (id=ID ';' {"+action+"} )+\n" +
    957 				"  ;\n" +
    958 				"ID : 'a';\n");
    959 		Tool antlr = newTool();
    960 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    961 		g.setCodeGenerator(generator);
    962 		generator.genRecognizer(); // forces load of templates
    963 		ActionTranslator translator = new ActionTranslator(generator,"a",
    964 			new CommonToken(ANTLRParser.ACTION,action),1);
    965 
    966 		assertEquals("unexpected errors: "+equeue, 2, equeue.errors.size());
    967 
    968 		int expectedMsgID = ErrorManager.MSG_UNKNOWN_DYNAMIC_SCOPE;
    969 		Object expectedArg = "Symbols";
    970 		GrammarSemanticsMessage expectedMessage =
    971 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
    972 		checkError(equeue, expectedMessage);
    973 	}
    974 
    975 	@Test public void testIndexedGlobalScope() throws Exception {
    976 		String action = "$Symbols[-1]::names.add($id.text);";
    977 		String expecting =
    978 			"((Symbols_scope)Symbols_stack.elementAt(Symbols_stack.size()-1-1)).names.add((id!=null?id.getText():null));";
    979 
    980 		ErrorQueue equeue = new ErrorQueue();
    981 		ErrorManager.setErrorListener(equeue);
    982 		Grammar g = new Grammar(
    983 			"grammar t;\n"+
    984 				"scope Symbols {\n" +
    985 				"  int n;\n" +
    986 				"  List names;\n" +
    987 				"}\n" +
    988 				"a scope Symbols; : (id=ID ';' {"+action+"} )+\n" +
    989 				"  ;\n" +
    990 				"ID : 'a';\n");
    991 		Tool antlr = newTool();
    992 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
    993 		g.setCodeGenerator(generator);
    994 		generator.genRecognizer(); // forces load of templates
    995 		ActionTranslator translator = new ActionTranslator(generator,"a",
    996 			new CommonToken(ANTLRParser.ACTION,action),1);
    997 		String found = translator.translate();
    998 		assertEquals(expecting, found);
    999 
   1000 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1001 	}
   1002 
   1003 	@Test public void test0IndexedGlobalScope() throws Exception {
   1004 		String action = "$Symbols[0]::names.add($id.text);";
   1005 		String expecting =
   1006 			"((Symbols_scope)Symbols_stack.elementAt(0)).names.add((id!=null?id.getText():null));";
   1007 
   1008 		ErrorQueue equeue = new ErrorQueue();
   1009 		ErrorManager.setErrorListener(equeue);
   1010 		Grammar g = new Grammar(
   1011 			"grammar t;\n"+
   1012 				"scope Symbols {\n" +
   1013 				"  int n;\n" +
   1014 				"  List names;\n" +
   1015 				"}\n" +
   1016 				"a scope Symbols; : (id=ID ';' {"+action+"} )+\n" +
   1017 				"  ;\n" +
   1018 				"ID : 'a';\n");
   1019 		Tool antlr = newTool();
   1020 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1021 		g.setCodeGenerator(generator);
   1022 		generator.genRecognizer(); // forces load of templates
   1023 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1024 			new CommonToken(ANTLRParser.ACTION,action),1);
   1025 		String found = translator.translate();
   1026 		assertEquals(expecting, found);
   1027 
   1028 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1029 	}
   1030 
   1031 	@Test public void testAbsoluteIndexedGlobalScope() throws Exception {
   1032 		String action = "$Symbols[3]::names.add($id.text);";
   1033 		String expecting =
   1034 			"((Symbols_scope)Symbols_stack.elementAt(3)).names.add((id!=null?id.getText():null));";
   1035 
   1036 		ErrorQueue equeue = new ErrorQueue();
   1037 		ErrorManager.setErrorListener(equeue);
   1038 		Grammar g = new Grammar(
   1039 			"grammar t;\n"+
   1040 				"scope Symbols {\n" +
   1041 				"  int n;\n" +
   1042 				"  List names;\n" +
   1043 				"}\n" +
   1044 				"a scope Symbols; : (id=ID ';' {"+action+"} )+\n" +
   1045 				"  ;\n" +
   1046 				"ID : 'a';\n");
   1047 		Tool antlr = newTool();
   1048 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1049 		g.setCodeGenerator(generator);
   1050 		generator.genRecognizer(); // forces load of templates
   1051 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1052 			new CommonToken(ANTLRParser.ACTION,action),1);
   1053 		String found = translator.translate();
   1054 		assertEquals(expecting, found);
   1055 
   1056 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1057 	}
   1058 
   1059 	@Test public void testScopeAndAttributeWithUnderscore() throws Exception {
   1060 		String action = "$foo_bar::a_b;";
   1061 		String expecting = "((foo_bar_scope)foo_bar_stack.peek()).a_b;";
   1062 
   1063 		ErrorQueue equeue = new ErrorQueue();
   1064 		ErrorManager.setErrorListener(equeue);
   1065 		Grammar g = new Grammar(
   1066 			"grammar t;\n"+
   1067 				"scope foo_bar {\n" +
   1068 				"  int a_b;\n" +
   1069 				"}\n" +
   1070 				"a scope foo_bar; : (ID {"+action+"} )+\n" +
   1071 				"  ;\n" +
   1072 				"ID : 'a';\n");
   1073 		Tool antlr = newTool();
   1074 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1075 		g.setCodeGenerator(generator);
   1076 		generator.genRecognizer(); // forces load of templates
   1077 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1078 			new CommonToken(ANTLRParser.ACTION,action),1);
   1079 		String found = translator.translate();
   1080 		assertEquals(expecting, found);
   1081 
   1082 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1083 	}
   1084 
   1085 	@Test public void testSharedGlobalScope() throws Exception {
   1086 		String action = "$Symbols::x;";
   1087 		String expecting = "((Symbols_scope)Symbols_stack.peek()).x;";
   1088 
   1089 		ErrorQueue equeue = new ErrorQueue();
   1090 		ErrorManager.setErrorListener(equeue);
   1091 		Grammar g = new Grammar(
   1092 			"grammar t;\n"+
   1093 				"scope Symbols {\n" +
   1094 				"  String x;\n" +
   1095 				"}\n" +
   1096 				"a\n"+
   1097 				"scope { int y; }\n"+
   1098 				"scope Symbols;\n" +
   1099 				" : b {"+action+"}\n" +
   1100 				" ;\n" +
   1101 				"b : ID {$Symbols::x=$ID.text} ;\n" +
   1102 				"ID : 'a';\n");
   1103 		Tool antlr = newTool();
   1104 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1105 		g.setCodeGenerator(generator);
   1106 		generator.genRecognizer(); // forces load of templates
   1107 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1108 			new CommonToken(ANTLRParser.ACTION,action),1);
   1109 		String found = translator.translate();
   1110 		assertEquals(expecting, found);
   1111 
   1112 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1113 	}
   1114 
   1115 	@Test public void testGlobalScopeOutsideRule() throws Exception {
   1116 		String action = "public void foo() {$Symbols::names.add('foo');}";
   1117 		String expecting = "public void foo() {((Symbols_scope)Symbols_stack.peek()).names.add('foo');}";
   1118 
   1119 		ErrorQueue equeue = new ErrorQueue();
   1120 		ErrorManager.setErrorListener(equeue);
   1121 		Grammar g = new Grammar(
   1122 			"grammar t;\n"+
   1123 				"scope Symbols {\n" +
   1124 				"  int n;\n" +
   1125 				"  List names;\n" +
   1126 				"}\n" +
   1127 				"@members {'+action+'}\n" +
   1128 				"a : \n" +
   1129 				"  ;\n");
   1130 		Tool antlr = newTool();
   1131 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1132 		g.setCodeGenerator(generator);
   1133 		generator.genRecognizer(); // forces load of templates
   1134 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1135 			new CommonToken(ANTLRParser.ACTION,action),1);
   1136 		String found = translator.translate();
   1137 		assertEquals(expecting, found);
   1138 
   1139 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1140 	}
   1141 
   1142 	@Test public void testRuleScopeOutsideRule() throws Exception {
   1143 		String action = "public void foo() {$a::name;}";
   1144 		String expecting = "public void foo() {((a_scope)a_stack.peek()).name;}";
   1145 
   1146 		ErrorQueue equeue = new ErrorQueue();
   1147 		ErrorManager.setErrorListener(equeue);
   1148 		Grammar g = new Grammar(
   1149 			"grammar t;\n"+
   1150 				"@members {"+action+"}\n" +
   1151 				"a\n" +
   1152 				"scope { String name; }\n" +
   1153 				"  : {foo();}\n" +
   1154 				"  ;\n");
   1155 		Tool antlr = newTool();
   1156 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1157 		g.setCodeGenerator(generator);
   1158 		generator.genRecognizer(); // forces load of templates
   1159 		ActionTranslator translator = new ActionTranslator(generator,
   1160 			null,
   1161 			new CommonToken(ANTLRParser.ACTION,action),0);
   1162 		String found = translator.translate();		assertEquals(expecting, found);
   1163 
   1164 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1165 	}
   1166 
   1167 	@Test public void testBasicRuleScope() throws Exception {
   1168 		String action = "$a::n;";
   1169 		String expecting = "((a_scope)a_stack.peek()).n;";
   1170 
   1171 		ErrorQueue equeue = new ErrorQueue();
   1172 		ErrorManager.setErrorListener(equeue);
   1173 		Grammar g = new Grammar(
   1174 			"grammar t;\n"+
   1175 				"a\n" +
   1176 				"scope {\n" +
   1177 				"  int n;\n" +
   1178 				"} : {"+action+"}\n" +
   1179 				"  ;\n");
   1180 		Tool antlr = newTool();
   1181 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1182 		g.setCodeGenerator(generator);
   1183 		generator.genRecognizer(); // forces load of templates
   1184 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1185 			new CommonToken(ANTLRParser.ACTION,action),1);
   1186 		String found = translator.translate();
   1187 		assertEquals(expecting, found);
   1188 
   1189 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1190 	}
   1191 
   1192 	@Test public void testUnqualifiedRuleScopeAccessInsideRule() throws Exception {
   1193 		String action = "$n;";
   1194 		String expecting = action;
   1195 
   1196 		ErrorQueue equeue = new ErrorQueue();
   1197 		ErrorManager.setErrorListener(equeue);
   1198 		Grammar g = new Grammar(
   1199 			"grammar t;\n"+
   1200 				"a\n" +
   1201 				"scope {\n" +
   1202 				"  int n;\n" +
   1203 				"} : {"+action+"}\n" +
   1204 				"  ;\n");
   1205 		Tool antlr = newTool();
   1206 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1207 		g.setCodeGenerator(generator);
   1208 		generator.genRecognizer(); // forces load of templates
   1209 
   1210 		int expectedMsgID = ErrorManager.MSG_ISOLATED_RULE_ATTRIBUTE;
   1211 		Object expectedArg = "n";
   1212 		Object expectedArg2 = null;
   1213 		GrammarSemanticsMessage expectedMessage =
   1214 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg,
   1215 				expectedArg2);
   1216 		checkError(equeue, expectedMessage);
   1217 	}
   1218 
   1219 	@Test public void testIsolatedDynamicRuleScopeRef() throws Exception {
   1220 		String action = "$a;"; // refers to stack not top of stack
   1221 		String expecting = "a_stack;";
   1222 
   1223 		ErrorQueue equeue = new ErrorQueue();
   1224 		ErrorManager.setErrorListener(equeue);
   1225 		Grammar g = new Grammar(
   1226 			"grammar t;\n"+
   1227 				"a\n" +
   1228 				"scope {\n" +
   1229 				"  int n;\n" +
   1230 				"} : b ;\n" +
   1231 				"b : {"+action+"}\n" +
   1232 				"  ;\n");
   1233 		Tool antlr = newTool();
   1234 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1235 		g.setCodeGenerator(generator);
   1236 		generator.genRecognizer(); // forces load of templates
   1237 		ActionTranslator translator = new ActionTranslator(generator, "b",
   1238 			new CommonToken(ANTLRParser.ACTION,action),1);
   1239 		String found = translator.translate();
   1240 		assertEquals(expecting, found);
   1241 
   1242 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1243 	}
   1244 
   1245 	@Test public void testDynamicRuleScopeRefInSubrule() throws Exception {
   1246 		String action = "$a::n;";
   1247 		String expecting = "((a_scope)a_stack.peek()).n;";
   1248 
   1249 		ErrorQueue equeue = new ErrorQueue();
   1250 		ErrorManager.setErrorListener(equeue);
   1251 		Grammar g = new Grammar(
   1252 			"grammar t;\n"+
   1253 				"a\n" +
   1254 				"scope {\n" +
   1255 				"  float n;\n" +
   1256 				"} : b ;\n" +
   1257 				"b : {"+action+"}\n" +
   1258 				"  ;\n");
   1259 		Tool antlr = newTool();
   1260 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1261 		g.setCodeGenerator(generator);
   1262 		generator.genRecognizer(); // forces load of templates
   1263 		ActionTranslator translator = new ActionTranslator(generator, "b",
   1264 			new CommonToken(ANTLRParser.ACTION,action),1);
   1265 		String found = translator.translate();
   1266 		assertEquals(expecting, found);
   1267 
   1268 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1269 	}
   1270 
   1271 	@Test public void testIsolatedGlobalScopeRef() throws Exception {
   1272 		String action = "$Symbols;";
   1273 		String expecting = "Symbols_stack;";
   1274 
   1275 		ErrorQueue equeue = new ErrorQueue();
   1276 		ErrorManager.setErrorListener(equeue);
   1277 		Grammar g = new Grammar(
   1278 			"grammar t;\n"+
   1279 				"scope Symbols {\n" +
   1280 				"  String x;\n" +
   1281 				"}\n" +
   1282 				"a\n"+
   1283 				"scope { int y; }\n"+
   1284 				"scope Symbols;\n" +
   1285 				" : b {"+action+"}\n" +
   1286 				" ;\n" +
   1287 				"b : ID {$Symbols::x=$ID.text} ;\n" +
   1288 				"ID : 'a';\n");
   1289 		Tool antlr = newTool();
   1290 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1291 		g.setCodeGenerator(generator);
   1292 		generator.genRecognizer(); // forces load of templates
   1293 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1294 			new CommonToken(ANTLRParser.ACTION,action),1);
   1295 		String found = translator.translate();
   1296 		assertEquals(expecting, found);
   1297 
   1298 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1299 	}
   1300 
   1301 	@Test public void testRuleScopeFromAnotherRule() throws Exception {
   1302 		String action = "$a::n;"; // must be qualified
   1303 		String expecting = "((a_scope)a_stack.peek()).n;";
   1304 
   1305 		ErrorQueue equeue = new ErrorQueue();
   1306 		ErrorManager.setErrorListener(equeue);
   1307 		Grammar g = new Grammar(
   1308 			"grammar t;\n"+
   1309 				"a\n" +
   1310 				"scope {\n" +
   1311 				"  boolean n;\n" +
   1312 				"} : b\n" +
   1313 				"  ;\n" +
   1314 				"b : {"+action+"}\n" +
   1315 				"  ;\n");
   1316 		Tool antlr = newTool();
   1317 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1318 		g.setCodeGenerator(generator);
   1319 		generator.genRecognizer(); // forces load of templates
   1320 		ActionTranslator translator = new ActionTranslator(generator, "b",
   1321 			new CommonToken(ANTLRParser.ACTION,action),1);
   1322 		String found = translator.translate();
   1323 		assertEquals(expecting, found);
   1324 
   1325 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1326 	}
   1327 
   1328 	@Test public void testFullyQualifiedRefToCurrentRuleParameter() throws Exception {
   1329 		String action = "$a.i;";
   1330 		String expecting = "i;";
   1331 
   1332 		ErrorQueue equeue = new ErrorQueue();
   1333 		ErrorManager.setErrorListener(equeue);
   1334 		Grammar g = new Grammar(
   1335 			"grammar t;\n"+
   1336 				"a[int i]: {"+action+"}\n" +
   1337 				"  ;\n");
   1338 		Tool antlr = newTool();
   1339 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1340 		g.setCodeGenerator(generator);
   1341 		generator.genRecognizer(); // forces load of templates
   1342 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1343 			new CommonToken(ANTLRParser.ACTION,action),1);
   1344 		String found = translator.translate();		assertEquals(expecting, found);
   1345 
   1346 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1347 	}
   1348 
   1349 	@Test public void testFullyQualifiedRefToCurrentRuleRetVal() throws Exception {
   1350 		String action = "$a.i;";
   1351 		String expecting = "retval.i;";
   1352 
   1353 		ErrorQueue equeue = new ErrorQueue();
   1354 		ErrorManager.setErrorListener(equeue);
   1355 		Grammar g = new Grammar(
   1356 			"grammar t;\n"+
   1357 				"a returns [int i, int j]: {"+action+"}\n" +
   1358 				"  ;\n");
   1359 		Tool antlr = newTool();
   1360 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1361 		g.setCodeGenerator(generator);
   1362 		generator.genRecognizer(); // forces load of templates
   1363 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1364 			new CommonToken(ANTLRParser.ACTION,action),1);
   1365 		String found = translator.translate();
   1366 		assertEquals(expecting, found);
   1367 
   1368 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1369 	}
   1370 
   1371 	@Test public void testSetFullyQualifiedRefToCurrentRuleRetVal() throws Exception {
   1372 		String action = "$a.i = 1;";
   1373 		String expecting = "retval.i = 1;";
   1374 
   1375 		ErrorQueue equeue = new ErrorQueue();
   1376 		ErrorManager.setErrorListener(equeue);
   1377 		Grammar g = new Grammar(
   1378 			"grammar t;\n"+
   1379 				"a returns [int i, int j]: {"+action+"}\n" +
   1380 				"  ;\n");
   1381 		Tool antlr = newTool();
   1382 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1383 		g.setCodeGenerator(generator);
   1384 		generator.genRecognizer(); // forces load of templates
   1385 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1386 			new CommonToken(ANTLRParser.ACTION,action),1);
   1387 		String found = translator.translate();
   1388 		assertEquals(expecting, found);
   1389 
   1390 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1391 	}
   1392 
   1393 	@Test public void testIsolatedRefToCurrentRule() throws Exception {
   1394 		String action = "$a;";
   1395 		String expecting = "";
   1396 
   1397 		ErrorQueue equeue = new ErrorQueue();
   1398 		ErrorManager.setErrorListener(equeue);
   1399 		Grammar g = new Grammar(
   1400 			"grammar t;\n"+
   1401 				"a : 'a' {"+action+"}\n" +
   1402 				"  ;\n");
   1403 		Tool antlr = newTool();
   1404 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1405 		g.setCodeGenerator(generator);
   1406 		generator.genRecognizer(); // forces load of templates
   1407 
   1408 		int expectedMsgID = ErrorManager.MSG_ISOLATED_RULE_SCOPE;
   1409 		Object expectedArg = "a";
   1410 		Object expectedArg2 = null;
   1411 		GrammarSemanticsMessage expectedMessage =
   1412 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg,
   1413 				expectedArg2);
   1414 		checkError(equeue, expectedMessage);
   1415 	}
   1416 
   1417 	@Test public void testIsolatedRefToRule() throws Exception {
   1418 		String action = "$x;";
   1419 
   1420 		ErrorQueue equeue = new ErrorQueue();
   1421 		ErrorManager.setErrorListener(equeue);
   1422 		Grammar g = new Grammar(
   1423 			"grammar t;\n"+
   1424 				"a : x=b {"+action+"}\n" +
   1425 				"  ;\n" +
   1426 				"b : 'b' ;\n");
   1427 		Tool antlr = newTool();
   1428 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1429 		g.setCodeGenerator(generator);
   1430 		generator.genRecognizer(); // forces load of templates
   1431 
   1432 		int expectedMsgID = ErrorManager.MSG_ISOLATED_RULE_SCOPE;
   1433 		Object expectedArg = "x";
   1434 		GrammarSemanticsMessage expectedMessage =
   1435 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
   1436 		checkError(equeue, expectedMessage);
   1437 	}
   1438 
   1439 	/*  I think these have to be errors $a.x makes no sense.
   1440 	@Test public void testFullyQualifiedRefToLabelInCurrentRule() throws Exception {
   1441 			String action = "$a.x;";
   1442 			String expecting = "x;";
   1443 
   1444 			ErrorQueue equeue = new ErrorQueue();
   1445 			ErrorManager.setErrorListener(equeue);
   1446 			Grammar g = new Grammar(
   1447 				"grammar t;\n"+
   1448 					"a : x='a' {"+action+"}\n" +
   1449 					"  ;\n");
   1450 			Tool antlr = newTool();
   1451 			CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1452 			g.setCodeGenerator(generator);
   1453 			generator.genRecognizer(); // forces load of templates
   1454 			ActionTranslator translator = new ActionTranslator(generator,"a",
   1455 															   new CommonToken(ANTLRParser.ACTION,action),1);
   1456 			String rawTranslation =
   1457 				translator.translate();
   1458 			STGroup templates =
   1459 				new STGroup();
   1460 			ST actionST = new ST(templates, rawTranslation);
   1461 			String found = actionST.render();
   1462 			assertEquals(expecting, found);
   1463 
   1464 			assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1465 		}
   1466 
   1467 	@Test public void testFullyQualifiedRefToListLabelInCurrentRule() throws Exception {
   1468 		String action = "$a.x;"; // must be qualified
   1469 		String expecting = "list_x;";
   1470 
   1471 		ErrorQueue equeue = new ErrorQueue();
   1472 		ErrorManager.setErrorListener(equeue);
   1473 		Grammar g = new Grammar(
   1474 			"grammar t;\n"+
   1475 				"a : x+='a' {"+action+"}\n" +
   1476 				"  ;\n");
   1477 		Tool antlr = newTool();
   1478 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1479 		g.setCodeGenerator(generator);
   1480 		generator.genRecognizer(); // forces load of templates
   1481 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1482 														   new CommonToken(ANTLRParser.ACTION,action),1);
   1483 		String found = translator.translate();		assertEquals(expecting, found);
   1484 
   1485 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1486 	}
   1487 */
   1488 	@Test public void testFullyQualifiedRefToTemplateAttributeInCurrentRule() throws Exception {
   1489 		String action = "$a.st;"; // can be qualified
   1490 		String expecting = "retval.st;";
   1491 
   1492 		ErrorQueue equeue = new ErrorQueue();
   1493 		ErrorManager.setErrorListener(equeue);
   1494 		Grammar g = new Grammar(
   1495 			"parser grammar t;\n" +
   1496 				"options {output=template;}\n"+
   1497 				"a : (A->{$A.text}) {"+action+"}\n" +
   1498 				"  ;\n");
   1499 		Tool antlr = newTool();
   1500 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1501 		g.setCodeGenerator(generator);
   1502 		generator.genRecognizer(); // forces load of templates
   1503 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1504 			new CommonToken(ANTLRParser.ACTION,action),1);
   1505 		String found = translator.translate();
   1506 		assertEquals(expecting, found);
   1507 
   1508 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1509 	}
   1510 
   1511 	@Test public void testRuleRefWhenRuleHasScope() throws Exception {
   1512 		String action = "$b.start;";
   1513 		String expecting = "(b1!=null?((Token)b1.start):null);";
   1514 
   1515 		ErrorQueue equeue = new ErrorQueue();
   1516 		ErrorManager.setErrorListener(equeue);
   1517 		Grammar g = new Grammar(
   1518 			"grammar t;\n" +
   1519 				"a : b {###"+action+"!!!} ;\n" +
   1520 				"b\n" +
   1521 				"scope {\n" +
   1522 				"  int n;\n" +
   1523 				"} : 'b' \n" +
   1524 				"  ;\n");
   1525 		Tool antlr = newTool();
   1526 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1527 		g.setCodeGenerator(generator);
   1528 		generator.genRecognizer(); // forces load of templates
   1529 
   1530 		ST codeST = generator.getRecognizerST();
   1531 		String code = codeST.render();
   1532 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   1533 		assertEquals(expecting, found);
   1534 
   1535 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1536 	}
   1537 
   1538 	@Test public void testDynamicScopeRefOkEvenThoughRuleRefExists() throws Exception {
   1539 		String action = "$b::n;";
   1540 		String expecting = "((b_scope)b_stack.peek()).n;";
   1541 
   1542 		ErrorQueue equeue = new ErrorQueue();
   1543 		ErrorManager.setErrorListener(equeue);
   1544 		Grammar g = new Grammar(
   1545 			"grammar t;\n" +
   1546 				"s : b ;\n"+
   1547 				"b\n" +
   1548 				"scope {\n" +
   1549 				"  int n;\n" +
   1550 				"} : '(' b ')' {"+action+"}\n" + // refers to current invocation's n
   1551 				"  ;\n");
   1552 		Tool antlr = newTool();
   1553 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1554 		g.setCodeGenerator(generator);
   1555 		generator.genRecognizer(); // forces load of templates
   1556 		ActionTranslator translator = new ActionTranslator(generator, "b",
   1557 			new CommonToken(ANTLRParser.ACTION,action),1);
   1558 		String found = translator.translate();		assertEquals(expecting, found);
   1559 
   1560 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1561 	}
   1562 
   1563 	@Test public void testRefToTemplateAttributeForCurrentRule() throws Exception {
   1564 		String action = "$st=null;";
   1565 		String expecting = "retval.st =null;";
   1566 
   1567 		ErrorQueue equeue = new ErrorQueue();
   1568 		ErrorManager.setErrorListener(equeue);
   1569 		Grammar g = new Grammar(
   1570 			"parser grammar t;\n" +
   1571 				"options {output=template;}\n"+
   1572 				"a : {"+action+"}\n" +
   1573 				"  ;\n");
   1574 		Tool antlr = newTool();
   1575 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1576 		g.setCodeGenerator(generator);
   1577 		generator.genRecognizer(); // forces load of templates
   1578 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1579 			new CommonToken(ANTLRParser.ACTION,action),1);
   1580 		String found = translator.translate();		assertEquals(expecting, found);
   1581 
   1582 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1583 	}
   1584 
   1585 	@Test public void testRefToTextAttributeForCurrentRule() throws Exception {
   1586 		String action = "$text";
   1587 		String expecting = "input.toString(retval.start,input.LT(-1))";
   1588 
   1589 		ErrorQueue equeue = new ErrorQueue();
   1590 		ErrorManager.setErrorListener(equeue);
   1591 		Grammar g = new Grammar(
   1592 			"parser grammar t;\n" +
   1593 				"options {output=template;}\n"+
   1594 				"a : {###"+action+"!!!}\n" +
   1595 				"  ;\n");
   1596 		Tool antlr = newTool();
   1597 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1598 		g.setCodeGenerator(generator);
   1599 		generator.genRecognizer(); // codegen phase sets some vars we need
   1600 		ST codeST = generator.getRecognizerST();
   1601 		String code = codeST.render();
   1602 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   1603 		assertEquals(expecting, found);
   1604 
   1605 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1606 	}
   1607 
   1608 	@Test public void testRefToStartAttributeForCurrentRule() throws Exception {
   1609 		String action = "$start;";
   1610 		String expecting = "((Token)retval.start);";
   1611 
   1612 		ErrorQueue equeue = new ErrorQueue();
   1613 		ErrorManager.setErrorListener(equeue);
   1614 		Grammar g = new Grammar(
   1615 			"parser grammar t;\n" +
   1616 				"a : {###"+action+"!!!}\n" +
   1617 				"  ;\n");
   1618 		Tool antlr = newTool();
   1619 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1620 		g.setCodeGenerator(generator);
   1621 		generator.genRecognizer(); // forces load of templates
   1622 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1623 			new CommonToken(ANTLRParser.ACTION,action),1);
   1624 		ST codeST = generator.getRecognizerST();
   1625 		String code = codeST.render();
   1626 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   1627 		assertEquals(expecting, found);
   1628 
   1629 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1630 	}
   1631 
   1632 	@Test public void testTokenLabelFromMultipleAlts() throws Exception {
   1633 		String action = "$ID.text;"; // must be qualified
   1634 		String action2 = "$INT.text;"; // must be qualified
   1635 		String expecting = "(ID1!=null?ID1.getText():null);";
   1636 		String expecting2 = "(INT2!=null?INT2.getText():null);";
   1637 
   1638 		ErrorQueue equeue = new ErrorQueue();
   1639 		ErrorManager.setErrorListener(equeue);
   1640 		Grammar g = new Grammar(
   1641 			"grammar t;\n"+
   1642 				"a : ID {"+action+"}\n" +
   1643 				"  | INT {"+action2+"}\n" +
   1644 				"  ;\n" +
   1645 				"ID : 'a';\n" +
   1646 				"INT : '0';\n");
   1647 		Tool antlr = newTool();
   1648 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1649 		g.setCodeGenerator(generator);
   1650 		generator.genRecognizer(); // forces load of templates
   1651 		ActionTranslator translator = new ActionTranslator(generator,"a",
   1652 			new CommonToken(ANTLRParser.ACTION,action),1);
   1653 		String found = translator.translate();		assertEquals(expecting, found);
   1654 
   1655 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1656 		translator = new ActionTranslator(generator,
   1657 			"a",
   1658 			new CommonToken(ANTLRParser.ACTION,action2),2);
   1659 		found = translator.translate();
   1660 		assertEquals(expecting2, found);
   1661 
   1662 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1663 	}
   1664 
   1665 	@Test public void testRuleLabelFromMultipleAlts() throws Exception {
   1666 		String action = "$b.text;"; // must be qualified
   1667 		String action2 = "$c.text;"; // must be qualified
   1668 		String expecting = "(b1!=null?input.toString(b1.start,b1.stop):null);";
   1669 		String expecting2 = "(c2!=null?input.toString(c2.start,c2.stop):null);";
   1670 
   1671 		ErrorQueue equeue = new ErrorQueue();
   1672 		ErrorManager.setErrorListener(equeue);
   1673 		Grammar g = new Grammar(
   1674 			"grammar t;\n"+
   1675 				"a : b {###"+action+"!!!}\n" +
   1676 				"  | c {^^^"+action2+"&&&}\n" +
   1677 				"  ;\n" +
   1678 				"b : 'a';\n" +
   1679 				"c : '0';\n");
   1680 		Tool antlr = newTool();
   1681 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1682 		g.setCodeGenerator(generator);
   1683 		generator.genRecognizer(); // codegen phase sets some vars we need
   1684 		ST codeST = generator.getRecognizerST();
   1685 		String code = codeST.render();
   1686 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   1687 		assertEquals(expecting, found);
   1688 		found = code.substring(code.indexOf("^^^")+3,code.indexOf("&&&"));
   1689 		assertEquals(expecting2, found);
   1690 
   1691 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1692 	}
   1693 
   1694 	@Test public void testUnknownDynamicAttribute() throws Exception {
   1695 		String action = "$a::x";
   1696 		String expecting = action;
   1697 
   1698 		ErrorQueue equeue = new ErrorQueue();
   1699 		ErrorManager.setErrorListener(equeue);
   1700 		Grammar g = new Grammar(
   1701 			"grammar t;\n"+
   1702 				"a\n" +
   1703 				"scope {\n" +
   1704 				"  int n;\n" +
   1705 				"} : {"+action+"}\n" +
   1706 				"  ;\n");
   1707 		Tool antlr = newTool();
   1708 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1709 		g.setCodeGenerator(generator);
   1710 		generator.genRecognizer(); // forces load of templates
   1711 		ActionTranslator translator =
   1712 			new ActionTranslator(generator,
   1713 				"a",
   1714 				new CommonToken(ANTLRParser.ACTION,action),1);
   1715 		String found = translator.translate();		assertEquals(expecting, found);
   1716 
   1717 		int expectedMsgID = ErrorManager.MSG_UNKNOWN_DYNAMIC_SCOPE_ATTRIBUTE;
   1718 		Object expectedArg = "a";
   1719 		Object expectedArg2 = "x";
   1720 		GrammarSemanticsMessage expectedMessage =
   1721 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   1722 		checkError(equeue, expectedMessage);
   1723 	}
   1724 
   1725 	@Test public void testUnknownGlobalDynamicAttribute() throws Exception {
   1726 		String action = "$Symbols::x";
   1727 		String expecting = action;
   1728 
   1729 		ErrorQueue equeue = new ErrorQueue();
   1730 		ErrorManager.setErrorListener(equeue);
   1731 		Grammar g = new Grammar(
   1732 			"grammar t;\n"+
   1733 				"scope Symbols {\n" +
   1734 				"  int n;\n" +
   1735 				"}\n" +
   1736 				"a : {'+action+'}\n" +
   1737 				"  ;\n");
   1738 		Tool antlr = newTool();
   1739 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1740 		g.setCodeGenerator(generator);
   1741 		generator.genRecognizer(); // forces load of templates
   1742 		ActionTranslator translator =
   1743 			new ActionTranslator(generator,
   1744 				"a",
   1745 				new CommonToken(ANTLRParser.ACTION,action),1);
   1746 		String found = translator.translate();		assertEquals(expecting, found);
   1747 
   1748 		int expectedMsgID = ErrorManager.MSG_UNKNOWN_DYNAMIC_SCOPE_ATTRIBUTE;
   1749 		Object expectedArg = "Symbols";
   1750 		Object expectedArg2 = "x";
   1751 		GrammarSemanticsMessage expectedMessage =
   1752 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   1753 		checkError(equeue, expectedMessage);
   1754 	}
   1755 
   1756 	@Test public void testUnqualifiedRuleScopeAttribute() throws Exception {
   1757 		String action = "$n;"; // must be qualified
   1758 		String expecting = "$n;";
   1759 
   1760 		ErrorQueue equeue = new ErrorQueue();
   1761 		ErrorManager.setErrorListener(equeue);
   1762 		Grammar g = new Grammar(
   1763 			"grammar t;\n"+
   1764 				"a\n" +
   1765 				"scope {\n" +
   1766 				"  int n;\n" +
   1767 				"} : b\n" +
   1768 				"  ;\n" +
   1769 				"b : {'+action+'}\n" +
   1770 				"  ;\n");
   1771 		Tool antlr = newTool();
   1772 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1773 		ActionTranslator translator =
   1774 			new ActionTranslator(generator,
   1775 				"b",
   1776 				new CommonToken(ANTLRParser.ACTION,action),1);
   1777 		String found = translator.translate();		assertEquals(expecting, found);
   1778 
   1779 		int expectedMsgID = ErrorManager.MSG_UNKNOWN_SIMPLE_ATTRIBUTE;
   1780 		Object expectedArg = "n";
   1781 		Object expectedArg2 = null;
   1782 		GrammarSemanticsMessage expectedMessage =
   1783 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   1784 		checkError(equeue, expectedMessage);
   1785 	}
   1786 
   1787 	@Test public void testRuleAndTokenLabelTypeMismatch() throws Exception {
   1788 		ErrorQueue equeue = new ErrorQueue();
   1789 		ErrorManager.setErrorListener(equeue);
   1790 		Grammar g = new Grammar(
   1791 			"grammar t;\n"+
   1792 				"a : id='foo' id=b\n" +
   1793 				"  ;\n" +
   1794 				"b : ;\n");
   1795 		int expectedMsgID = ErrorManager.MSG_LABEL_TYPE_CONFLICT;
   1796 		Object expectedArg = "id";
   1797 		Object expectedArg2 = "rule!=token";
   1798 		GrammarSemanticsMessage expectedMessage =
   1799 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   1800 		checkError(equeue, expectedMessage);
   1801 	}
   1802 
   1803 	@Test public void testListAndTokenLabelTypeMismatch() throws Exception {
   1804 		ErrorQueue equeue = new ErrorQueue();
   1805 		ErrorManager.setErrorListener(equeue);
   1806 		Grammar g = new Grammar(
   1807 			"grammar t;\n"+
   1808 				"a : ids+='a' ids='b'\n" +
   1809 				"  ;\n" +
   1810 				"b : ;\n");
   1811 		int expectedMsgID = ErrorManager.MSG_LABEL_TYPE_CONFLICT;
   1812 		Object expectedArg = "ids";
   1813 		Object expectedArg2 = "token!=token-list";
   1814 		GrammarSemanticsMessage expectedMessage =
   1815 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   1816 		checkError(equeue, expectedMessage);
   1817 	}
   1818 
   1819 	@Test public void testListAndRuleLabelTypeMismatch() throws Exception {
   1820 		ErrorQueue equeue = new ErrorQueue();
   1821 		ErrorManager.setErrorListener(equeue);
   1822 		Grammar g = new Grammar(
   1823 			"grammar t;\n" +
   1824 				"options {output=AST;}\n"+
   1825 				"a : bs+=b bs=b\n" +
   1826 				"  ;\n" +
   1827 				"b : 'b';\n");
   1828 		int expectedMsgID = ErrorManager.MSG_LABEL_TYPE_CONFLICT;
   1829 		Object expectedArg = "bs";
   1830 		Object expectedArg2 = "rule!=rule-list";
   1831 		GrammarSemanticsMessage expectedMessage =
   1832 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   1833 		checkError(equeue, expectedMessage);
   1834 	}
   1835 
   1836 	@Test public void testArgReturnValueMismatch() throws Exception {
   1837 		ErrorQueue equeue = new ErrorQueue();
   1838 		ErrorManager.setErrorListener(equeue);
   1839 		Grammar g = new Grammar(
   1840 			"grammar t;\n"+
   1841 				"a[int i] returns [int x, int i]\n" +
   1842 				"  : \n" +
   1843 				"  ;\n" +
   1844 				"b : ;\n");
   1845 		int expectedMsgID = ErrorManager.MSG_ARG_RETVAL_CONFLICT;
   1846 		Object expectedArg = "i";
   1847 		Object expectedArg2 = "a";
   1848 		GrammarSemanticsMessage expectedMessage =
   1849 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   1850 		checkError(equeue, expectedMessage);
   1851 	}
   1852 
   1853 	@Test public void testSimplePlusEqualLabel() throws Exception {
   1854 		String action = "$ids.size();"; // must be qualified
   1855 		String expecting = "list_ids.size();";
   1856 
   1857 		ErrorQueue equeue = new ErrorQueue();
   1858 		ErrorManager.setErrorListener(equeue);
   1859 		Grammar g = new Grammar(
   1860 			"parser grammar t;\n"+
   1861 				"a : ids+=ID ( COMMA ids+=ID {"+action+"})* ;\n");
   1862 		Tool antlr = newTool();
   1863 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1864 		g.setCodeGenerator(generator);
   1865 		generator.genRecognizer(); // forces load of templates
   1866 		ActionTranslator translator =
   1867 			new ActionTranslator(generator,
   1868 				"a",
   1869 				new CommonToken(ANTLRParser.ACTION,action),1);
   1870 		String found = translator.translate();
   1871 		assertEquals(expecting, found);
   1872 
   1873 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1874 	}
   1875 
   1876 	@Test public void testPlusEqualStringLabel() throws Exception {
   1877 		String action = "$ids.size();"; // must be qualified
   1878 		String expecting = "list_ids.size();";
   1879 
   1880 		ErrorQueue equeue = new ErrorQueue();
   1881 		ErrorManager.setErrorListener(equeue);
   1882 		Grammar g = new Grammar(
   1883 			"grammar t;\n"+
   1884 				"a : ids+='if' ( ',' ids+=ID {"+action+"})* ;" +
   1885 				"ID : 'a';\n");
   1886 		Tool antlr = newTool();
   1887 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1888 		g.setCodeGenerator(generator);
   1889 		generator.genRecognizer(); // forces load of templates
   1890 		ActionTranslator translator =
   1891 			new ActionTranslator(generator,
   1892 				"a",
   1893 				new CommonToken(ANTLRParser.ACTION,action),1);
   1894 		String found = translator.translate();
   1895 		assertEquals(expecting, found);
   1896 
   1897 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1898 	}
   1899 
   1900 	@Test public void testPlusEqualSetLabel() throws Exception {
   1901 		String action = "$ids.size();"; // must be qualified
   1902 		String expecting = "list_ids.size();";
   1903 
   1904 		ErrorQueue equeue = new ErrorQueue();
   1905 		ErrorManager.setErrorListener(equeue);
   1906 		Grammar g = new Grammar(
   1907 			"grammar t;\n"+
   1908 				"a : ids+=('a'|'b') ( ',' ids+=ID {"+action+"})* ;" +
   1909 				"ID : 'a';\n");
   1910 		Tool antlr = newTool();
   1911 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1912 		g.setCodeGenerator(generator);
   1913 		generator.genRecognizer(); // forces load of templates
   1914 		ActionTranslator translator =
   1915 			new ActionTranslator(generator,
   1916 				"a",
   1917 				new CommonToken(ANTLRParser.ACTION,action),1);
   1918 		String found = translator.translate();
   1919 		assertEquals(expecting, found);
   1920 
   1921 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1922 	}
   1923 
   1924 	@Test public void testPlusEqualWildcardLabel() throws Exception {
   1925 		String action = "$ids.size();"; // must be qualified
   1926 		String expecting = "list_ids.size();";
   1927 
   1928 		ErrorQueue equeue = new ErrorQueue();
   1929 		ErrorManager.setErrorListener(equeue);
   1930 		Grammar g = new Grammar(
   1931 			"grammar t;\n"+
   1932 				"a : ids+=. ( ',' ids+=ID {"+action+"})* ;" +
   1933 				"ID : 'a';\n");
   1934 		Tool antlr = newTool();
   1935 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1936 		ActionTranslator translator =
   1937 			new ActionTranslator(generator,
   1938 				"a",
   1939 				new CommonToken(ANTLRParser.ACTION,action),1);
   1940 		g.setCodeGenerator(generator);
   1941 		generator.genRecognizer(); // forces load of templates
   1942 		String found = translator.translate();
   1943 		assertEquals(expecting, found);
   1944 
   1945 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1946 	}
   1947 
   1948 	@Test public void testImplicitTokenLabel() throws Exception {
   1949 		String action = "$ID; $ID.text; $ID.getText()";
   1950 		String expecting = "ID1; (ID1!=null?ID1.getText():null); ID1.getText()";
   1951 
   1952 		ErrorQueue equeue = new ErrorQueue();
   1953 		ErrorManager.setErrorListener(equeue);
   1954 		Grammar g = new Grammar(
   1955 			"grammar t;\n"+
   1956 				"a : ID {"+action+"} ;" +
   1957 				"ID : 'a';\n");
   1958 		Tool antlr = newTool();
   1959 		antlr.setOutputDirectory(null); // write to /dev/null
   1960 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1961 
   1962 		ActionTranslator translator =
   1963 			new ActionTranslator(generator,
   1964 				"a",
   1965 				new CommonToken(ANTLRParser.ACTION,action),1);
   1966 		g.setCodeGenerator(generator);
   1967 		generator.genRecognizer(); // forces load of templates
   1968 		String found = translator.translate();
   1969 		assertEquals(expecting, found);
   1970 
   1971 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1972 	}
   1973 
   1974 	@Test public void testImplicitRuleLabel() throws Exception {
   1975 		String action = "$r.start;";
   1976 		String expecting = "(r1!=null?((Token)r1.start):null);";
   1977 
   1978 		ErrorQueue equeue = new ErrorQueue();
   1979 		ErrorManager.setErrorListener(equeue);
   1980 		Grammar g = new Grammar(
   1981 			"grammar t;\n"+
   1982 				"a : r {###"+action+"!!!} ;" +
   1983 				"r : 'a';\n");
   1984 		Tool antlr = newTool();
   1985 		antlr.setOutputDirectory(null); // write to /dev/null
   1986 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   1987 		g.setCodeGenerator(generator);
   1988 		generator.genRecognizer();
   1989 
   1990 		ST codeST = generator.getRecognizerST();
   1991 		String code = codeST.render();
   1992 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   1993 		assertEquals(expecting, found);
   1994 
   1995 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   1996 	}
   1997 
   1998 	@Test public void testReuseExistingLabelWithImplicitRuleLabel() throws Exception {
   1999 		String action = "$r.start;";
   2000 		String expecting = "(x!=null?((Token)x.start):null);";
   2001 
   2002 		ErrorQueue equeue = new ErrorQueue();
   2003 		ErrorManager.setErrorListener(equeue);
   2004 		Grammar g = new Grammar(
   2005 			"grammar t;\n"+
   2006 				"a : x=r {###"+action+"!!!} ;" +
   2007 				"r : 'a';\n");
   2008 		Tool antlr = newTool();
   2009 		antlr.setOutputDirectory(null); // write to /dev/null
   2010 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2011 		g.setCodeGenerator(generator);
   2012 		generator.genRecognizer();
   2013 
   2014 		ST codeST = generator.getRecognizerST();
   2015 		String code = codeST.render();
   2016 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   2017 		assertEquals(expecting, found);
   2018 
   2019 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2020 	}
   2021 
   2022 	@Test public void testReuseExistingListLabelWithImplicitRuleLabel() throws Exception {
   2023 		String action = "$r.start;";
   2024 		String expecting = "(x!=null?((Token)x.start):null);";
   2025 
   2026 		ErrorQueue equeue = new ErrorQueue();
   2027 		ErrorManager.setErrorListener(equeue);
   2028 		Grammar g = new Grammar(
   2029 			"grammar t;\n"+
   2030 				"options {output=AST;}\n" +
   2031 				"a : x+=r {###"+action+"!!!} ;" +
   2032 				"r : 'a';\n");
   2033 		Tool antlr = newTool();
   2034 		antlr.setOutputDirectory(null); // write to /dev/null
   2035 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2036 		g.setCodeGenerator(generator);
   2037 		generator.genRecognizer();
   2038 
   2039 		ST codeST = generator.getRecognizerST();
   2040 		String code = codeST.render();
   2041 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   2042 		assertEquals(expecting, found);
   2043 
   2044 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2045 	}
   2046 
   2047 	@Test public void testReuseExistingLabelWithImplicitTokenLabel() throws Exception {
   2048 		String action = "$ID.text;";
   2049 		String expecting = "(x!=null?x.getText():null);";
   2050 
   2051 		ErrorQueue equeue = new ErrorQueue();
   2052 		ErrorManager.setErrorListener(equeue);
   2053 		Grammar g = new Grammar(
   2054 			"grammar t;\n"+
   2055 				"a : x=ID {"+action+"} ;" +
   2056 				"ID : 'a';\n");
   2057 		Tool antlr = newTool();
   2058 		antlr.setOutputDirectory(null); // write to /dev/null
   2059 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2060 		g.setCodeGenerator(generator);
   2061 		generator.genRecognizer();
   2062 
   2063 		ActionTranslator translator = new ActionTranslator(generator,"a",
   2064 			new CommonToken(ANTLRParser.ACTION,action),1);
   2065 		String found = translator.translate();
   2066 		assertEquals(expecting, found);
   2067 
   2068 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2069 	}
   2070 
   2071 	@Test public void testReuseExistingListLabelWithImplicitTokenLabel() throws Exception {
   2072 		String action = "$ID.text;";
   2073 		String expecting = "(x!=null?x.getText():null);";
   2074 
   2075 		ErrorQueue equeue = new ErrorQueue();
   2076 		ErrorManager.setErrorListener(equeue);
   2077 		Grammar g = new Grammar(
   2078 			"grammar t;\n"+
   2079 				"a : x+=ID {"+action+"} ;" +
   2080 				"ID : 'a';\n");
   2081 		Tool antlr = newTool();
   2082 		antlr.setOutputDirectory(null); // write to /dev/null
   2083 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2084 		g.setCodeGenerator(generator);
   2085 		generator.genRecognizer();
   2086 
   2087 		ActionTranslator translator = new ActionTranslator(generator,"a",
   2088 			new CommonToken(ANTLRParser.ACTION,action),1);
   2089 		String found = translator.translate();
   2090 		assertEquals(expecting, found);
   2091 
   2092 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2093 	}
   2094 
   2095 	@Test public void testRuleLabelWithoutOutputOption() throws Exception {
   2096 		ErrorQueue equeue = new ErrorQueue();
   2097 		ErrorManager.setErrorListener(equeue);
   2098 		Grammar g = new Grammar(
   2099 			"grammar T;\n"+
   2100 				"s : x+=a ;" +
   2101 				"a : 'a';\n"+
   2102 				"b : 'b';\n"+
   2103 				"WS : ' '|'\n';\n");
   2104 		Tool antlr = newTool();
   2105 		antlr.setOutputDirectory(null); // write to /dev/null
   2106 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2107 		g.setCodeGenerator(generator);
   2108 		generator.genRecognizer();
   2109 
   2110 		int expectedMsgID = ErrorManager.MSG_LIST_LABEL_INVALID_UNLESS_RETVAL_STRUCT;
   2111 		Object expectedArg = "x";
   2112 		Object expectedArg2 = null;
   2113 		GrammarSemanticsMessage expectedMessage =
   2114 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2115 		checkError(equeue, expectedMessage);
   2116 	}
   2117 
   2118 	@Test public void testRuleLabelOnTwoDifferentRulesAST() throws Exception {
   2119 		String grammar =
   2120 			"grammar T;\n"+
   2121 				"options {output=AST;}\n"+
   2122 				"s : x+=a x+=b {System.out.println($x);} ;" +
   2123 				"a : 'a';\n"+
   2124 				"b : 'b';\n"+
   2125 				"WS : (' '|'\\n') {skip();};\n";
   2126 		String expecting = "[a, b]\na b\n";
   2127 		String found = execParser("T.g", grammar, "TParser", "TLexer",
   2128 			"s", "a b", false);
   2129 		assertEquals(expecting, found);
   2130 	}
   2131 
   2132 	@Test public void testRuleLabelOnTwoDifferentRulesTemplate() throws Exception {
   2133 		String grammar =
   2134 			"grammar T;\n"+
   2135 				"options {output=template;}\n"+
   2136 				"s : x+=a x+=b {System.out.println($x);} ;" +
   2137 				"a : 'a' -> {%{\"hi\"}} ;\n"+
   2138 				"b : 'b' -> {%{\"mom\"}} ;\n"+
   2139 				"WS : (' '|'\\n') {skip();};\n";
   2140 		String expecting = "[hi, mom]\n";
   2141 		String found = execParser("T.g", grammar, "TParser", "TLexer",
   2142 			"s", "a b", false);
   2143 		assertEquals(expecting, found);
   2144 	}
   2145 
   2146 	@Test public void testMissingArgs() throws Exception {
   2147 		ErrorQueue equeue = new ErrorQueue();
   2148 		ErrorManager.setErrorListener(equeue);
   2149 		Grammar g = new Grammar(
   2150 			"grammar t;\n"+
   2151 				"a : r ;" +
   2152 				"r[int i] : 'a';\n");
   2153 		Tool antlr = newTool();
   2154 		antlr.setOutputDirectory(null); // write to /dev/null
   2155 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2156 		g.setCodeGenerator(generator);
   2157 		generator.genRecognizer();
   2158 
   2159 		int expectedMsgID = ErrorManager.MSG_MISSING_RULE_ARGS;
   2160 		Object expectedArg = "r";
   2161 		Object expectedArg2 = null;
   2162 		GrammarSemanticsMessage expectedMessage =
   2163 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2164 		checkError(equeue, expectedMessage);
   2165 	}
   2166 
   2167 	@Test public void testArgsWhenNoneDefined() throws Exception {
   2168 		ErrorQueue equeue = new ErrorQueue();
   2169 		ErrorManager.setErrorListener(equeue);
   2170 		Grammar g = new Grammar(
   2171 			"grammar t;\n"+
   2172 				"a : r[32,34] ;" +
   2173 				"r : 'a';\n");
   2174 		Tool antlr = newTool();
   2175 		antlr.setOutputDirectory(null); // write to /dev/null
   2176 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2177 		g.setCodeGenerator(generator);
   2178 		generator.genRecognizer();
   2179 
   2180 		int expectedMsgID = ErrorManager.MSG_RULE_HAS_NO_ARGS;
   2181 		Object expectedArg = "r";
   2182 		Object expectedArg2 = null;
   2183 		GrammarSemanticsMessage expectedMessage =
   2184 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2185 		checkError(equeue, expectedMessage);
   2186 	}
   2187 
   2188 	@Test public void testReturnInitValue() throws Exception {
   2189 		ErrorQueue equeue = new ErrorQueue();
   2190 		ErrorManager.setErrorListener(equeue);
   2191 		Grammar g = new Grammar(
   2192 			"grammar t;\n"+
   2193 				"a : r ;\n" +
   2194 				"r returns [int x=0] : 'a' {$x = 4;} ;\n");
   2195 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2196 
   2197 		Rule r = g.getRule("r");
   2198 		AttributeScope retScope = r.returnScope;
   2199 		List parameters = retScope.getAttributes();
   2200 		assertNotNull("missing return action", parameters);
   2201 		assertEquals(1, parameters.size());
   2202 		String found = parameters.get(0).toString();
   2203 		String expecting = "int x=0";
   2204 		assertEquals(expecting, found);
   2205 	}
   2206 
   2207 	@Test public void testMultipleReturnInitValue() throws Exception {
   2208 		ErrorQueue equeue = new ErrorQueue();
   2209 		ErrorManager.setErrorListener(equeue);
   2210 		Grammar g = new Grammar(
   2211 			"grammar t;\n"+
   2212 				"a : r ;\n" +
   2213 				"r returns [int x=0, int y, String s=new String(\"foo\")] : 'a' {$x = 4;} ;\n");
   2214 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2215 
   2216 		Rule r = g.getRule("r");
   2217 		AttributeScope retScope = r.returnScope;
   2218 		List parameters = retScope.getAttributes();
   2219 		assertNotNull("missing return action", parameters);
   2220 		assertEquals(3, parameters.size());
   2221 		assertEquals("int x=0", parameters.get(0).toString());
   2222 		assertEquals("int y", parameters.get(1).toString());
   2223 		assertEquals("String s=new String(\"foo\")", parameters.get(2).toString());
   2224 	}
   2225 
   2226 	@Test public void testCStyleReturnInitValue() throws Exception {
   2227 		ErrorQueue equeue = new ErrorQueue();
   2228 		ErrorManager.setErrorListener(equeue);
   2229 		Grammar g = new Grammar(
   2230 			"grammar t;\n"+
   2231 				"a : r ;\n" +
   2232 				"r returns [int (*x)()=NULL] : 'a' ;\n");
   2233 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2234 
   2235 		Rule r = g.getRule("r");
   2236 		AttributeScope retScope = r.returnScope;
   2237 		List parameters = retScope.getAttributes();
   2238 		assertNotNull("missing return action", parameters);
   2239 		assertEquals(1, parameters.size());
   2240 		String found = parameters.get(0).toString();
   2241 		String expecting = "int (*)() x=NULL";
   2242 		assertEquals(expecting, found);
   2243 	}
   2244 
   2245 	@Test public void testArgsWithInitValues() throws Exception {
   2246 		ErrorQueue equeue = new ErrorQueue();
   2247 		ErrorManager.setErrorListener(equeue);
   2248 		Grammar g = new Grammar(
   2249 			"grammar t;\n"+
   2250 				"a : r[32,34] ;" +
   2251 				"r[int x, int y=3] : 'a';\n");
   2252 		Tool antlr = newTool();
   2253 		antlr.setOutputDirectory(null); // write to /dev/null
   2254 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2255 		g.setCodeGenerator(generator);
   2256 		generator.genRecognizer();
   2257 
   2258 		int expectedMsgID = ErrorManager.MSG_ARG_INIT_VALUES_ILLEGAL;
   2259 		Object expectedArg = "y";
   2260 		Object expectedArg2 = null;
   2261 		GrammarSemanticsMessage expectedMessage =
   2262 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2263 		checkError(equeue, expectedMessage);
   2264 	}
   2265 
   2266 	@Test public void testArgsOnToken() throws Exception {
   2267 		ErrorQueue equeue = new ErrorQueue();
   2268 		ErrorManager.setErrorListener(equeue);
   2269 		Grammar g = new Grammar(
   2270 			"grammar t;\n"+
   2271 				"a : ID[32,34] ;" +
   2272 				"ID : 'a';\n");
   2273 		Tool antlr = newTool();
   2274 		antlr.setOutputDirectory(null); // write to /dev/null
   2275 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2276 		g.setCodeGenerator(generator);
   2277 		generator.genRecognizer();
   2278 
   2279 		int expectedMsgID = ErrorManager.MSG_ARGS_ON_TOKEN_REF;
   2280 		Object expectedArg = "ID";
   2281 		Object expectedArg2 = null;
   2282 		GrammarSemanticsMessage expectedMessage =
   2283 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2284 		checkError(equeue, expectedMessage);
   2285 	}
   2286 
   2287 	@Test public void testArgsOnTokenInLexer() throws Exception {
   2288 		ErrorQueue equeue = new ErrorQueue();
   2289 		ErrorManager.setErrorListener(equeue);
   2290 		Grammar g = new Grammar(
   2291 			"lexer grammar t;\n"+
   2292 				"R : 'z' ID[32,34] ;" +
   2293 				"ID : 'a';\n");
   2294 		Tool antlr = newTool();
   2295 		antlr.setOutputDirectory(null); // write to /dev/null
   2296 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2297 		g.setCodeGenerator(generator);
   2298 		generator.genRecognizer();
   2299 
   2300 		int expectedMsgID = ErrorManager.MSG_RULE_HAS_NO_ARGS;
   2301 		Object expectedArg = "ID";
   2302 		Object expectedArg2 = null;
   2303 		GrammarSemanticsMessage expectedMessage =
   2304 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2305 		checkError(equeue, expectedMessage);
   2306 	}
   2307 
   2308 	@Test public void testLabelOnRuleRefInLexer() throws Exception {
   2309 		String action = "$i.text";
   2310 		String expecting = "(i!=null?i.getText():null)";
   2311 		ErrorQueue equeue = new ErrorQueue();
   2312 		ErrorManager.setErrorListener(equeue);
   2313 		Grammar g = new Grammar(
   2314 			"lexer grammar t;\n"+
   2315 				"R : 'z' i=ID {"+action+"};" +
   2316 				"fragment ID : 'a';\n");
   2317 		Tool antlr = newTool();
   2318 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2319 		g.setCodeGenerator(generator);
   2320 		generator.genRecognizer(); // forces load of templates
   2321 		ActionTranslator translator =
   2322 			new ActionTranslator(generator,
   2323 				"R",
   2324 				new CommonToken(ANTLRParser.ACTION,action),1);
   2325 		String found = translator.translate();
   2326 		assertEquals(expecting, found);
   2327 
   2328 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2329 	}
   2330 
   2331 	@Test public void testRefToRuleRefInLexer() throws Exception {
   2332 		String action = "$ID.text";
   2333 		String expecting = "(ID1!=null?ID1.getText():null)";
   2334 		ErrorQueue equeue = new ErrorQueue();
   2335 		ErrorManager.setErrorListener(equeue);
   2336 		Grammar g = new Grammar(
   2337 			"lexer grammar t;\n"+
   2338 				"R : 'z' ID {"+action+"};" +
   2339 				"ID : 'a';\n");
   2340 		Tool antlr = newTool();
   2341 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2342 		g.setCodeGenerator(generator);
   2343 		generator.genRecognizer(); // forces load of templates
   2344 		ActionTranslator translator =
   2345 			new ActionTranslator(generator,
   2346 				"R",
   2347 				new CommonToken(ANTLRParser.ACTION,action),1);
   2348 		String found = translator.translate();
   2349 		assertEquals(expecting, found);
   2350 
   2351 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2352 	}
   2353 
   2354 	@Test public void testRefToRuleRefInLexerNoAttribute() throws Exception {
   2355 		String action = "$ID";
   2356 		String expecting = "ID1";
   2357 		ErrorQueue equeue = new ErrorQueue();
   2358 		ErrorManager.setErrorListener(equeue);
   2359 		Grammar g = new Grammar(
   2360 			"lexer grammar t;\n"+
   2361 				"R : 'z' ID {"+action+"};" +
   2362 				"ID : 'a';\n");
   2363 		Tool antlr = newTool();
   2364 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2365 		g.setCodeGenerator(generator);
   2366 		generator.genRecognizer(); // forces load of templates
   2367 		ActionTranslator translator =
   2368 			new ActionTranslator(generator,
   2369 				"R",
   2370 				new CommonToken(ANTLRParser.ACTION,action),1);
   2371 		String found = translator.translate();
   2372 		assertEquals(expecting, found);
   2373 
   2374 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2375 	}
   2376 
   2377 	@Test public void testCharLabelInLexer() throws Exception {
   2378 		ErrorQueue equeue = new ErrorQueue();
   2379 		ErrorManager.setErrorListener(equeue);
   2380 		Grammar g = new Grammar(
   2381 			"lexer grammar t;\n"+
   2382 				"R : x='z' ;\n");
   2383 
   2384 		Tool antlr = newTool();
   2385 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2386 		g.setCodeGenerator(generator);
   2387 		generator.genRecognizer(); // forces load of templates
   2388 
   2389 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2390 	}
   2391 
   2392 	@Test public void testCharListLabelInLexer() throws Exception {
   2393 		ErrorQueue equeue = new ErrorQueue();
   2394 		ErrorManager.setErrorListener(equeue);
   2395 		Grammar g = new Grammar(
   2396 			"lexer grammar t;\n"+
   2397 				"R : x+='z' ;\n");
   2398 
   2399 		Tool antlr = newTool();
   2400 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2401 		g.setCodeGenerator(generator);
   2402 		generator.genRecognizer(); // forces load of templates
   2403 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2404 	}
   2405 
   2406 	@Test public void testWildcardCharLabelInLexer() throws Exception {
   2407 		ErrorQueue equeue = new ErrorQueue();
   2408 		ErrorManager.setErrorListener(equeue);
   2409 		Grammar g = new Grammar(
   2410 			"lexer grammar t;\n"+
   2411 				"R : x=. ;\n");
   2412 
   2413 		Tool antlr = newTool();
   2414 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2415 		g.setCodeGenerator(generator);
   2416 		generator.genRecognizer(); // forces load of templates
   2417 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2418 	}
   2419 
   2420 	@Test public void testWildcardCharListLabelInLexer() throws Exception {
   2421 		ErrorQueue equeue = new ErrorQueue();
   2422 		ErrorManager.setErrorListener(equeue);
   2423 		Grammar g = new Grammar(
   2424 			"lexer grammar t;\n"+
   2425 				"R : x+=. ;\n");
   2426 
   2427 		Tool antlr = newTool();
   2428 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2429 		g.setCodeGenerator(generator);
   2430 		generator.genRecognizer(); // forces load of templates
   2431 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2432 	}
   2433 
   2434 	@Test public void testMissingArgsInLexer() throws Exception {
   2435 		ErrorQueue equeue = new ErrorQueue();
   2436 		ErrorManager.setErrorListener(equeue);
   2437 		Grammar g = new Grammar(
   2438 			"lexer grammar t;\n"+
   2439 				"A : R ;" +
   2440 				"R[int i] : 'a';\n");
   2441 		Tool antlr = newTool();
   2442 		antlr.setOutputDirectory(null); // write to /dev/null
   2443 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2444 		g.setCodeGenerator(generator);
   2445 		generator.genRecognizer();
   2446 
   2447 		int expectedMsgID = ErrorManager.MSG_MISSING_RULE_ARGS;
   2448 		Object expectedArg = "R";
   2449 		Object expectedArg2 = null;
   2450 		// getting a second error @1:12, probably from nextToken
   2451 		GrammarSemanticsMessage expectedMessage =
   2452 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2453 		checkError(equeue, expectedMessage);
   2454 	}
   2455 
   2456 	@Test public void testLexerRulePropertyRefs() throws Exception {
   2457 		String action = "$text $type $line $pos $channel $index $start $stop";
   2458 		String expecting = "getText() _type state.tokenStartLine state.tokenStartCharPositionInLine _channel -1 state.tokenStartCharIndex (getCharIndex()-1)";
   2459 		ErrorQueue equeue = new ErrorQueue();
   2460 		ErrorManager.setErrorListener(equeue);
   2461 		Grammar g = new Grammar(
   2462 			"lexer grammar t;\n"+
   2463 				"R : 'r' {"+action+"};\n");
   2464 		Tool antlr = newTool();
   2465 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2466 		g.setCodeGenerator(generator);
   2467 		generator.genRecognizer(); // forces load of templates
   2468 		ActionTranslator translator =
   2469 			new ActionTranslator(generator,
   2470 				"R",
   2471 				new CommonToken(ANTLRParser.ACTION,action),1);
   2472 		String found = translator.translate();
   2473 		assertEquals(expecting, found);
   2474 
   2475 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2476 	}
   2477 
   2478 	@Test public void testLexerLabelRefs() throws Exception {
   2479 		String action = "$a $b.text $c $d.text";
   2480 		String expecting = "a (b!=null?b.getText():null) c (d!=null?d.getText():null)";
   2481 		ErrorQueue equeue = new ErrorQueue();
   2482 		ErrorManager.setErrorListener(equeue);
   2483 		Grammar g = new Grammar(
   2484 			"lexer grammar t;\n"+
   2485 				"R : a='c' b='hi' c=. d=DUH {"+action+"};\n" +
   2486 				"DUH : 'd' ;\n");
   2487 		Tool antlr = newTool();
   2488 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2489 		g.setCodeGenerator(generator);
   2490 		generator.genRecognizer(); // forces load of templates
   2491 		ActionTranslator translator =
   2492 			new ActionTranslator(generator,
   2493 				"R",
   2494 				new CommonToken(ANTLRParser.ACTION,action),1);
   2495 		String found = translator.translate();
   2496 		assertEquals(expecting, found);
   2497 
   2498 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2499 	}
   2500 
   2501 	@Test public void testSettingLexerRulePropertyRefs() throws Exception {
   2502 		String action = "$text $type=1 $line=1 $pos=1 $channel=1 $index";
   2503 		String expecting = "getText() _type=1 state.tokenStartLine=1 state.tokenStartCharPositionInLine=1 _channel=1 -1";
   2504 		ErrorQueue equeue = new ErrorQueue();
   2505 		ErrorManager.setErrorListener(equeue);
   2506 		Grammar g = new Grammar(
   2507 			"lexer grammar t;\n"+
   2508 				"R : 'r' {"+action+"};\n");
   2509 		Tool antlr = newTool();
   2510 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2511 		g.setCodeGenerator(generator);
   2512 		generator.genRecognizer(); // forces load of templates
   2513 		ActionTranslator translator =
   2514 			new ActionTranslator(generator,
   2515 				"R",
   2516 				new CommonToken(ANTLRParser.ACTION,action),1);
   2517 		String found = translator.translate();
   2518 		assertEquals(expecting, found);
   2519 
   2520 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2521 	}
   2522 
   2523 	@Test public void testArgsOnTokenInLexerRuleOfCombined() throws Exception {
   2524 		ErrorQueue equeue = new ErrorQueue();
   2525 		ErrorManager.setErrorListener(equeue);
   2526 		Grammar g = new Grammar(
   2527 			"grammar t;\n"+
   2528 				"a : R;\n" +
   2529 				"R : 'z' ID[32] ;\n" +
   2530 				"ID : 'a';\n");
   2531 
   2532 		String lexerGrammarStr = g.getLexerGrammar();
   2533 		StringReader sr = new StringReader(lexerGrammarStr);
   2534 		Grammar lexerGrammar = new Grammar();
   2535 		lexerGrammar.setFileName("<internally-generated-lexer>");
   2536 		lexerGrammar.importTokenVocabulary(g);
   2537 		lexerGrammar.parseAndBuildAST(sr);
   2538 		lexerGrammar.defineGrammarSymbols();
   2539 		lexerGrammar.checkNameSpaceAndActions();
   2540 		sr.close();
   2541 
   2542 		Tool antlr = newTool();
   2543 		antlr.setOutputDirectory(null); // write to /dev/null
   2544 		CodeGenerator generator = new CodeGenerator(antlr, lexerGrammar, "Java");
   2545 		lexerGrammar.setCodeGenerator(generator);
   2546 		generator.genRecognizer();
   2547 
   2548 		int expectedMsgID = ErrorManager.MSG_RULE_HAS_NO_ARGS;
   2549 		Object expectedArg = "ID";
   2550 		Object expectedArg2 = null;
   2551 		GrammarSemanticsMessage expectedMessage =
   2552 			new GrammarSemanticsMessage(expectedMsgID, lexerGrammar, null, expectedArg, expectedArg2);
   2553 		checkError(equeue, expectedMessage);
   2554 	}
   2555 
   2556 	@Test public void testMissingArgsOnTokenInLexerRuleOfCombined() throws Exception {
   2557 		ErrorQueue equeue = new ErrorQueue();
   2558 		ErrorManager.setErrorListener(equeue);
   2559 		Grammar g = new Grammar(
   2560 			"grammar t;\n"+
   2561 				"a : R;\n" +
   2562 				"R : 'z' ID ;\n" +
   2563 				"ID[int i] : 'a';\n");
   2564 
   2565 		String lexerGrammarStr = g.getLexerGrammar();
   2566 		StringReader sr = new StringReader(lexerGrammarStr);
   2567 		Grammar lexerGrammar = new Grammar();
   2568 		lexerGrammar.setFileName("<internally-generated-lexer>");
   2569 		lexerGrammar.importTokenVocabulary(g);
   2570 		lexerGrammar.parseAndBuildAST(sr);
   2571 		lexerGrammar.defineGrammarSymbols();
   2572 		lexerGrammar.checkNameSpaceAndActions();
   2573 		sr.close();
   2574 
   2575 		Tool antlr = newTool();
   2576 		antlr.setOutputDirectory(null); // write to /dev/null
   2577 		CodeGenerator generator = new CodeGenerator(antlr, lexerGrammar, "Java");
   2578 		lexerGrammar.setCodeGenerator(generator);
   2579 		generator.genRecognizer();
   2580 
   2581 		int expectedMsgID = ErrorManager.MSG_MISSING_RULE_ARGS;
   2582 		Object expectedArg = "ID";
   2583 		Object expectedArg2 = null;
   2584 		GrammarSemanticsMessage expectedMessage =
   2585 			new GrammarSemanticsMessage(expectedMsgID, lexerGrammar, null, expectedArg, expectedArg2);
   2586 		checkError(equeue, expectedMessage);
   2587 	}
   2588 
   2589 	// T R E E S
   2590 
   2591 	@Test public void testTokenLabelTreeProperty() throws Exception {
   2592 		String action = "$id.tree;";
   2593 		String expecting = "id_tree;";
   2594 
   2595 		ErrorQueue equeue = new ErrorQueue();
   2596 		ErrorManager.setErrorListener(equeue);
   2597 		Grammar g = new Grammar(
   2598 			"grammar t;\n"+
   2599 				"a : id=ID {"+action+"} ;\n" +
   2600 				"ID : 'a';\n");
   2601 
   2602 		Tool antlr = newTool();
   2603 		antlr.setOutputDirectory(null); // write to /dev/null
   2604 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2605 		ActionTranslator translator =
   2606 			new ActionTranslator(generator,
   2607 				"a",
   2608 				new CommonToken(ANTLRParser.ACTION,action),1);
   2609 		g.setCodeGenerator(generator);
   2610 		generator.genRecognizer(); // forces load of templates
   2611 		String found = translator.translate();
   2612 		assertEquals(expecting, found);
   2613 
   2614 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2615 	}
   2616 
   2617 	@Test public void testTokenRefTreeProperty() throws Exception {
   2618 		String action = "$ID.tree;";
   2619 		String expecting = "ID1_tree;";
   2620 
   2621 		ErrorQueue equeue = new ErrorQueue();
   2622 		ErrorManager.setErrorListener(equeue);
   2623 		Grammar g = new Grammar(
   2624 			"grammar t;\n"+
   2625 				"a : ID {"+action+"} ;" +
   2626 				"ID : 'a';\n");
   2627 		Tool antlr = newTool();
   2628 		antlr.setOutputDirectory(null); // write to /dev/null
   2629 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2630 		g.setCodeGenerator(generator);
   2631 		generator.genRecognizer();
   2632 
   2633 		ActionTranslator translator = new ActionTranslator(generator,"a",
   2634 			new CommonToken(ANTLRParser.ACTION,action),1);
   2635 		String found = translator.translate();
   2636 		assertEquals(expecting, found);
   2637 	}
   2638 
   2639 	@Test public void testAmbiguousTokenRef() throws Exception {
   2640 		String action = "$ID;";
   2641 		String expecting = "";
   2642 
   2643 		ErrorQueue equeue = new ErrorQueue();
   2644 		ErrorManager.setErrorListener(equeue);
   2645 		Grammar g = new Grammar(
   2646 			"grammar t;\n"+
   2647 				"a : ID ID {"+action+"};" +
   2648 				"ID : 'a';\n");
   2649 		Tool antlr = newTool();
   2650 		antlr.setOutputDirectory(null); // write to /dev/null
   2651 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2652 		g.setCodeGenerator(generator);
   2653 		generator.genRecognizer();
   2654 
   2655 		int expectedMsgID = ErrorManager.MSG_NONUNIQUE_REF;
   2656 		Object expectedArg = "ID";
   2657 		GrammarSemanticsMessage expectedMessage =
   2658 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
   2659 		checkError(equeue, expectedMessage);
   2660 	}
   2661 
   2662 	@Test public void testAmbiguousTokenRefWithProp() throws Exception {
   2663 		String action = "$ID.text;";
   2664 		String expecting = "";
   2665 
   2666 		ErrorQueue equeue = new ErrorQueue();
   2667 		ErrorManager.setErrorListener(equeue);
   2668 		Grammar g = new Grammar(
   2669 			"grammar t;\n"+
   2670 				"a : ID ID {"+action+"};" +
   2671 				"ID : 'a';\n");
   2672 		Tool antlr = newTool();
   2673 		antlr.setOutputDirectory(null); // write to /dev/null
   2674 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2675 		g.setCodeGenerator(generator);
   2676 		generator.genRecognizer();
   2677 
   2678 		int expectedMsgID = ErrorManager.MSG_NONUNIQUE_REF;
   2679 		Object expectedArg = "ID";
   2680 		GrammarSemanticsMessage expectedMessage =
   2681 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg);
   2682 		checkError(equeue, expectedMessage);
   2683 	}
   2684 
   2685 	@Test public void testRuleRefWithDynamicScope() throws Exception {
   2686 		String action = "$field::x = $field.st;";
   2687 		String expecting = "((field_scope)field_stack.peek()).x = retval.st;";
   2688 
   2689 		ErrorQueue equeue = new ErrorQueue();
   2690 		ErrorManager.setErrorListener(equeue);
   2691 		Grammar g = new Grammar(
   2692 			"grammar a;\n" +
   2693 				"field\n" +
   2694 				"scope { ST x; }\n" +
   2695 				"    :   'y' {"+action+"}\n" +
   2696 				"    ;\n");
   2697 		Tool antlr = newTool();
   2698 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2699 		g.setCodeGenerator(generator);
   2700 		generator.genRecognizer(); // forces load of templates
   2701 		ActionTranslator translator = new ActionTranslator(generator,
   2702 			"field",
   2703 			new CommonToken(ANTLRParser.ACTION,action),1);
   2704 		String found = translator.translate();
   2705 		assertEquals(expecting, found);
   2706 
   2707 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2708 	}
   2709 
   2710 	@Test public void testAssignToOwnRulenameAttr() throws Exception {
   2711 		String action = "$rule.tree = null;";
   2712 		String expecting = "retval.tree = null;";
   2713 		ErrorQueue equeue = new ErrorQueue();
   2714 		ErrorManager.setErrorListener(equeue);
   2715 		Grammar g = new Grammar(
   2716 			"grammar a;\n" +
   2717 				"rule\n" +
   2718 				"    : 'y' {" + action +"}\n" +
   2719 				"    ;");
   2720 		Tool antlr = newTool();
   2721 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2722 		g.setCodeGenerator(generator);
   2723 		generator.genRecognizer(); // forces load of templates
   2724 		ActionTranslator translator = new ActionTranslator(generator,
   2725 			"rule",
   2726 			new CommonToken(ANTLRParser.ACTION,action),1);
   2727 		String found = translator.translate();
   2728 		assertEquals(expecting, found);
   2729 
   2730 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2731 	}
   2732 
   2733 	@Test public void testAssignToOwnParamAttr() throws Exception {
   2734 		String action = "$rule.i = 42; $i = 23;";
   2735 		String expecting = "i = 42; i = 23;";
   2736 		ErrorQueue equeue = new ErrorQueue();
   2737 		ErrorManager.setErrorListener(equeue);
   2738 		Grammar g = new Grammar(
   2739 			"grammar a;\n" +
   2740 				"rule[int i]\n" +
   2741 				"    : 'y' {" + action +"}\n" +
   2742 				"    ;");
   2743 		Tool antlr = newTool();
   2744 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2745 		g.setCodeGenerator(generator);
   2746 		generator.genRecognizer(); // forces load of templates
   2747 		ActionTranslator translator = new ActionTranslator(generator,
   2748 			"rule",
   2749 			new CommonToken(ANTLRParser.ACTION,action),1);
   2750 		String found = translator.translate();
   2751 		assertEquals(expecting, found);
   2752 
   2753 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2754 	}
   2755 
   2756 	@Test public void testIllegalAssignToOwnRulenameAttr() throws Exception {
   2757 		String action = "$rule.stop = 0;";
   2758 		ErrorQueue equeue = new ErrorQueue();
   2759 		ErrorManager.setErrorListener(equeue);
   2760 		Grammar g = new Grammar(
   2761 			"grammar a;\n" +
   2762 				"rule\n" +
   2763 				"    : 'y' {" + action +"}\n" +
   2764 				"    ;");
   2765 		Tool antlr = newTool();
   2766 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2767 		g.setCodeGenerator(generator);
   2768 		generator.genRecognizer(); // forces load of templates
   2769 		ActionTranslator translator = new ActionTranslator(generator,
   2770 			"rule",
   2771 			new CommonToken(ANTLRParser.ACTION,action),1);
   2772 		String rawTranslation =
   2773 			translator.translate();
   2774 
   2775 		int expectedMsgID = ErrorManager.MSG_WRITE_TO_READONLY_ATTR;
   2776 		Object expectedArg = "rule";
   2777 		Object expectedArg2 = "stop";
   2778 		GrammarSemanticsMessage expectedMessage =
   2779 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2780 		checkError(equeue, expectedMessage);
   2781 	}
   2782 
   2783 	@Test public void testIllegalAssignToLocalAttr() throws Exception {
   2784 		String action = "$tree = null; $st = null; $start = 0; $stop = 0; $text = 0;";
   2785 		String expecting = "retval.tree = null; retval.st = null;   ";
   2786 		ErrorQueue equeue = new ErrorQueue();
   2787 		ErrorManager.setErrorListener(equeue);
   2788 		Grammar g = new Grammar(
   2789 			"grammar a;\n" +
   2790 				"rule\n" +
   2791 				"    : 'y' {" + action +"}\n" +
   2792 				"    ;");
   2793 		Tool antlr = newTool();
   2794 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2795 		g.setCodeGenerator(generator);
   2796 		generator.genRecognizer(); // forces load of templates
   2797 		ActionTranslator translator = new ActionTranslator(generator,
   2798 			"rule",
   2799 			new CommonToken(ANTLRParser.ACTION,action),1);
   2800 		String rawTranslation =
   2801 			translator.translate();
   2802 
   2803 		int expectedMsgID = ErrorManager.MSG_WRITE_TO_READONLY_ATTR;
   2804 		ArrayList expectedErrors = new ArrayList(3);
   2805 		GrammarSemanticsMessage expectedMessage =
   2806 			new GrammarSemanticsMessage(expectedMsgID, g, null, "start", "");
   2807 		expectedErrors.add(expectedMessage);
   2808 		GrammarSemanticsMessage expectedMessage2 =
   2809 			new GrammarSemanticsMessage(expectedMsgID, g, null, "stop", "");
   2810 		expectedErrors.add(expectedMessage2);
   2811 		GrammarSemanticsMessage expectedMessage3 =
   2812 			new GrammarSemanticsMessage(expectedMsgID, g, null, "text", "");
   2813 		expectedErrors.add(expectedMessage3);
   2814 		checkErrors(equeue, expectedErrors);
   2815 
   2816 		STGroup templates =
   2817 			new STGroup();
   2818 		ST actionST = new ST(templates, rawTranslation);
   2819 		String found = actionST.render();
   2820 		assertEquals(expecting, found);
   2821 	}
   2822 
   2823 	@Test public void testIllegalAssignRuleRefAttr() throws Exception {
   2824 		String action = "$other.tree = null;";
   2825 		ErrorQueue equeue = new ErrorQueue();
   2826 		ErrorManager.setErrorListener(equeue);
   2827 		Grammar g = new Grammar(
   2828 			"grammar a;\n" +
   2829 				"options { output = AST;}" +
   2830 				"otherrule\n" +
   2831 				"    : 'y' ;" +
   2832 				"rule\n" +
   2833 				"    : other=otherrule {" + action +"}\n" +
   2834 				"    ;");
   2835 		Tool antlr = newTool();
   2836 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2837 		g.setCodeGenerator(generator);
   2838 		generator.genRecognizer(); // forces load of templates
   2839 		ActionTranslator translator = new ActionTranslator(generator,
   2840 			"rule",
   2841 			new CommonToken(ANTLRParser.ACTION,action),1);
   2842 		String rawTranslation =
   2843 			translator.translate();
   2844 
   2845 		int expectedMsgID = ErrorManager.MSG_WRITE_TO_READONLY_ATTR;
   2846 		Object expectedArg = "other";
   2847 		Object expectedArg2 = "tree";
   2848 		GrammarSemanticsMessage expectedMessage =
   2849 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2850 		checkError(equeue, expectedMessage);
   2851 	}
   2852 
   2853 	@Test public void testIllegalAssignTokenRefAttr() throws Exception {
   2854 		String action = "$ID.text = \"test\";";
   2855 		ErrorQueue equeue = new ErrorQueue();
   2856 		ErrorManager.setErrorListener(equeue);
   2857 		Grammar g = new Grammar(
   2858 			"grammar a;\n" +
   2859 				"ID\n" +
   2860 				"    : 'y' ;" +
   2861 				"rule\n" +
   2862 				"    : ID {" + action +"}\n" +
   2863 				"    ;");
   2864 		Tool antlr = newTool();
   2865 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2866 		g.setCodeGenerator(generator);
   2867 		generator.genRecognizer(); // forces load of templates
   2868 		ActionTranslator translator = new ActionTranslator(generator,
   2869 			"rule",
   2870 			new CommonToken(ANTLRParser.ACTION,action),1);
   2871 		String rawTranslation =
   2872 			translator.translate();
   2873 
   2874 		int expectedMsgID = ErrorManager.MSG_WRITE_TO_READONLY_ATTR;
   2875 		Object expectedArg = "ID";
   2876 		Object expectedArg2 = "text";
   2877 		GrammarSemanticsMessage expectedMessage =
   2878 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   2879 		checkError(equeue, expectedMessage);
   2880 	}
   2881 
   2882 	@Test public void testAssignToTreeNodeAttribute() throws Exception {
   2883 		String action = "$tree.scope = localScope;";
   2884 		String expecting = "((Object)retval.tree).scope = localScope;";
   2885 		ErrorQueue equeue = new ErrorQueue();
   2886 		ErrorManager.setErrorListener(equeue);
   2887 		Grammar g = new Grammar(
   2888 			"grammar a;\n" +
   2889 				"options { output=AST; }" +
   2890 				"rule\n" +
   2891 				"@init {\n" +
   2892 				"   Scope localScope=null;\n" +
   2893 				"}\n" +
   2894 				"@after {\n" +
   2895 				"   ###$tree.scope = localScope;!!!\n" +
   2896 				"}\n" +
   2897 				"   : 'a' -> ^('a')\n" +
   2898 				";");
   2899 		Tool antlr = newTool();
   2900 
   2901 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2902 		g.setCodeGenerator(generator);
   2903 		generator.genRecognizer(); // codegen phase sets some vars we need
   2904 		ST codeST = generator.getRecognizerST();
   2905 		String code = codeST.render();
   2906 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   2907 		assertEquals(expecting, found);
   2908 
   2909 	}
   2910 
   2911 	@Test public void testDoNotTranslateAttributeCompare() throws Exception {
   2912 		String action = "$a.line == $b.line";
   2913 		String expecting = "(a!=null?a.getLine():0) == (b!=null?b.getLine():0)";
   2914 		ErrorQueue equeue = new ErrorQueue();
   2915 		ErrorManager.setErrorListener(equeue);
   2916 		Grammar g = new Grammar(
   2917 			"lexer grammar a;\n" +
   2918 				"RULE:\n" +
   2919 				"     a=ID b=ID {" + action + "}" +
   2920 				"    ;\n" +
   2921 				"ID : 'id';"
   2922 		);
   2923 		Tool antlr = newTool();
   2924 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2925 		g.setCodeGenerator(generator);
   2926 		generator.genRecognizer();
   2927 		ActionTranslator translator = new ActionTranslator(generator,
   2928 			"RULE",
   2929 			new CommonToken(ANTLRParser.ACTION,action),1);
   2930 		String found = translator.translate();
   2931 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2932 		assertEquals(expecting, found);
   2933 	}
   2934 
   2935 	@Test public void testDoNotTranslateScopeAttributeCompare() throws Exception {
   2936 		String action = "if ($rule::foo == \"foo\" || 1) { System.out.println(\"ouch\"); }";
   2937 		String expecting = "if (((rule_scope)rule_stack.peek()).foo == \"foo\" || 1) { System.out.println(\"ouch\"); }";
   2938 		ErrorQueue equeue = new ErrorQueue();
   2939 		ErrorManager.setErrorListener(equeue);
   2940 		Grammar g = new Grammar(
   2941 			"grammar a;\n" +
   2942 				"rule\n" +
   2943 				"scope {\n" +
   2944 				"   String foo;" +
   2945 				"} :\n" +
   2946 				"     twoIDs" +
   2947 				"    ;\n" +
   2948 				"twoIDs:\n" +
   2949 				"    ID ID {" + action + "}\n" +
   2950 				"    ;\n" +
   2951 				"ID : 'id';"
   2952 		);
   2953 		Tool antlr = newTool();
   2954 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2955 		g.setCodeGenerator(generator);
   2956 		generator.genRecognizer();
   2957 		ActionTranslator translator = new ActionTranslator(generator,
   2958 			"twoIDs",
   2959 			new CommonToken(ANTLRParser.ACTION,action),1);
   2960 		String rawTranslation =
   2961 			translator.translate();
   2962 		// check that we didn't use scopeSetAttributeRef int translation!
   2963 		boolean foundScopeSetAttributeRef = false;
   2964 		for (int i = 0; i < translator.chunks.size(); i++) {
   2965 			Object chunk = translator.chunks.get(i);
   2966 			if (chunk instanceof ST) {
   2967 				if (((ST)chunk).getName().equals("/scopeSetAttributeRef")) {
   2968 					foundScopeSetAttributeRef = true;
   2969 				}
   2970 			}
   2971 		}
   2972 		assertFalse("action translator used scopeSetAttributeRef template in comparison!", foundScopeSetAttributeRef);
   2973 		STGroup templates =
   2974 			new STGroup();
   2975 		ST actionST = new ST(templates, rawTranslation);
   2976 		String found = actionST.render();
   2977 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   2978 		assertEquals(expecting, found);
   2979 	}
   2980 
   2981 	@Test public void testTreeRuleStopAttributeIsInvalid() throws Exception {
   2982 		String action = "$r.x; $r.start; $r.stop";
   2983 		String expecting = "(r!=null?r.x:0); (r!=null?((CommonTree)r.start):null); $r.stop";
   2984 
   2985 		ErrorQueue equeue = new ErrorQueue();
   2986 		ErrorManager.setErrorListener(equeue);
   2987 		Grammar g = new Grammar(
   2988 			"tree grammar t;\n" +
   2989 				"options {ASTLabelType=CommonTree;}\n"+
   2990 				"a returns [int x]\n" +
   2991 				"  :\n" +
   2992 				"  ;\n"+
   2993 				"b : r=a {###"+action+"!!!}\n" +
   2994 				"  ;");
   2995 		System.out.println(g.toString());
   2996 		Tool antlr = newTool();
   2997 		antlr.setOutputDirectory(null); // write to /dev/null
   2998 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   2999 		g.setCodeGenerator(generator);
   3000 		generator.genRecognizer(); // codegen phase sets some vars we need
   3001 		ST codeST = generator.getRecognizerST();
   3002 		String code = codeST.render();
   3003 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   3004 		assertEquals(expecting, found);
   3005 
   3006 		int expectedMsgID = ErrorManager.MSG_UNKNOWN_RULE_ATTRIBUTE;
   3007 		Object expectedArg = "a";
   3008 		Object expectedArg2 = "stop";
   3009 		GrammarSemanticsMessage expectedMessage =
   3010 			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
   3011 		System.out.println("equeue:"+equeue);
   3012 		checkError(equeue, expectedMessage);
   3013 	}
   3014 
   3015 	@Test public void testRefToTextAttributeForCurrentTreeRule() throws Exception {
   3016 		String action = "$text";
   3017 		String expecting = "input.getTokenStream().toString(" +
   3018 			"input.getTreeAdaptor().getTokenStartIndex(retval.start)," +
   3019 			"input.getTreeAdaptor().getTokenStopIndex(retval.start))";
   3020 
   3021 		ErrorQueue equeue = new ErrorQueue();
   3022 		ErrorManager.setErrorListener(equeue);
   3023 		Grammar g = new Grammar(
   3024 			"tree grammar t;\n" +
   3025 				"options {ASTLabelType=CommonTree;}\n" +
   3026 				"a : {###"+action+"!!!}\n" +
   3027 				"  ;\n");
   3028 
   3029 		Tool antlr = newTool();
   3030 		antlr.setOutputDirectory(null); // write to /dev/null
   3031 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   3032 		g.setCodeGenerator(generator);
   3033 		generator.genRecognizer(); // codegen phase sets some vars we need
   3034 		ST codeST = generator.getRecognizerST();
   3035 		String code = codeST.render();
   3036 		String found = code.substring(code.indexOf("###")+3,code.indexOf("!!!"));
   3037 		assertEquals(expecting, found);
   3038 
   3039 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   3040 	}
   3041 
   3042 	@Test public void testTypeOfGuardedAttributeRefIsCorrect() throws Exception {
   3043 		String action = "int x = $b::n;";
   3044 		String expecting = "int x = ((b_scope)b_stack.peek()).n;";
   3045 
   3046 		ErrorQueue equeue = new ErrorQueue();
   3047 		ErrorManager.setErrorListener(equeue);
   3048 		Grammar g = new Grammar(
   3049 			"grammar t;\n" +
   3050 				"s : b ;\n"+
   3051 				"b\n" +
   3052 				"scope {\n" +
   3053 				"  int n;\n" +
   3054 				"} : '(' b ')' {"+action+"}\n" + // refers to current invocation's n
   3055 				"  ;\n");
   3056 		Tool antlr = newTool();
   3057 		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
   3058 		g.setCodeGenerator(generator);
   3059 		generator.genRecognizer(); // forces load of templates
   3060 		ActionTranslator translator = new ActionTranslator(generator, "b",
   3061 			new CommonToken(ANTLRParser.ACTION,action),1);
   3062 		String found = translator.translate();
   3063 		assertEquals(expecting, found);
   3064 
   3065 		assertEquals("unexpected errors: "+equeue, 0, equeue.errors.size());
   3066 	}
   3067 
   3068 	// S U P P O R T
   3069 
   3070 	protected void checkError(ErrorQueue equeue,
   3071 							  GrammarSemanticsMessage expectedMessage)
   3072 		throws Exception
   3073 	{
   3074 		/*
   3075 		System.out.println(equeue.infos);
   3076 		System.out.println(equeue.warnings);
   3077 		System.out.println(equeue.errors);
   3078 		*/
   3079 		Message foundMsg = null;
   3080 		for (int i = 0; i < equeue.errors.size(); i++) {
   3081 			Message m = (Message)equeue.errors.get(i);
   3082 			if (m.msgID==expectedMessage.msgID ) {
   3083 				foundMsg = m;
   3084 			}
   3085 		}
   3086 		assertTrue("no error; "+expectedMessage.msgID+" expected", equeue.errors.size() > 0);
   3087 		assertNotNull("couldn't find expected error: "+expectedMessage.msgID+" in "+equeue, foundMsg);
   3088 		assertTrue("error is not a GrammarSemanticsMessage",
   3089 			foundMsg instanceof GrammarSemanticsMessage);
   3090 		assertEquals(expectedMessage.arg, foundMsg.arg);
   3091 		assertEquals(expectedMessage.arg2, foundMsg.arg2);
   3092 	}
   3093 
   3094 	/** Allow checking for multiple errors in one test */
   3095 	protected void checkErrors(ErrorQueue equeue,
   3096 							   ArrayList expectedMessages)
   3097 		throws Exception
   3098 	{
   3099 		ArrayList messageExpected = new ArrayList(equeue.errors.size());
   3100 		for (int i = 0; i < equeue.errors.size(); i++) {
   3101 			Message m = (Message)equeue.errors.get(i);
   3102 			boolean foundMsg = false;
   3103 			for (int j = 0; j < expectedMessages.size(); j++) {
   3104 				Message em = (Message)expectedMessages.get(j);
   3105 				if (m.msgID==em.msgID && m.arg.equals(em.arg) && m.arg2.equals(em.arg2)) {
   3106 					foundMsg = true;
   3107 				}
   3108 			}
   3109 			if (foundMsg) {
   3110 				messageExpected.add(i, Boolean.TRUE);
   3111 			} else
   3112 				messageExpected.add(i, Boolean.FALSE);
   3113 		}
   3114 		for (int i = 0; i < equeue.errors.size(); i++) {
   3115 			assertTrue("unexpected error:" + equeue.errors.get(i), ((Boolean)messageExpected.get(i)).booleanValue());
   3116 		}
   3117 	}
   3118 }
   3119