mirror of
https://github.com/marcin-szczepanski/jFuzzyLogic.git
synced 2024-08-16 18:06:57 +02:00
1481 lines
46 KiB
Java
1481 lines
46 KiB
Java
/*
|
|
[The "BSD licence"]
|
|
Copyright (c) 2005-2006 Terence Parr
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
3. The name of the author may not be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
package org.antlr.test;
|
|
|
|
import org.antlr.tool.ErrorManager;
|
|
import org.antlr.tool.GrammarSemanticsMessage;
|
|
import org.antlr.tool.Message;
|
|
import org.antlr.tool.Grammar;
|
|
import org.antlr.Tool;
|
|
import org.antlr.codegen.CodeGenerator;
|
|
|
|
public class TestRewriteAST extends BaseTest {
|
|
protected boolean debug = false;
|
|
|
|
public void testDelete() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID INT -> ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc 34", debug);
|
|
assertEquals("", found);
|
|
}
|
|
|
|
public void testSingleToken() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID -> ID;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("abc\n", found);
|
|
}
|
|
|
|
public void testSingleTokenToNewNode() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID -> ID[\"x\"];\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("x\n", found);
|
|
}
|
|
|
|
public void testSingleTokenToNewNodeRoot() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID -> ^(ID[\"x\"] INT);\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("(x INT)\n", found);
|
|
}
|
|
|
|
public void testSingleTokenToNewNode2() throws Exception {
|
|
// Allow creation of new nodes w/o args.
|
|
String grammar =
|
|
"grammar TT;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID -> ID[ ];\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("TT.g", grammar, "TTParser", "TTLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("ID\n", found);
|
|
}
|
|
|
|
public void testSingleCharLiteral() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : 'c' -> 'c';\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "c", debug);
|
|
assertEquals("c\n", found);
|
|
}
|
|
|
|
public void testSingleStringLiteral() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : 'ick' -> 'ick';\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "ick", debug);
|
|
assertEquals("ick\n", found);
|
|
}
|
|
|
|
public void testSingleRule() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : b -> b;\n" +
|
|
"b : ID ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("abc\n", found);
|
|
}
|
|
|
|
public void testReorderTokens() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID INT -> INT ID;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc 34", debug);
|
|
assertEquals("34 abc\n", found);
|
|
}
|
|
|
|
public void testReorderTokenAndRule() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : b INT -> INT b;\n" +
|
|
"b : ID ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc 34", debug);
|
|
assertEquals("34 abc\n", found);
|
|
}
|
|
|
|
public void testTokenTree() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID INT -> ^(INT ID);\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc 34", debug);
|
|
assertEquals("(34 abc)\n", found);
|
|
}
|
|
|
|
public void testTokenTreeAfterOtherStuff() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : 'void' ID INT -> 'void' ^(INT ID);\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "void abc 34", debug);
|
|
assertEquals("void (34 abc)\n", found);
|
|
}
|
|
|
|
public void testNestedTokenTreeWithOuterLoop() throws Exception {
|
|
// verify that ID and INT both iterate over outer index variable
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {DUH;}\n" +
|
|
"a : ID INT ID INT -> ^( DUH ID ^( DUH INT) )+ ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a 1 b 2", debug);
|
|
assertEquals("(DUH a (DUH 1)) (DUH b (DUH 2))\n", found);
|
|
}
|
|
|
|
public void testOptionalSingleToken() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID -> ID? ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("abc\n", found);
|
|
}
|
|
|
|
public void testClosureSingleToken() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID ID -> ID* ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testPositiveClosureSingleToken() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID ID -> ID+ ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testOptionalSingleRule() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : b -> b?;\n" +
|
|
"b : ID ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("abc\n", found);
|
|
}
|
|
|
|
public void testClosureSingleRule() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : b b -> b*;\n" +
|
|
"b : ID ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testClosureOfLabel() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : x+=b x+=b -> $x*;\n" +
|
|
"b : ID ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testOptionalLabelNoListLabel() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : (x=ID)? -> $x?;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a", debug);
|
|
assertEquals("a\n", found);
|
|
}
|
|
|
|
public void testPositiveClosureSingleRule() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : b b -> b+;\n" +
|
|
"b : ID ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testSinglePredicateT() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID -> {true}? ID -> ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("abc\n", found);
|
|
}
|
|
|
|
public void testSinglePredicateF() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID -> {false}? ID -> ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("", found);
|
|
}
|
|
|
|
public void testMultiplePredicate() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID INT -> {false}? ID\n" +
|
|
" -> {true}? INT\n" +
|
|
" -> \n" +
|
|
" ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a 2", debug);
|
|
assertEquals("2\n", found);
|
|
}
|
|
|
|
public void testMultiplePredicateTrees() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID INT -> {false}? ^(ID INT)\n" +
|
|
" -> {true}? ^(INT ID)\n" +
|
|
" -> ID\n" +
|
|
" ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a 2", debug);
|
|
assertEquals("(2 a)\n", found);
|
|
}
|
|
|
|
public void testSimpleTree() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : op INT -> ^(op INT);\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "-34", debug);
|
|
assertEquals("(- 34)\n", found);
|
|
}
|
|
|
|
public void testSimpleTree2() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : op INT -> ^(INT op);\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "+ 34", debug);
|
|
assertEquals("(34 +)\n", found);
|
|
}
|
|
|
|
|
|
public void testNestedTrees() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : 'var' (ID ':' type ';')+ -> ^('var' ^(':' ID type)+) ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "var a:int; b:float;", debug);
|
|
assertEquals("(var (: a int) (: b float))\n", found);
|
|
}
|
|
|
|
public void testImaginaryTokenCopy() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {VAR;}\n" +
|
|
"a : ID (',' ID)*-> ^(VAR ID)+ ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a,b,c", debug);
|
|
assertEquals("(VAR a) (VAR b) (VAR c)\n", found);
|
|
}
|
|
|
|
public void testTokenUnreferencedOnLeftButDefined() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {VAR;}\n" +
|
|
"a : b -> ID ;\n" +
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a", debug);
|
|
assertEquals("ID\n", found);
|
|
}
|
|
|
|
public void testImaginaryTokenCopySetText() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {VAR;}\n" +
|
|
"a : ID (',' ID)*-> ^(VAR[\"var\"] ID)+ ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a,b,c", debug);
|
|
assertEquals("(var a) (var b) (var c)\n", found);
|
|
}
|
|
|
|
public void testImaginaryTokenNoCopyFromToken() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "{a b c}", debug);
|
|
assertEquals("({ a b c)\n", found);
|
|
}
|
|
|
|
public void testImaginaryTokenNoCopyFromTokenSetText() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : lc='{' ID+ '}' -> ^(BLOCK[$lc,\"block\"] ID+) ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "{a b c}", debug);
|
|
assertEquals("(block a b c)\n", found);
|
|
}
|
|
|
|
public void testMixedRewriteAndAutoAST() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : b b^ ;\n" + // 2nd b matches only an INT; can make it root
|
|
"b : ID INT -> INT ID\n" +
|
|
" | INT\n" +
|
|
" ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a 1 2", debug);
|
|
assertEquals("(2 1 a)\n", found);
|
|
}
|
|
|
|
public void testSubruleWithRewrite() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : b b ;\n" +
|
|
"b : (ID INT -> INT ID | INT INT -> INT+ )\n" +
|
|
" ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a 1 2 3", debug);
|
|
assertEquals("1 a 2 3\n", found);
|
|
}
|
|
|
|
public void testSubruleWithRewrite2() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {TYPE;}\n" +
|
|
"a : b b ;\n" +
|
|
"b : 'int'\n" +
|
|
" ( ID -> ^(TYPE 'int' ID)\n" +
|
|
" | ID '=' INT -> ^(TYPE 'int' ID INT)\n" +
|
|
" )\n" +
|
|
" ';'\n" +
|
|
" ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "int a; int b=3;", debug);
|
|
assertEquals("(TYPE int a) (TYPE int b 3)\n", found);
|
|
}
|
|
|
|
public void testNestedRewriteShutsOffAutoAST() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : b b ;\n" +
|
|
"b : ID ( ID (last=ID -> $last)+ ) ';'\n" + // get last ID
|
|
" | INT\n" + // should still get auto AST construction
|
|
" ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b c d; 42", debug);
|
|
assertEquals("d 42\n", found);
|
|
}
|
|
|
|
public void testRewriteActions() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : atom -> ^({adaptor.create(INT,\"9\")} atom) ;\n" +
|
|
"atom : INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "3", debug);
|
|
assertEquals("(9 3)\n", found);
|
|
}
|
|
|
|
public void testRewriteActions2() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : atom -> {adaptor.create(INT,\"9\")} atom ;\n" +
|
|
"atom : INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "3", debug);
|
|
assertEquals("9 3\n", found);
|
|
}
|
|
|
|
public void testRefToOldValue() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : (atom -> atom) (op='+' r=atom -> ^($op $a $r) )* ;\n" +
|
|
"atom : INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "3+4+5", debug);
|
|
assertEquals("(+ (+ 3 4) 5)\n", found);
|
|
}
|
|
|
|
public void testCopySemanticsForRules() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : atom -> ^(atom atom) ;\n" + // NOT CYCLE! (dup atom)
|
|
"atom : INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "3", debug);
|
|
assertEquals("(3 3)\n", found);
|
|
}
|
|
|
|
public void testCopySemanticsForRules2() throws Exception {
|
|
// copy type as a root for each invocation of (...)+ in rewrite
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : type ID (',' ID)* ';' -> ^(type ID)+ ;\n" +
|
|
"type : 'int' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "int a,b,c;", debug);
|
|
assertEquals("(int a) (int b) (int c)\n", found);
|
|
}
|
|
|
|
public void testCopySemanticsForRules3() throws Exception {
|
|
// copy type *and* modifier even though it's optional
|
|
// for each invocation of (...)+ in rewrite
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : modifier? type ID (',' ID)* ';' -> ^(type modifier? ID)+ ;\n" +
|
|
"type : 'int' ;\n" +
|
|
"modifier : 'public' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "public int a,b,c;", debug);
|
|
assertEquals("(int public a) (int public b) (int public c)\n", found);
|
|
}
|
|
|
|
public void testCopySemanticsForRules3Double() throws Exception {
|
|
// copy type *and* modifier even though it's optional
|
|
// for each invocation of (...)+ in rewrite
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : modifier? type ID (',' ID)* ';' -> ^(type modifier? ID)+ ^(type modifier? ID)+ ;\n" +
|
|
"type : 'int' ;\n" +
|
|
"modifier : 'public' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "public int a,b,c;", debug);
|
|
assertEquals("(int public a) (int public b) (int public c) (int public a) (int public b) (int public c)\n", found);
|
|
}
|
|
|
|
public void testCopySemanticsForRules4() throws Exception {
|
|
// copy type *and* modifier even though it's optional
|
|
// for each invocation of (...)+ in rewrite
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {MOD;}\n" +
|
|
"a : modifier? type ID (',' ID)* ';' -> ^(type ^(MOD modifier)? ID)+ ;\n" +
|
|
"type : 'int' ;\n" +
|
|
"modifier : 'public' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "public int a,b,c;", debug);
|
|
assertEquals("(int (MOD public) a) (int (MOD public) b) (int (MOD public) c)\n", found);
|
|
}
|
|
|
|
public void testCopySemanticsLists() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {MOD;}\n" +
|
|
"a : ID (',' ID)* ';' -> ID+ ID+ ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a,b,c;", debug);
|
|
assertEquals("a b c a b c\n", found);
|
|
}
|
|
|
|
public void testCopyRuleLabel() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x=b -> $x $x;\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a", debug);
|
|
assertEquals("a a\n", found);
|
|
}
|
|
|
|
public void testCopyRuleLabel2() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x=b -> ^($x $x);\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a", debug);
|
|
assertEquals("(a a)\n", found);
|
|
}
|
|
|
|
public void testQueueingOfTokens() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : 'int' ID (',' ID)* ';' -> ^('int' ID+) ;\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "int a,b,c;", debug);
|
|
assertEquals("(int a b c)\n", found);
|
|
}
|
|
|
|
public void testCopyOfTokens() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : 'int' ID ';' -> 'int' ID 'int' ID ;\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "int a;", debug);
|
|
assertEquals("int a int a\n", found);
|
|
}
|
|
|
|
public void testTokenCopyInLoop() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : 'int' ID (',' ID)* ';' -> ^('int' ID)+ ;\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "int a,b,c;", debug);
|
|
assertEquals("(int a) (int b) (int c)\n", found);
|
|
}
|
|
|
|
public void testTokenCopyInLoopAgainstTwoOthers() throws Exception {
|
|
// must smear 'int' copies across as root of multiple trees
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : 'int' ID ':' INT (',' ID ':' INT)* ';' -> ^('int' ID INT)+ ;\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "int a:1,b:2,c:3;", debug);
|
|
assertEquals("(int a 1) (int b 2) (int c 3)\n", found);
|
|
}
|
|
|
|
public void testListRefdOneAtATime() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID+ -> ID ID ID ;\n" + // works if 3 input IDs
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b c", debug);
|
|
assertEquals("a b c\n", found);
|
|
}
|
|
|
|
public void testSplitListWithLabels() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {VAR;}\n"+
|
|
"a : first=ID others+=ID* -> $first VAR $others+ ;\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b c", debug);
|
|
assertEquals("a VAR b c\n", found);
|
|
}
|
|
|
|
public void testComplicatedMelange() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : A A b=B B b=B c+=C C c+=C D {String s=$D.text;} -> A+ B+ C+ D ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"A : 'a' ;\n" +
|
|
"B : 'b' ;\n" +
|
|
"C : 'c' ;\n" +
|
|
"D : 'd' ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a a b b b c c c d", debug);
|
|
assertEquals("a a b b b c c c d\n", found);
|
|
}
|
|
|
|
public void testRuleLabel() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x=b -> $x;\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a", debug);
|
|
assertEquals("a\n", found);
|
|
}
|
|
|
|
public void testAmbiguousRule() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID a -> a | INT ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT: '0'..'9'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc 34", debug);
|
|
assertEquals("34\n", found);
|
|
}
|
|
|
|
public void testWeirdRuleRef() throws Exception {
|
|
ErrorQueue equeue = new ErrorQueue();
|
|
ErrorManager.setErrorListener(equeue);
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID a -> $a | INT ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT: '0'..'9'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
|
|
Grammar g = new Grammar(grammar);
|
|
Tool antlr = newTool();
|
|
antlr.setOutputDirectory(null); // write to /dev/null
|
|
CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
|
|
g.setCodeGenerator(generator);
|
|
generator.genRecognizer();
|
|
|
|
// $a is ambig; is it previous root or ref to a ref in alt?
|
|
assertEquals("unexpected errors: "+equeue, 1, equeue.errors.size());
|
|
}
|
|
|
|
public void testRuleListLabel() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x+=b x+=b -> $x+;\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testRuleListLabel2() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x+=b x+=b -> $x $x*;\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testOptional() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x=b (y=b)? -> $x $y?;\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a", debug);
|
|
assertEquals("a\n", found);
|
|
}
|
|
|
|
public void testOptional2() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x=ID (y=b)? -> $x $y?;\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testOptional3() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x=ID (y=b)? -> ($x $y)?;\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testOptional4() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x+=ID (y=b)? -> ($x $y)?;\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("a b\n", found);
|
|
}
|
|
|
|
public void testOptional5() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : ID -> ID? ;\n"+ // match an ID to optional ID
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a", debug);
|
|
assertEquals("a\n", found);
|
|
}
|
|
|
|
public void testArbitraryExprType() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : x+=b x+=b -> {new CommonTree()};\n"+
|
|
"b : ID ;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
assertEquals("", found);
|
|
}
|
|
|
|
public void testSet() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options { output = AST; } \n" +
|
|
"a: (INT|ID)+ -> INT+ ID+ ;\n" +
|
|
"INT: '0'..'9'+;\n" +
|
|
"ID : 'a'..'z'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "2 a 34 de", debug);
|
|
assertEquals("2 34 a de\n", found);
|
|
}
|
|
|
|
public void testSet2() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options { output = AST; } \n" +
|
|
"a: (INT|ID) -> INT? ID? ;\n" +
|
|
"INT: '0'..'9'+;\n" +
|
|
"ID : 'a'..'z'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "2", debug);
|
|
assertEquals("2\n", found);
|
|
}
|
|
|
|
public void testSetWithLabel() throws Exception {
|
|
// FAILS. The should probably generate a warning from antlr
|
|
// See http://www.antlr.org:8888/browse/ANTLR-162
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options { output = AST; } \n" +
|
|
"a : x=(INT|ID) -> $x ;\n" +
|
|
"INT: '0'..'9'+;\n" +
|
|
"ID : 'a'..'z'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "2", debug);
|
|
assertEquals("2\n", found);
|
|
}
|
|
|
|
public void testRewriteAction() throws Exception {
|
|
String grammar =
|
|
"grammar T; \n" +
|
|
"options { output = AST; }\n" +
|
|
"tokens { FLOAT; }\n" +
|
|
"r\n" +
|
|
" : INT -> {new CommonTree(new CommonToken(FLOAT,$INT.text+\".0\"))} \n" +
|
|
" ; \n" +
|
|
"INT : '0'..'9'+; \n" +
|
|
"WS: (' ' | '\\n' | '\\t')+ {$channel = HIDDEN;}; \n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"r", "25", debug);
|
|
assertEquals("25.0\n", found);
|
|
}
|
|
|
|
public void testOptionalSubruleWithoutRealElements() throws Exception {
|
|
// copy type *and* modifier even though it's optional
|
|
// for each invocation of (...)+ in rewrite
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;} \n" +
|
|
"tokens {PARMS;} \n" +
|
|
"\n" +
|
|
"modulo \n" +
|
|
" : 'modulo' ID ('(' parms+ ')')? -> ^('modulo' ID ^(PARMS parms+)?) \n" +
|
|
" ; \n" +
|
|
"parms : '#'|ID; \n" +
|
|
"ID : ('a'..'z' | 'A'..'Z')+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"modulo", "modulo abc (x y #)", debug);
|
|
assertEquals("(modulo abc (PARMS x y #))\n", found);
|
|
}
|
|
|
|
// C A R D I N A L I T Y I S S U E S
|
|
|
|
public void testCardinality() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {BLOCK;}\n" +
|
|
"a : ID ID INT INT INT -> (ID INT)+;\n"+
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+; \n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b 3 4 5", debug);
|
|
String expecting =
|
|
"org.antlr.runtime.tree.RewriteCardinalityException: token ID";
|
|
String found = getFirstLineOfException();
|
|
assertEquals(expecting, found);
|
|
}
|
|
|
|
public void testCardinality2() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID+ -> ID ID ID ;\n" + // only 2 input IDs
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "a b", debug);
|
|
String expecting =
|
|
"org.antlr.runtime.tree.RewriteCardinalityException: token ID";
|
|
String found = getFirstLineOfException();
|
|
assertEquals(expecting, found);
|
|
}
|
|
|
|
public void testCardinality3() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID? INT -> ID INT ;\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "3", debug);
|
|
String expecting =
|
|
"org.antlr.runtime.tree.RewriteEmptyStreamException: token ID";
|
|
String found = getFirstLineOfException();
|
|
assertEquals(expecting, found);
|
|
}
|
|
|
|
public void testLoopCardinality() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID? INT -> ID+ INT ;\n" +
|
|
"op : '+'|'-' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "3", debug);
|
|
String expecting =
|
|
"org.antlr.runtime.tree.RewriteEarlyExitException";
|
|
String found = getFirstLineOfException();
|
|
assertEquals(expecting, found);
|
|
}
|
|
|
|
public void testWildcard() throws Exception {
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID c=. -> $c;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("T.g", grammar, "TParser", "TLexer",
|
|
"a", "abc 34", debug);
|
|
assertEquals("34\n", found);
|
|
}
|
|
|
|
// E R R O R S
|
|
|
|
public void testUnknownRule() throws Exception {
|
|
ErrorQueue equeue = new ErrorQueue();
|
|
ErrorManager.setErrorListener(equeue);
|
|
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : INT -> ugh ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
|
|
Grammar g = new Grammar(grammar);
|
|
Tool antlr = newTool();
|
|
antlr.setOutputDirectory(null); // write to /dev/null
|
|
CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
|
|
g.setCodeGenerator(generator);
|
|
generator.genRecognizer();
|
|
|
|
int expectedMsgID = ErrorManager.MSG_UNDEFINED_RULE_REF;
|
|
Object expectedArg = "ugh";
|
|
Object expectedArg2 = null;
|
|
GrammarSemanticsMessage expectedMessage =
|
|
new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
|
|
|
|
checkError(equeue, expectedMessage);
|
|
}
|
|
|
|
public void testKnownRuleButNotInLHS() throws Exception {
|
|
ErrorQueue equeue = new ErrorQueue();
|
|
ErrorManager.setErrorListener(equeue);
|
|
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : INT -> b ;\n" +
|
|
"b : 'b' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
|
|
Grammar g = new Grammar(grammar);
|
|
Tool antlr = newTool();
|
|
antlr.setOutputDirectory(null); // write to /dev/null
|
|
CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
|
|
g.setCodeGenerator(generator);
|
|
generator.genRecognizer();
|
|
|
|
int expectedMsgID = ErrorManager.MSG_REWRITE_ELEMENT_NOT_PRESENT_ON_LHS;
|
|
Object expectedArg = "b";
|
|
Object expectedArg2 = null;
|
|
GrammarSemanticsMessage expectedMessage =
|
|
new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
|
|
|
|
checkError(equeue, expectedMessage);
|
|
}
|
|
|
|
public void testUnknownToken() throws Exception {
|
|
ErrorQueue equeue = new ErrorQueue();
|
|
ErrorManager.setErrorListener(equeue);
|
|
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : INT -> ICK ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
|
|
Grammar g = new Grammar(grammar);
|
|
Tool antlr = newTool();
|
|
antlr.setOutputDirectory(null); // write to /dev/null
|
|
CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
|
|
g.setCodeGenerator(generator);
|
|
generator.genRecognizer();
|
|
|
|
int expectedMsgID = ErrorManager.MSG_UNDEFINED_TOKEN_REF_IN_REWRITE;
|
|
Object expectedArg = "ICK";
|
|
Object expectedArg2 = null;
|
|
GrammarSemanticsMessage expectedMessage =
|
|
new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
|
|
|
|
checkError(equeue, expectedMessage);
|
|
}
|
|
|
|
public void testUnknownLabel() throws Exception {
|
|
ErrorQueue equeue = new ErrorQueue();
|
|
ErrorManager.setErrorListener(equeue);
|
|
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : INT -> $foo ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
|
|
Grammar g = new Grammar(grammar);
|
|
Tool antlr = newTool();
|
|
antlr.setOutputDirectory(null); // write to /dev/null
|
|
CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
|
|
g.setCodeGenerator(generator);
|
|
generator.genRecognizer();
|
|
|
|
int expectedMsgID = ErrorManager.MSG_UNDEFINED_LABEL_REF_IN_REWRITE;
|
|
Object expectedArg = "foo";
|
|
Object expectedArg2 = null;
|
|
GrammarSemanticsMessage expectedMessage =
|
|
new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
|
|
|
|
checkError(equeue, expectedMessage);
|
|
}
|
|
|
|
public void testUnknownCharLiteralToken() throws Exception {
|
|
ErrorQueue equeue = new ErrorQueue();
|
|
ErrorManager.setErrorListener(equeue);
|
|
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : INT -> 'a' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
|
|
Grammar g = new Grammar(grammar);
|
|
Tool antlr = newTool();
|
|
antlr.setOutputDirectory(null); // write to /dev/null
|
|
CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
|
|
g.setCodeGenerator(generator);
|
|
generator.genRecognizer();
|
|
|
|
int expectedMsgID = ErrorManager.MSG_UNDEFINED_TOKEN_REF_IN_REWRITE;
|
|
Object expectedArg = "'a'";
|
|
Object expectedArg2 = null;
|
|
GrammarSemanticsMessage expectedMessage =
|
|
new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
|
|
|
|
checkError(equeue, expectedMessage);
|
|
}
|
|
|
|
public void testUnknownStringLiteralToken() throws Exception {
|
|
ErrorQueue equeue = new ErrorQueue();
|
|
ErrorManager.setErrorListener(equeue);
|
|
|
|
String grammar =
|
|
"grammar T;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : INT -> 'foo' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
|
|
Grammar g = new Grammar(grammar);
|
|
Tool antlr = newTool();
|
|
antlr.setOutputDirectory(null); // write to /dev/null
|
|
CodeGenerator generator = new CodeGenerator(antlr, g, "Java");
|
|
g.setCodeGenerator(generator);
|
|
generator.genRecognizer();
|
|
|
|
int expectedMsgID = ErrorManager.MSG_UNDEFINED_TOKEN_REF_IN_REWRITE;
|
|
Object expectedArg = "'foo'";
|
|
Object expectedArg2 = null;
|
|
GrammarSemanticsMessage expectedMessage =
|
|
new GrammarSemanticsMessage(expectedMsgID, g, null, expectedArg, expectedArg2);
|
|
|
|
checkError(equeue, expectedMessage);
|
|
}
|
|
|
|
public void testExtraTokenInSimpleDecl() throws Exception {
|
|
String grammar =
|
|
"grammar foo;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {EXPR;}\n" +
|
|
"decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
|
|
"decl", "int 34 x=1;", debug);
|
|
assertEquals("line 1:4 extraneous input '34' expecting ID\n", this.stderr);
|
|
assertEquals("(EXPR int x 1)\n", found); // tree gets correct x and 1 tokens
|
|
}
|
|
|
|
public void testMissingIDInSimpleDecl() throws Exception {
|
|
String grammar =
|
|
"grammar foo;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {EXPR;}\n" +
|
|
"decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
|
|
"decl", "int =1;", debug);
|
|
assertEquals("line 1:4 missing ID at '='\n", this.stderr);
|
|
assertEquals("(EXPR int <missing ID> 1)\n", found); // tree gets invented ID token
|
|
}
|
|
|
|
public void testMissingSetInSimpleDecl() throws Exception {
|
|
String grammar =
|
|
"grammar foo;\n" +
|
|
"options {output=AST;}\n" +
|
|
"tokens {EXPR;}\n" +
|
|
"decl : type ID '=' INT ';' -> ^(EXPR type ID INT) ;\n" +
|
|
"type : 'int' | 'float' ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
|
|
"decl", "x=1;", debug);
|
|
assertEquals("line 1:0 mismatched input 'x' expecting set null\n", this.stderr);
|
|
assertEquals("(EXPR <error: x> x 1)\n", found); // tree gets invented ID token
|
|
}
|
|
|
|
public void testMissingTokenGivesErrorNode() throws Exception {
|
|
String grammar =
|
|
"grammar foo;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID INT -> ID INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
|
|
"a", "abc", debug);
|
|
assertEquals("line 0:-1 missing INT at '<EOF>'\n", this.stderr);
|
|
// doesn't do in-line recovery for sets (yet?)
|
|
assertEquals("abc <missing INT>\n", found);
|
|
}
|
|
|
|
public void testExtraTokenGivesErrorNode() throws Exception {
|
|
String grammar =
|
|
"grammar foo;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : b c -> b c;\n" +
|
|
"b : ID -> ID ;\n" +
|
|
"c : INT -> INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
|
|
"a", "abc ick 34", debug);
|
|
assertEquals("line 1:4 extraneous input 'ick' expecting INT\n", this.stderr);
|
|
assertEquals("abc 34\n", found);
|
|
}
|
|
|
|
public void testMissingFirstTokenGivesErrorNode() throws Exception {
|
|
String grammar =
|
|
"grammar foo;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : ID INT -> ID INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
|
|
"a", "34", debug);
|
|
assertEquals("line 1:0 missing ID at '34'\n", this.stderr);
|
|
assertEquals("<missing ID> 34\n", found);
|
|
}
|
|
|
|
public void testMissingFirstTokenGivesErrorNode2() throws Exception {
|
|
String grammar =
|
|
"grammar foo;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : b c -> b c;\n" +
|
|
"b : ID -> ID ;\n" +
|
|
"c : INT -> INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
|
|
"a", "34", debug);
|
|
// finds an error at the first token, 34, and re-syncs.
|
|
// re-synchronizing does not consume a token because 34 follows
|
|
// ref to rule b (start of c). It then matches 34 in c.
|
|
assertEquals("line 1:0 missing ID at '34'\n", this.stderr);
|
|
assertEquals("<missing ID> 34\n", found);
|
|
}
|
|
|
|
public void testNoViableAltGivesErrorNode() throws Exception {
|
|
String grammar =
|
|
"grammar foo;\n" +
|
|
"options {output=AST;}\n" +
|
|
"a : b -> b | c -> c;\n" +
|
|
"b : ID -> ID ;\n" +
|
|
"c : INT -> INT ;\n" +
|
|
"ID : 'a'..'z'+ ;\n" +
|
|
"S : '*' ;\n" +
|
|
"INT : '0'..'9'+;\n" +
|
|
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
|
|
String found = execParser("foo.g", grammar, "fooParser", "fooLexer",
|
|
"a", "*", debug);
|
|
// finds an error at the first token, 34, and re-syncs.
|
|
// re-synchronizing does not consume a token because 34 follows
|
|
// ref to rule b (start of c). It then matches 34 in c.
|
|
assertEquals("line 1:0 no viable alternative at input '*'\n", this.stderr);
|
|
assertEquals("<unexpected: [@0,0:0='*',<6>,1:0], resync=*>\n", found);
|
|
}
|
|
|
|
|
|
// S U P P O R T
|
|
|
|
protected void checkError(ErrorQueue equeue,
|
|
GrammarSemanticsMessage expectedMessage)
|
|
throws Exception
|
|
{
|
|
//System.out.println("errors="+equeue);
|
|
Message foundMsg = null;
|
|
for (int i = 0; i < equeue.errors.size(); i++) {
|
|
Message m = (Message)equeue.errors.get(i);
|
|
if (m.msgID==expectedMessage.msgID ) {
|
|
foundMsg = m;
|
|
}
|
|
}
|
|
assertTrue("no error; "+expectedMessage.msgID+" expected", equeue.errors.size()>0);
|
|
assertTrue("too many errors; "+equeue.errors, equeue.errors.size()<=1);
|
|
assertNotNull("couldn't find expected error: "+expectedMessage.msgID, foundMsg);
|
|
assertTrue("error is not a GrammarSemanticsMessage",
|
|
foundMsg instanceof GrammarSemanticsMessage);
|
|
assertEquals(expectedMessage.arg, foundMsg.arg);
|
|
assertEquals(expectedMessage.arg2, foundMsg.arg2);
|
|
ErrorManager.resetErrorState(); // wack errors for next test
|
|
}
|
|
|
|
}
|