001: /*
002: [The "BSD licence"]
003: Copyright (c) 2005-2006 Terence Parr
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in the
013: documentation and/or other materials provided with the distribution.
014: 3. The name of the author may not be used to endorse or promote products
015: derived from this software without specific prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
018: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
019: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
020: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
021: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028: package org.antlr.test;
029:
030: public class TestAutoAST extends BaseTest {
031: protected boolean debug = false;
032:
033: public void testTokenList() throws Exception {
034: String grammar = "grammar foo;\n" + "options {output=AST;}\n"
035: + "a : ID INT ;\n" + "ID : 'a'..'z'+ ;\n"
036: + "INT : '0'..'9'+;\n"
037: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
038: String found = execParser("foo.g", grammar, "fooParser",
039: "fooLexer", "a", "abc 34", debug);
040: assertEquals("abc 34\n", found);
041: }
042:
043: public void testTokenListInSingleAltBlock() throws Exception {
044: String grammar = "grammar foo;\n" + "options {output=AST;}\n"
045: + "a : (ID INT) ;\n" + "ID : 'a'..'z'+ ;\n"
046: + "INT : '0'..'9'+;\n"
047: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
048: String found = execParser("foo.g", grammar, "fooParser",
049: "fooLexer", "a", "abc 34", debug);
050: assertEquals("abc 34\n", found);
051: }
052:
053: public void testSimpleRootAtOuterLevel() throws Exception {
054: String grammar = "grammar foo;\n" + "options {output=AST;}\n"
055: + "a : ID^ INT ;\n" + "ID : 'a'..'z'+ ;\n"
056: + "INT : '0'..'9'+;\n"
057: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
058: String found = execParser("foo.g", grammar, "fooParser",
059: "fooLexer", "a", "abc 34", debug);
060: assertEquals("(abc 34)\n", found);
061: }
062:
063: public void testSimpleRootAtOuterLevelReverse() throws Exception {
064: String grammar = "grammar T;\n" + "options {output=AST;}\n"
065: + "a : INT ID^ ;\n" + "ID : 'a'..'z'+ ;\n"
066: + "INT : '0'..'9'+;\n"
067: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
068: String found = execParser("T.g", grammar, "TParser", "TLexer",
069: "a", "34 abc", debug);
070: assertEquals("(abc 34)\n", found);
071: }
072:
073: public void testBang() throws Exception {
074: String grammar = "grammar T;\n" + "options {output=AST;}\n"
075: + "a : ID INT! ID! INT ;\n" + "ID : 'a'..'z'+ ;\n"
076: + "INT : '0'..'9'+;\n"
077: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
078: String found = execParser("T.g", grammar, "TParser", "TLexer",
079: "a", "abc 34 dag 4532", debug);
080: assertEquals("abc 4532\n", found);
081: }
082:
083: public void testOptionalThenRoot() throws Exception {
084: String grammar = "grammar T;\n" + "options {output=AST;}\n"
085: + "a : ( ID INT )? ID^ ;\n" + "ID : 'a'..'z'+ ;\n"
086: + "INT : '0'..'9'+;\n"
087: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
088: String found = execParser("T.g", grammar, "TParser", "TLexer",
089: "a", "a 1 b", debug);
090: assertEquals("(b a 1)\n", found);
091: }
092:
093: public void testLabeledStringRoot() throws Exception {
094: String grammar = "grammar T;\n" + "options {output=AST;}\n"
095: + "a : v='void'^ ID ';' ;\n" + "ID : 'a'..'z'+ ;\n"
096: + "INT : '0'..'9'+;\n"
097: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
098: String found = execParser("T.g", grammar, "TParser", "TLexer",
099: "a", "void foo;", debug);
100: assertEquals("(void foo ;)\n", found);
101: }
102:
103: public void testWildcard() throws Exception {
104: String grammar = "grammar T;\n" + "options {output=AST;}\n"
105: + "a : v='void'^ . ';' ;\n" + "ID : 'a'..'z'+ ;\n"
106: + "INT : '0'..'9'+;\n"
107: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
108: String found = execParser("T.g", grammar, "TParser", "TLexer",
109: "a", "void foo;", debug);
110: assertEquals("(void foo ;)\n", found);
111: }
112:
113: public void testWildcardRoot() throws Exception {
114: String grammar = "grammar T;\n" + "options {output=AST;}\n"
115: + "a : v='void' .^ ';' ;\n" + "ID : 'a'..'z'+ ;\n"
116: + "INT : '0'..'9'+;\n"
117: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
118: String found = execParser("T.g", grammar, "TParser", "TLexer",
119: "a", "void foo;", debug);
120: assertEquals("(foo void ;)\n", found);
121: }
122:
123: public void testRootRoot() throws Exception {
124: String grammar = "grammar T;\n" + "options {output=AST;}\n"
125: + "a : ID^ INT^ ID ;\n" + "ID : 'a'..'z'+ ;\n"
126: + "INT : '0'..'9'+;\n"
127: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
128: String found = execParser("T.g", grammar, "TParser", "TLexer",
129: "a", "a 34 c", debug);
130: assertEquals("(34 a c)\n", found);
131: }
132:
133: public void testRootRoot2() throws Exception {
134: String grammar = "grammar T;\n" + "options {output=AST;}\n"
135: + "a : ID INT^ ID^ ;\n" + "ID : 'a'..'z'+ ;\n"
136: + "INT : '0'..'9'+;\n"
137: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
138: String found = execParser("T.g", grammar, "TParser", "TLexer",
139: "a", "a 34 c", debug);
140: assertEquals("(c (34 a))\n", found);
141: }
142:
143: public void testRootThenRootInLoop() throws Exception {
144: String grammar = "grammar T;\n" + "options {output=AST;}\n"
145: + "a : ID^ (INT '*'^ ID)+ ;\n" + "ID : 'a'..'z'+ ;\n"
146: + "INT : '0'..'9'+;\n"
147: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
148: String found = execParser("T.g", grammar, "TParser", "TLexer",
149: "a", "a 34 * b 9 * c", debug);
150: assertEquals("(* (* (a 34) b 9) c)\n", found);
151: }
152:
153: public void testNestedSubrule() throws Exception {
154: String grammar = "grammar T;\n" + "options {output=AST;}\n"
155: + "a : 'void' (({;}ID|INT) ID | 'null' ) ';' ;\n"
156: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
157: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
158: String found = execParser("T.g", grammar, "TParser", "TLexer",
159: "a", "void a b;", debug);
160: assertEquals("void a b ;\n", found);
161: }
162:
163: public void testInvokeRule() throws Exception {
164: String grammar = "grammar T;\n" + "options {output=AST;}\n"
165: + "a : type ID ;\n" + "type : {;}'int' | 'float' ;\n"
166: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
167: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
168: String found = execParser("T.g", grammar, "TParser", "TLexer",
169: "a", "int a", debug);
170: assertEquals("int a\n", found);
171: }
172:
173: public void testInvokeRuleAsRoot() throws Exception {
174: String grammar = "grammar T;\n" + "options {output=AST;}\n"
175: + "a : type^ ID ;\n" + "type : {;}'int' | 'float' ;\n"
176: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
177: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
178: String found = execParser("T.g", grammar, "TParser", "TLexer",
179: "a", "int a", debug);
180: assertEquals("(int a)\n", found);
181: }
182:
183: public void testRuleRootInLoop() throws Exception {
184: String grammar = "grammar T;\n" + "options {output=AST;}\n"
185: + "a : ID ('+'^ ID)* ;\n" + "ID : 'a'..'z'+ ;\n"
186: + "INT : '0'..'9'+;\n"
187: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
188: String found = execParser("T.g", grammar, "TParser", "TLexer",
189: "a", "a+b+c+d", debug);
190: assertEquals("(+ (+ (+ a b) c) d)\n", found);
191: }
192:
193: public void testRuleInvocationRuleRootInLoop() throws Exception {
194: String grammar = "grammar T;\n" + "options {output=AST;}\n"
195: + "a : ID (op^ ID)* ;\n" + "op : {;}'+' | '-' ;\n"
196: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
197: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
198: String found = execParser("T.g", grammar, "TParser", "TLexer",
199: "a", "a+b+c-d", debug);
200: assertEquals("(- (+ (+ a b) c) d)\n", found);
201: }
202:
203: public void testTailRecursion() throws Exception {
204: String grammar = "grammar T;\n" + "options {output=AST;}\n"
205: + "s : a ;\n" + "a : atom ('exp'^ a)? ;\n"
206: + "atom : INT ;\n" + "ID : 'a'..'z'+ ;\n"
207: + "INT : '0'..'9'+;\n"
208: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
209: String found = execParser("T.g", grammar, "TParser", "TLexer",
210: "s", "3 exp 4 exp 5", debug);
211: assertEquals("(exp 3 (exp 4 5))\n", found);
212: }
213:
214: public void testSet() throws Exception {
215: String grammar = "grammar T;\n" + "options {output=AST;}\n"
216: + "a : ID|INT ;\n" + "ID : 'a'..'z'+ ;\n"
217: + "INT : '0'..'9'+;\n"
218: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
219: String found = execParser("T.g", grammar, "TParser", "TLexer",
220: "a", "abc", debug);
221: assertEquals("abc\n", found);
222: }
223:
224: public void testSetRoot() throws Exception {
225: String grammar = "grammar T;\n" + "options {output=AST;}\n"
226: + "a : ('+' | '-')^ ID ;\n" + "ID : 'a'..'z'+ ;\n"
227: + "INT : '0'..'9'+;\n"
228: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
229: String found = execParser("T.g", grammar, "TParser", "TLexer",
230: "a", "+abc", debug);
231: assertEquals("(+ abc)\n", found);
232: }
233:
234: public void testSetAsRuleRootInLoop() throws Exception {
235: String grammar = "grammar T;\n" + "options {output=AST;}\n"
236: + "a : ID (('+'|'-')^ ID)* ;\n" + "ID : 'a'..'z'+ ;\n"
237: + "INT : '0'..'9'+;\n"
238: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
239: String found = execParser("T.g", grammar, "TParser", "TLexer",
240: "a", "a+b-c", debug);
241: assertEquals("(- (+ a b) c)\n", found);
242: }
243:
244: public void testNotSet() throws Exception {
245: String grammar = "grammar T;\n" + "options {output=AST;}\n"
246: + "a : ~ID '+' INT ;\n" + "ID : 'a'..'z'+ ;\n"
247: + "INT : '0'..'9'+;\n"
248: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
249: String found = execParser("T.g", grammar, "TParser", "TLexer",
250: "a", "34+2", debug);
251: assertEquals("34 + 2\n", found);
252: }
253:
254: public void testNotSetRoot() throws Exception {
255: String grammar = "grammar T;\n" + "options {output=AST;}\n"
256: + "a : ~'+'^ INT ;\n" + "ID : 'a'..'z'+ ;\n"
257: + "INT : '0'..'9'+;\n"
258: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
259: String found = execParser("T.g", grammar, "TParser", "TLexer",
260: "a", "34 55", debug);
261: assertEquals("(34 55)\n", found);
262: }
263:
264: public void testNotSetRuleRootInLoop() throws Exception {
265: String grammar = "grammar T;\n" + "options {output=AST;}\n"
266: + "a : INT (~INT^ INT)* ;\n" + "blort : '+' ;\n"
267: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
268: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
269: String found = execParser("T.g", grammar, "TParser", "TLexer",
270: "a", "3+4+5", debug);
271: assertEquals("(+ (+ 3 4) 5)\n", found);
272: }
273:
274: public void testTokenLabelReuse() throws Exception {
275: // check for compilation problem due to multiple defines
276: String grammar = "grammar T;\n"
277: + "options {output=AST;}\n"
278: + "a : id=ID id=ID {System.out.print(\"2nd id=\"+$id.text+';');} ;\n"
279: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
280: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
281: String found = execParser("T.g", grammar, "TParser", "TLexer",
282: "a", "a b", debug);
283: assertEquals("2nd id=b;a b\n", found);
284: }
285:
286: public void testTokenLabelReuse2() throws Exception {
287: // check for compilation problem due to multiple defines
288: String grammar = "grammar T;\n"
289: + "options {output=AST;}\n"
290: + "a : id=ID id=ID^ {System.out.print(\"2nd id=\"+$id.text+';');} ;\n"
291: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
292: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
293: String found = execParser("T.g", grammar, "TParser", "TLexer",
294: "a", "a b", debug);
295: assertEquals("2nd id=b;(b a)\n", found);
296: }
297:
298: public void testTokenListLabelReuse() throws Exception {
299: // check for compilation problem due to multiple defines
300: // make sure ids has both ID tokens
301: String grammar = "grammar T;\n"
302: + "options {output=AST;}\n"
303: + "a : ids+=ID ids+=ID {System.out.print(\"id list=\"+$ids+';');} ;\n"
304: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
305: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
306: String found = execParser("T.g", grammar, "TParser", "TLexer",
307: "a", "a b", debug);
308: String expecting = "id list=[[@0,0:0='a',<4>,1:0], [@2,2:2='b',<4>,1:2]];a b\n";
309: assertEquals(expecting, found);
310: }
311:
312: public void testTokenListLabelReuse2() throws Exception {
313: // check for compilation problem due to multiple defines
314: // make sure ids has both ID tokens
315: String grammar = "grammar T;\n"
316: + "options {output=AST;}\n"
317: + "a : ids+=ID^ ids+=ID {System.out.print(\"id list=\"+$ids+';');} ;\n"
318: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
319: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
320: String found = execParser("T.g", grammar, "TParser", "TLexer",
321: "a", "a b", debug);
322: String expecting = "id list=[[@0,0:0='a',<4>,1:0], [@2,2:2='b',<4>,1:2]];(a b)\n";
323: assertEquals(expecting, found);
324: }
325:
326: public void testTokenListLabelRuleRoot() throws Exception {
327: String grammar = "grammar T;\n" + "options {output=AST;}\n"
328: + "a : id+=ID^ ;\n" + "ID : 'a'..'z'+ ;\n"
329: + "INT : '0'..'9'+;\n"
330: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
331: String found = execParser("T.g", grammar, "TParser", "TLexer",
332: "a", "a", debug);
333: assertEquals("a\n", found);
334: }
335:
336: public void testTokenListLabelBang() throws Exception {
337: String grammar = "grammar T;\n" + "options {output=AST;}\n"
338: + "a : id+=ID! ;\n" + "ID : 'a'..'z'+ ;\n"
339: + "INT : '0'..'9'+;\n"
340: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
341: String found = execParser("T.g", grammar, "TParser", "TLexer",
342: "a", "a", debug);
343: assertEquals("nil\n", found);
344: }
345:
346: public void testRuleListLabel() throws Exception {
347: String grammar = "grammar T;\n"
348: + "options {output=AST;}\n"
349: + "a : x+=b x+=b {"
350: + "Tree t=(Tree)$x.get(1);"
351: + "System.out.print(\"2nd x=\"+t.toStringTree()+';');} ;\n"
352: + "b : ID;\n" + "ID : 'a'..'z'+ ;\n"
353: + "INT : '0'..'9'+;\n"
354: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
355: String found = execParser("T.g", grammar, "TParser", "TLexer",
356: "a", "a b", debug);
357: assertEquals("2nd x=b;a b\n", found);
358: }
359:
360: public void testRuleListLabelRuleRoot() throws Exception {
361: String grammar = "grammar T;\n"
362: + "options {output=AST;}\n"
363: + "a : ( x+=b^ )+ {"
364: + "System.out.print(\"x=\"+((CommonTree)$x.get(1)).toStringTree()+';');} ;\n"
365: + "b : ID;\n" + "ID : 'a'..'z'+ ;\n"
366: + "INT : '0'..'9'+;\n"
367: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
368: String found = execParser("T.g", grammar, "TParser", "TLexer",
369: "a", "a b", debug);
370: assertEquals("x=(b a);(b a)\n", found);
371: }
372:
373: public void testRuleListLabelBang() throws Exception {
374: String grammar = "grammar T;\n"
375: + "options {output=AST;}\n"
376: + "a : x+=b! x+=b {"
377: + "System.out.print(\"1st x=\"+((CommonTree)$x.get(0)).toStringTree()+';');} ;\n"
378: + "b : ID;\n" + "ID : 'a'..'z'+ ;\n"
379: + "INT : '0'..'9'+;\n"
380: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
381: String found = execParser("T.g", grammar, "TParser", "TLexer",
382: "a", "a b", debug);
383: assertEquals("1st x=a;b\n", found);
384: }
385:
386: public void testComplicatedMelange() throws Exception {
387: // check for compilation problem
388: String grammar = "grammar T;\n" + "options {output=AST;}\n"
389: + "a : A b=B b=B c+=C c+=C D {$D.text;} ;\n"
390: + "A : 'a' ;\n" + "B : 'b' ;\n" + "C : 'c' ;\n"
391: + "D : 'd' ;\n"
392: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
393: String found = execParser("T.g", grammar, "TParser", "TLexer",
394: "a", "a b b c c d", debug);
395: assertEquals("a b b c c d\n", found);
396: }
397:
398: public void testReturnValueWithAST() throws Exception {
399: String grammar = "grammar foo;\n"
400: + "options {output=AST;}\n"
401: + "a : ID b {System.out.println($b.i);} ;\n"
402: + "b returns [int i] : INT {$i=Integer.parseInt($INT.text);} ;\n"
403: + "ID : 'a'..'z'+ ;\n" + "INT : '0'..'9'+;\n"
404: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
405: String found = execParser("foo.g", grammar, "fooParser",
406: "fooLexer", "a", "abc 34", debug);
407: assertEquals("34\nabc 34\n", found);
408: }
409:
410: public void testSetLoop() throws Exception {
411: String grammar = "grammar T;\n" + "options { output=AST; }\n"
412: + "r : (INT|ID)+ ; \n" + "ID : 'a'..'z' + ;\n"
413: + "INT : '0'..'9' +;\n"
414: + "WS: (' ' | '\\n' | '\\t')+ {$channel = HIDDEN;};\n";
415: String found = execParser("T.g", grammar, "TParser", "TLexer",
416: "r", "abc 34 d", debug);
417: assertEquals("abc 34 d\n", found);
418: }
419:
420: // S U P P O R T
421:
422: public void _test() throws Exception {
423: String grammar = "grammar T;\n" + "options {output=AST;}\n"
424: + "a : ;\n" + "ID : 'a'..'z'+ ;\n"
425: + "INT : '0'..'9'+;\n"
426: + "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
427: String found = execParser("T.g", grammar, "TParser", "TLexer",
428: "a", "abc 34", debug);
429: assertEquals("\n", found);
430: }
431:
432: }
|