1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/*
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * [The "BSD license"]
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  Copyright (c) 2010 Terence Parr
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  All rights reserved.
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  Redistribution and use in source and binary forms, with or without
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  modification, are permitted provided that the following conditions
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  are met:
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  1. Redistributions of source code must retain the above copyright
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *      notice, this list of conditions and the following disclaimer.
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  2. Redistributions in binary form must reproduce the above copyright
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *      notice, this list of conditions and the following disclaimer in the
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *      documentation and/or other materials provided with the distribution.
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  3. The name of the author may not be used to endorse or promote products
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *      derived from this software without specific prior written permission.
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpackage org.antlr.test;
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.Tool;
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.codegen.CodeGenerator;
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.tool.ErrorManager;
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.tool.Grammar;
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.tool.GrammarSemanticsMessage;
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.junit.Ignore;
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.junit.Test;
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpublic class TestRewriteAST extends BaseTest {
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected boolean debug = false;
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testDelete() throws Exception {
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID INT -> ;\n" +
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc 34", debug);
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("", found);
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSingleToken() throws Exception {
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID -> ID;\n" +
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("abc\n", found);
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSingleTokenToNewNode() throws Exception {
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID -> ID[\"x\"];\n" +
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("x\n", found);
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSingleTokenToNewNodeRoot() throws Exception {
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID -> ^(ID[\"x\"] INT);\n" +
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(x INT)\n", found);
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSingleTokenToNewNode2() throws Exception {
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// Allow creation of new nodes w/o args.
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar TT;\n" +
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID -> ID[ ];\n" +
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("TT.g", grammar, "TTParser", "TTLexer",
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("ID\n", found);
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSingleCharLiteral() throws Exception {
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : 'c' -> 'c';\n" +
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "c", debug);
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("c\n", found);
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSingleStringLiteral() throws Exception {
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : 'ick' -> 'ick';\n" +
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "ick", debug);
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("ick\n", found);
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSingleRule() throws Exception {
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b -> b;\n" +
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n" +
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("abc\n", found);
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testReorderTokens() throws Exception {
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID INT -> INT ID;\n" +
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc 34", debug);
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("34 abc\n", found);
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testReorderTokenAndRule() throws Exception {
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b INT -> INT b;\n" +
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n" +
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc 34", debug);
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("34 abc\n", found);
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testTokenTree() throws Exception {
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID INT -> ^(INT ID);\n" +
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc 34", debug);
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(34 abc)\n", found);
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testTokenTreeAfterOtherStuff() throws Exception {
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : 'void' ID INT -> 'void' ^(INT ID);\n" +
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "void abc 34", debug);
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("void (34 abc)\n", found);
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testNestedTokenTreeWithOuterLoop() throws Exception {
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// verify that ID and INT both iterate over outer index variable
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {DUH;}\n" +
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID INT ID INT -> ^( DUH ID ^( DUH INT) )+ ;\n" +
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a 1 b 2", debug);
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(DUH a (DUH 1)) (DUH b (DUH 2))\n", found);
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptionalSingleToken() throws Exception {
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID -> ID? ;\n" +
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("abc\n", found);
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testClosureSingleToken() throws Exception {
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID ID -> ID* ;\n" +
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testPositiveClosureSingleToken() throws Exception {
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID ID -> ID+ ;\n" +
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptionalSingleRule() throws Exception {
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b -> b?;\n" +
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n" +
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("abc\n", found);
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testClosureSingleRule() throws Exception {
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b b -> b*;\n" +
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n" +
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testClosureOfLabel() throws Exception {
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x+=b x+=b -> $x*;\n" +
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n" +
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptionalLabelNoListLabel() throws Exception {
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : (x=ID)? -> $x?;\n" +
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a", debug);
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a\n", found);
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testPositiveClosureSingleRule() throws Exception {
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b b -> b+;\n" +
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n" +
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSinglePredicateT() throws Exception {
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID -> {true}? ID -> ;\n" +
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("abc\n", found);
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSinglePredicateF() throws Exception {
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID -> {false}? ID -> ;\n" +
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc", debug);
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("", found);
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testMultiplePredicate() throws Exception {
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID INT -> {false}? ID\n" +
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"           -> {true}? INT\n" +
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"           -> \n" +
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"  ;\n" +
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a 2", debug);
362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("2\n", found);
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testMultiplePredicateTrees() throws Exception {
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID INT -> {false}? ^(ID INT)\n" +
370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"           -> {true}? ^(INT ID)\n" +
371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"           -> ID\n" +
372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"  ;\n" +
373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a 2", debug);
378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(2 a)\n", found);
379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSimpleTree() throws Exception {
382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : op INT -> ^(op INT);\n" +
386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "-34", debug);
392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(- 34)\n", found);
393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSimpleTree2() throws Exception {
396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : op INT -> ^(INT op);\n" +
400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "+ 34", debug);
406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(34 +)\n", found);
407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testNestedTrees() throws Exception {
411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : 'var' (ID ':' type ';')+ -> ^('var' ^(':' ID type)+) ;\n" +
415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "var a:int; b:float;", debug);
421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(var (: a int) (: b float))\n", found);
422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testImaginaryTokenCopy() throws Exception {
425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {VAR;}\n" +
429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID (',' ID)*-> ^(VAR ID)+ ;\n" +
430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a,b,c", debug);
436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(VAR a) (VAR b) (VAR c)\n", found);
437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testTokenUnreferencedOnLeftButDefined() throws Exception {
440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {VAR;}\n" +
444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b -> ID ;\n" +
445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a", debug);
451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("ID\n", found);
452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testImaginaryTokenCopySetText() throws Exception {
455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {VAR;}\n" +
459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID (',' ID)*-> ^(VAR[\"var\"] ID)+ ;\n" +
460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a,b,c", debug);
466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(var a) (var b) (var c)\n", found);
467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testImaginaryTokenNoCopyFromToken() throws Exception {
470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;\n" +
475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "{a b c}", debug);
481324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("({ a b c)\n", found);
482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testImaginaryTokenNoCopyFromTokenSetText() throws Exception {
485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : lc='{' ID+ '}' -> ^(BLOCK[$lc,\"block\"] ID+) ;\n" +
490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "{a b c}", debug);
496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(block a b c)\n", found);
497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testMixedRewriteAndAutoAST() throws Exception {
500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b b^ ;\n" + // 2nd b matches only an INT; can make it root
505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID INT -> INT ID\n" +
506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"  | INT\n" +
507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"  ;\n" +
508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
510324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
511324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
512324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a 1 2", debug);
513324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(2 1 a)\n", found);
514324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
515324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
516324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSubruleWithRewrite() throws Exception {
517324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
518324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
519324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
520324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
521324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b b ;\n" +
522324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : (ID INT -> INT ID | INT INT -> INT+ )\n" +
523324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"  ;\n" +
524324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
525324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
526324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
527324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
528324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a 1 2 3", debug);
529324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("1 a 2 3\n", found);
530324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
531324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
532324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSubruleWithRewrite2() throws Exception {
533324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
534324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
535324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
536324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {TYPE;}\n" +
537324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b b ;\n" +
538324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : 'int'\n" +
539324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"    ( ID -> ^(TYPE 'int' ID)\n" +
540324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"    | ID '=' INT -> ^(TYPE 'int' ID INT)\n" +
541324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"    )\n" +
542324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"    ';'\n" +
543324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"  ;\n" +
544324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
545324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
546324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
547324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
548324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "int a; int b=3;", debug);
549324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(TYPE int a) (TYPE int b 3)\n", found);
550324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
551324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
552324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testNestedRewriteShutsOffAutoAST() throws Exception {
553324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
554324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
555324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
556324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
557324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b b ;\n" +
558324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ( ID (last=ID -> $last)+ ) ';'\n" + // get last ID
559324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"  | INT\n" + // should still get auto AST construction
560324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"  ;\n" +
561324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
562324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
563324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
564324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
565324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b c d; 42", debug);
566324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("d 42\n", found);
567324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
568324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
569324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testRewriteActions() throws Exception {
570324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
571324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
572324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
573324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : atom -> ^({adaptor.create(INT,\"9\")} atom) ;\n" +
574324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"atom : INT ;\n" +
575324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
576324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
577324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
578324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
579324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "3", debug);
580324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(9 3)\n", found);
581324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
582324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
583324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testRewriteActions2() throws Exception {
584324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
585324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
586324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
587324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : atom -> {adaptor.create(INT,\"9\")} atom ;\n" +
588324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"atom : INT ;\n" +
589324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
590324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
591324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
592324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
593324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "3", debug);
594324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("9 3\n", found);
595324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
596324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
597324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testRefToOldValue() throws Exception {
598324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
599324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
600324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
601324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
602324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : (atom -> atom) (op='+' r=atom -> ^($op $a $r) )* ;\n" +
603324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"atom : INT ;\n" +
604324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
605324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
606324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
607324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
608324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "3+4+5", debug);
609324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(+ (+ 3 4) 5)\n", found);
610324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
611324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
612324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopySemanticsForRules() throws Exception {
613324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
614324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
615324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
616324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
617324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : atom -> ^(atom atom) ;\n" + // NOT CYCLE! (dup atom)
618324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"atom : INT ;\n" +
619324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
620324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
621324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
622324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
623324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "3", debug);
624324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(3 3)\n", found);
625324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
626324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
627324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopySemanticsForRules2() throws Exception {
628324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// copy type as a root for each invocation of (...)+ in rewrite
629324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
630324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
631324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
632324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : type ID (',' ID)* ';' -> ^(type ID)+ ;\n" +
633324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' ;\n" +
634324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
635324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
636324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
637324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "int a,b,c;", debug);
638324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(int a) (int b) (int c)\n", found);
639324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
640324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
641324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopySemanticsForRules3() throws Exception {
642324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// copy type *and* modifier even though it's optional
643324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// for each invocation of (...)+ in rewrite
644324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
645324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
646324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
647324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : modifier? type ID (',' ID)* ';' -> ^(type modifier? ID)+ ;\n" +
648324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' ;\n" +
649324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"modifier : 'public' ;\n" +
650324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
651324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
652324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
653324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "public int a,b,c;", debug);
654324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(int public a) (int public b) (int public c)\n", found);
655324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
656324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
657324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopySemanticsForRules3Double() throws Exception {
658324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// copy type *and* modifier even though it's optional
659324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// for each invocation of (...)+ in rewrite
660324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
661324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
662324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
663324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : modifier? type ID (',' ID)* ';' -> ^(type modifier? ID)+ ^(type modifier? ID)+ ;\n" +
664324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' ;\n" +
665324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"modifier : 'public' ;\n" +
666324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
667324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
668324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
669324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "public int a,b,c;", debug);
670324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(int public a) (int public b) (int public c) (int public a) (int public b) (int public c)\n", found);
671324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
672324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
673324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopySemanticsForRules4() throws Exception {
674324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// copy type *and* modifier even though it's optional
675324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// for each invocation of (...)+ in rewrite
676324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
677324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
678324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
679324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {MOD;}\n" +
680324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : modifier? type ID (',' ID)* ';' -> ^(type ^(MOD modifier)? ID)+ ;\n" +
681324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' ;\n" +
682324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"modifier : 'public' ;\n" +
683324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
684324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
685324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
686324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "public int a,b,c;", debug);
687324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(int (MOD public) a) (int (MOD public) b) (int (MOD public) c)\n", found);
688324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
689324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
690324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopySemanticsLists() throws Exception {
691324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
692324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
693324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
694324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {MOD;}\n" +
695324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID (',' ID)* ';' -> ID+ ID+ ;\n"+
696324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
697324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
698324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
699324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a,b,c;", debug);
700324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b c a b c\n", found);
701324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
702324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
703324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopyRuleLabel() throws Exception {
704324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
705324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
706324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
707324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
708324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x=b -> $x $x;\n"+
709324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
710324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
711324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
712324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
713324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a", debug);
714324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a a\n", found);
715324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
716324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
717324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopyRuleLabel2() throws Exception {
718324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
719324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
720324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
721324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
722324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x=b -> ^($x $x);\n"+
723324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
724324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
725324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
726324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
727324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a", debug);
728324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(a a)\n", found);
729324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
730324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
731324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testQueueingOfTokens() throws Exception {
732324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
733324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
734324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
735324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : 'int' ID (',' ID)* ';' -> ^('int' ID+) ;\n" +
736324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
737324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
738324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
739324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
740324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
741324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "int a,b,c;", debug);
742324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(int a b c)\n", found);
743324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
744324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
745324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCopyOfTokens() throws Exception {
746324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
747324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
748324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
749324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : 'int' ID ';' -> 'int' ID 'int' ID ;\n" +
750324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
751324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
752324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
753324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
754324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
755324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "int a;", debug);
756324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("int a int a\n", found);
757324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
758324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
759324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testTokenCopyInLoop() throws Exception {
760324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
761324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
762324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
763324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : 'int' ID (',' ID)* ';' -> ^('int' ID)+ ;\n" +
764324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
765324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
766324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
767324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
768324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
769324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "int a,b,c;", debug);
770324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(int a) (int b) (int c)\n", found);
771324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
772324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
773324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testTokenCopyInLoopAgainstTwoOthers() throws Exception {
774324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// must smear 'int' copies across as root of multiple trees
775324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
776324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
777324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
778324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : 'int' ID ':' INT (',' ID ':' INT)* ';' -> ^('int' ID INT)+ ;\n" +
779324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
780324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
781324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
782324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
783324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
784324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "int a:1,b:2,c:3;", debug);
785324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(int a 1) (int b 2) (int c 3)\n", found);
786324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
787324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
788324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testListRefdOneAtATime() throws Exception {
789324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
790324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
791324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
792324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID+ -> ID ID ID ;\n" + // works if 3 input IDs
793324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
794324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
795324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
796324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
797324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
798324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b c", debug);
799324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b c\n", found);
800324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
801324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
802324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSplitListWithLabels() throws Exception {
803324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
804324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
805324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
806324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {VAR;}\n"+
807324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : first=ID others+=ID* -> $first VAR $others+ ;\n" +
808324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
809324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
810324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
811324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
812324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
813324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b c", debug);
814324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a VAR b c\n", found);
815324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
816324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
817324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testComplicatedMelange() throws Exception {
818324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
819324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
820324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
821324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
822324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : A A b=B B b=B c+=C C c+=C D {String s=$D.text;} -> A+ B+ C+ D ;\n" +
823324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
824324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"A : 'a' ;\n" +
825324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"B : 'b' ;\n" +
826324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"C : 'c' ;\n" +
827324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"D : 'd' ;\n" +
828324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
829324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
830324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a a b b b c c c d", debug);
831324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a a b b b c c c d\n", found);
832324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
833324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
834324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testRuleLabel() throws Exception {
835324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
836324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
837324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
838324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
839324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x=b -> $x;\n"+
840324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
841324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
842324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
843324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
844324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a", debug);
845324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a\n", found);
846324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
847324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
848324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testAmbiguousRule() throws Exception {
849324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
850324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
851324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
852324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID a -> a | INT ;\n"+
853324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
854324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT: '0'..'9'+ ;\n" +
855324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
856324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
857324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc 34", debug);
858324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("34\n", found);
859324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
860324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
861324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testWeirdRuleRef() throws Exception {
862324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorQueue equeue = new ErrorQueue();
863324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorManager.setErrorListener(equeue);
864324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
865324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
866324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
867324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID a -> $a | INT ;\n"+
868324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
869324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT: '0'..'9'+ ;\n" +
870324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
871324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
872324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar g = new Grammar(grammar);
873324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Tool antlr = newTool();
874324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		antlr.setOutputDirectory(null); // write to /dev/null
875324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
876324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		g.setCodeGenerator(generator);
877324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		generator.genRecognizer();
878324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
879324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// $a is ambig; is it previous root or ref to a ref in alt?
880324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("unexpected errors: "+equeue, 1, equeue.errors.size());
881324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
882324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
883324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testRuleListLabel() throws Exception {
884324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
885324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
886324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
887324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
888324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x+=b x+=b -> $x+;\n"+
889324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
890324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
891324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
892324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
893324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
894324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
895324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
896324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
897324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testRuleListLabel2() throws Exception {
898324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
899324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
900324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
901324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
902324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x+=b x+=b -> $x $x*;\n"+
903324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
904324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
905324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
906324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
907324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
908324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
909324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
910324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
911324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptional() throws Exception {
912324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
913324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
914324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
915324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
916324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x=b (y=b)? -> $x $y?;\n"+
917324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
918324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
919324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
920324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
921324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a", debug);
922324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a\n", found);
923324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
924324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
925324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptional2() throws Exception {
926324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
927324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
928324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
929324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
930324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x=ID (y=b)? -> $x $y?;\n"+
931324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
932324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
933324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
934324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
935324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
936324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
937324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
938324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
939324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptional3() throws Exception {
940324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
941324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
942324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
943324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
944324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x=ID (y=b)? -> ($x $y)?;\n"+
945324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
946324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
947324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
948324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
949324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
950324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
951324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
952324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
953324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptional4() throws Exception {
954324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
955324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
956324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
957324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
958324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x+=ID (y=b)? -> ($x $y)?;\n"+
959324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
960324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
961324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
962324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
963324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
964324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a b\n", found);
965324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
966324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
967324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptional5() throws Exception {
968324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
969324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
970324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
971324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
972324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID -> ID? ;\n"+ // match an ID to optional ID
973324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
974324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
975324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
976324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
977324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a", debug);
978324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("a\n", found);
979324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
980324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
981324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testArbitraryExprType() throws Exception {
982324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
983324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
984324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
985324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
986324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x+=b x+=b -> {new CommonTree()};\n"+
987324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID ;\n"+
988324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
989324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
990324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
991324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b", debug);
992324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("", found);
993324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
994324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
995324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSet() throws Exception {
996324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
997324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
998324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options { output = AST; } \n" +
999324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a: (INT|ID)+ -> INT+ ID+ ;\n" +
1000324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT: '0'..'9'+;\n" +
1001324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+;\n" +
1002324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1003324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
1004324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "2 a 34 de", debug);
1005324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("2 34 a de\n", found);
1006324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1007324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1008324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testSet2() throws Exception {
1009324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1010324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1011324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options { output = AST; } \n" +
1012324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a: (INT|ID) -> INT? ID? ;\n" +
1013324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT: '0'..'9'+;\n" +
1014324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+;\n" +
1015324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1016324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
1017324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "2", debug);
1018324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("2\n", found);
1019324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1020324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1021324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Ignore
1022324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // TODO: FAILS. The should probably generate a warning from antlr
1023324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // See http://www.antlr.org:8888/browse/ANTLR-162
1024324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    //
1025324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void testSetWithLabel() throws Exception {
1026324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1027324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1028324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1029324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options { output = AST; } \n" +
1030324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : x=(INT|ID) -> $x ;\n" +
1031324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT: '0'..'9'+;\n" +
1032324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+;\n" +
1033324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1034324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
1035324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "2", debug);
1036324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("2\n", found);
1037324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1038324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1039324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testRewriteAction() throws Exception {
1040324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1041324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T; \n" +
1042324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options { output = AST; }\n" +
1043324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens { FLOAT; }\n" +
1044324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"r\n" +
1045324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"    : INT -> {new CommonTree(new CommonToken(FLOAT,$INT.text+\".0\"))} \n" +
1046324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"    ; \n" +
1047324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+; \n" +
1048324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS: (' ' | '\\n' | '\\t')+ {$channel = HIDDEN;}; \n";
1049324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
1050324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "r", "25", debug);
1051324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("25.0\n", found);
1052324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1053324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1054324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testOptionalSubruleWithoutRealElements() throws Exception {
1055324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// copy type *and* modifier even though it's optional
1056324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// for each invocation of (...)+ in rewrite
1057324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1058324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1059324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;} \n" +
1060324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {PARMS;} \n" +
1061324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"\n" +
1062324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"modulo \n" +
1063324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			" : 'modulo' ID ('(' parms+ ')')? -> ^('modulo' ID ^(PARMS parms+)?) \n" +
1064324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			" ; \n" +
1065324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"parms : '#'|ID; \n" +
1066324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : ('a'..'z' | 'A'..'Z')+;\n" +
1067324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1068324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
1069324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "modulo", "modulo abc (x y #)", debug);
1070324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(modulo abc (PARMS x y #))\n", found);
1071324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1072324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1073324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	// C A R D I N A L I T Y  I S S U E S
1074324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1075324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCardinality() throws Exception {
1076324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1077324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1078324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1079324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {BLOCK;}\n" +
1080324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID ID INT INT INT -> (ID INT)+;\n"+
1081324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1082324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+; \n" +
1083324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1084324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		execParser("T.g", grammar, "TParser", "TLexer",
1085324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "a b 3 4 5", debug);
1086324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String expecting =
1087324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"org.antlr.runtime.tree.RewriteCardinalityException: token ID";
1088324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = getFirstLineOfException();
1089324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals(expecting, found);
1090324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1091324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1092324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCardinality2() throws Exception {
1093324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1094324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1095324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1096324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID+ -> ID ID ID ;\n" + // only 2 input IDs
1097324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
1098324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1099324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		execParser("T.g", grammar, "TParser", "TLexer",
1102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				   "a", "a b", debug);
1103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String expecting =
1104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"org.antlr.runtime.tree.RewriteCardinalityException: token ID";
1105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = getFirstLineOfException();
1106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals(expecting, found);
1107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testCardinality3() throws Exception {
1110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID? INT -> ID INT ;\n" +
1114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
1115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		execParser("T.g", grammar, "TParser", "TLexer",
1119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				   "a", "3", debug);
1120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String expecting =
1121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"org.antlr.runtime.tree.RewriteEmptyStreamException: token ID";
1122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = getFirstLineOfException();
1123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals(expecting, found);
1124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testLoopCardinality() throws Exception {
1127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID? INT -> ID+ INT ;\n" +
1131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"op : '+'|'-' ;\n" +
1132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		execParser("T.g", grammar, "TParser", "TLexer",
1136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				   "a", "3", debug);
1137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String expecting =
1138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"org.antlr.runtime.tree.RewriteEarlyExitException";
1139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = getFirstLineOfException();
1140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals(expecting, found);
1141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testWildcard() throws Exception {
1144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID c=. -> $c;\n" +
1148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("T.g", grammar, "TParser", "TLexer",
1152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				    "a", "abc 34", debug);
1153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("34\n", found);
1154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	// E R R O R S
1157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testUnknownRule() throws Exception {
1159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorQueue equeue = new ErrorQueue();
1160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorManager.setErrorListener(equeue);
1161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : INT -> ugh ;\n" +
1166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar g = new Grammar(grammar);
1171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Tool antlr = newTool();
1172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		antlr.setOutputDirectory(null); // write to /dev/null
1173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
1174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		g.setCodeGenerator(generator);
1175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		generator.genRecognizer();
1176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int expectedMsgID = ErrorManager.MSG_UNDEFINED_RULE_REF;
1178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg = "ugh";
1179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg2 = null;
1180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarSemanticsMessage expectedMessage =
1181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
1182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		checkError(equeue, expectedMessage);
1184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testKnownRuleButNotInLHS() throws Exception {
1187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorQueue equeue = new ErrorQueue();
1188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorManager.setErrorListener(equeue);
1189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : INT -> b ;\n" +
1194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : 'b' ;\n" +
1195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar g = new Grammar(grammar);
1200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Tool antlr = newTool();
1201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		antlr.setOutputDirectory(null); // write to /dev/null
1202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
1203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		g.setCodeGenerator(generator);
1204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		generator.genRecognizer();
1205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int expectedMsgID = ErrorManager.MSG_REWRITE_ELEMENT_NOT_PRESENT_ON_LHS;
1207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg = "b";
1208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg2 = null;
1209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarSemanticsMessage expectedMessage =
1210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
1211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		checkError(equeue, expectedMessage);
1213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testUnknownToken() throws Exception {
1216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorQueue equeue = new ErrorQueue();
1217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorManager.setErrorListener(equeue);
1218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : INT -> ICK ;\n" +
1223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar g = new Grammar(grammar);
1228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Tool antlr = newTool();
1229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		antlr.setOutputDirectory(null); // write to /dev/null
1230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
1231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		g.setCodeGenerator(generator);
1232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		generator.genRecognizer();
1233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int expectedMsgID = ErrorManager.MSG_UNDEFINED_TOKEN_REF_IN_REWRITE;
1235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg = "ICK";
1236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg2 = null;
1237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarSemanticsMessage expectedMessage =
1238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
1239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		checkError(equeue, expectedMessage);
1241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testUnknownLabel() throws Exception {
1244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorQueue equeue = new ErrorQueue();
1245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorManager.setErrorListener(equeue);
1246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : INT -> $foo ;\n" +
1251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar g = new Grammar(grammar);
1256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Tool antlr = newTool();
1257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		antlr.setOutputDirectory(null); // write to /dev/null
1258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
1259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		g.setCodeGenerator(generator);
1260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		generator.genRecognizer();
1261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int expectedMsgID = ErrorManager.MSG_UNDEFINED_LABEL_REF_IN_REWRITE;
1263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg = "foo";
1264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg2 = null;
1265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarSemanticsMessage expectedMessage =
1266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
1267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		checkError(equeue, expectedMessage);
1269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testUnknownCharLiteralToken() throws Exception {
1272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorQueue equeue = new ErrorQueue();
1273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorManager.setErrorListener(equeue);
1274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : INT -> 'a' ;\n" +
1279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar g = new Grammar(grammar);
1284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Tool antlr = newTool();
1285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		antlr.setOutputDirectory(null); // write to /dev/null
1286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
1287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		g.setCodeGenerator(generator);
1288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		generator.genRecognizer();
1289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int expectedMsgID = ErrorManager.MSG_UNDEFINED_TOKEN_REF_IN_REWRITE;
1291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg = "'a'";
1292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg2 = null;
1293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarSemanticsMessage expectedMessage =
1294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
1295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		checkError(equeue, expectedMessage);
1297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testUnknownStringLiteralToken() throws Exception {
1300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorQueue equeue = new ErrorQueue();
1301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ErrorManager.setErrorListener(equeue);
1302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar T;\n" +
1305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : INT -> 'foo' ;\n" +
1307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar g = new Grammar(grammar);
1312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Tool antlr = newTool();
1313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		antlr.setOutputDirectory(null); // write to /dev/null
1314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
1315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		g.setCodeGenerator(generator);
1316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		generator.genRecognizer();
1317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int expectedMsgID = ErrorManager.MSG_UNDEFINED_TOKEN_REF_IN_REWRITE;
1319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg = "'foo'";
1320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object expectedArg2 = null;
1321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarSemanticsMessage expectedMessage =
1322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
1323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		checkError(equeue, expectedMessage);
1325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testExtraTokenInSimpleDecl() throws Exception {
1328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar foo;\n" +
1330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {EXPR;}\n" +
1332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;\n" +
1333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
1334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
1338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								  "decl", "int 34 x=1;", debug);
1339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("line 1:4 extraneous input '34' expecting ID\n", this.stderrDuringParse);
1340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(EXPR int x 1)\n", found); // tree gets correct x and 1 tokens
1341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testMissingIDInSimpleDecl() throws Exception {
1344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar foo;\n" +
1346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {EXPR;}\n" +
1348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;\n" +
1349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
1350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
1354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								  "decl", "int =1;", debug);
1355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("line 1:4 missing ID at '='\n", this.stderrDuringParse);
1356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(EXPR int <missing ID> 1)\n", found); // tree gets invented ID token
1357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testMissingSetInSimpleDecl() throws Exception {
1360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar foo;\n" +
1362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"tokens {EXPR;}\n" +
1364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;\n" +
1365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"type : 'int' | 'float' ;\n" +
1366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
1370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								  "decl", "x=1;", debug);
1371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("line 1:0 mismatched input 'x' expecting set null\n", this.stderrDuringParse);
1372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("(EXPR <error: x> x 1)\n", found); // tree gets invented ID token
1373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testMissingTokenGivesErrorNode() throws Exception {
1376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar foo;\n" +
1378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID INT -> ID INT ;\n" +
1380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
1384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								  "a", "abc", debug);
1385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("line 1:3 missing INT at '<EOF>'\n", this.stderrDuringParse);
1386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// doesn't do in-line recovery for sets (yet?)
1387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("abc <missing INT>\n", found);
1388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testExtraTokenGivesErrorNode() throws Exception {
1391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar foo;\n" +
1393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b c -> b c;\n" +
1395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID -> ID ;\n" +
1396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"c : INT -> INT ;\n" +
1397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
1401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								  "a", "abc ick 34", debug);
1402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("line 1:4 extraneous input 'ick' expecting INT\n", this.stderrDuringParse);
1403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("abc 34\n", found);
1404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testMissingFirstTokenGivesErrorNode() throws Exception {
1407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar foo;\n" +
1409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : ID INT -> ID INT ;\n" +
1411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
1415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								  "a", "34", debug);
1416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("line 1:0 missing ID at '34'\n", this.stderrDuringParse);
1417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("<missing ID> 34\n", found);
1418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testMissingFirstTokenGivesErrorNode2() throws Exception {
1421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar foo;\n" +
1423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b c -> b c;\n" +
1425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID -> ID ;\n" +
1426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"c : INT -> INT ;\n" +
1427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
1431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								  "a", "34", debug);
1432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// finds an error at the first token, 34, and re-syncs.
1433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// re-synchronizing does not consume a token because 34 follows
1434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// ref to rule b (start of c). It then matches 34 in c.
1435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("line 1:0 missing ID at '34'\n", this.stderrDuringParse);
1436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("<missing ID> 34\n", found);
1437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Test public void testNoViableAltGivesErrorNode() throws Exception {
1440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String grammar =
1441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"grammar foo;\n" +
1442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"options {output=AST;}\n" +
1443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"a : b -> b | c -> c;\n" +
1444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"b : ID -> ID ;\n" +
1445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"c : INT -> INT ;\n" +
1446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"ID : 'a'..'z'+ ;\n" +
1447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"S : '*' ;\n" +
1448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"INT : '0'..'9'+;\n" +
1449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
1450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
1451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								  "a", "*", debug);
1452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// finds an error at the first token, 34, and re-syncs.
1453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// re-synchronizing does not consume a token because 34 follows
1454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// ref to rule b (start of c). It then matches 34 in c.
1455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("line 1:0 no viable alternative at input '*'\n", this.stderrDuringParse);
1456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		assertEquals("<unexpected: [@0,0:0='*',<6>,1:0], resync=*>\n", found);
1457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
1460