got basic test harness for grammar errors

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6659]
This commit is contained in:
parrt 2010-02-03 16:25:19 -08:00
parent 6829fc9e47
commit 81bcfe56dc
12 changed files with 250 additions and 123 deletions

View File

@ -1,10 +1,14 @@
package org.antlr.v4;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.v4.parse.*;
import org.antlr.v4.parse.ANTLRLexer;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.semantics.SemanticsPipeline;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.GrammarRootAST;
import java.io.File;
import java.io.IOException;
@ -291,24 +295,34 @@ public class Tool {
}
public Grammar load(String fileName) {
Grammar g = null;
ANTLRFileStream in = null;
try {
ANTLRFileStream in = new ANTLRFileStream(fileName);
ANTLRLexer lexer = new ANTLRLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ANTLRParser p = new ANTLRParser(tokens);
p.setTreeAdaptor(new GrammarASTAdaptor(in));
ParserRuleReturnScope r = p.grammarSpec();
GrammarRootAST t = (GrammarRootAST) r.getTree();
if ( internalOption_PrintGrammarTree ) System.out.println(t.toStringTree());
g = new Grammar(this, t);
g.fileName = fileName;
grammars.put(g.name, g);
in = new ANTLRFileStream(fileName);
}
catch (IOException ioe) {
ErrorManager.toolError(ErrorType.CANNOT_OPEN_FILE, fileName, ioe);
}
Grammar g = load(in);
g.fileName = fileName;
return g;
}
public Grammar loadFromString(String grammar) {
Grammar g = load(new ANTLRStringStream(grammar));
g.fileName = "<string>";
return g;
}
public Grammar load(CharStream in) {
Grammar g = null;
try {
ANTLRLexer lexer = new ANTLRLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ANTLRParser p = new ANTLRParser(tokens);
p.setTreeAdaptor(new GrammarASTAdaptor(in));
ParserRuleReturnScope r = p.grammarSpec();
g = new Grammar(this, (GrammarRootAST)r.getTree());
}
catch (RecognitionException re) {
// TODO: do we gen errors now?
ErrorManager.internalError("can't generate this message at moment; antlr recovers");
@ -319,7 +333,9 @@ public class Tool {
public void process() {
// testing parser
Grammar g = load(grammarFileNames.get(0));
grammars.put(g.name, g);
g.loadImportedGrammars();
if ( g.ast!=null && internalOption_PrintGrammarTree ) System.out.println(g.ast.toStringTree());
//g.ast.inspect();
SemanticsPipeline sem = new SemanticsPipeline();
sem.process(g);

View File

@ -1,5 +1,7 @@
package org.antlr.v4.misc;
import java.util.Iterator;
/** */
public class Utils {
public static String stripFileExtension(String name) {
@ -8,4 +10,16 @@ public class Utils {
if ( lastDot<0 ) return name;
return name.substring(0, lastDot);
}
// Seriously: why isn't this built in to java? ugh!
public static String join(Iterator iter, String separator) {
StringBuilder buf = new StringBuilder();
while ( iter.hasNext() ) {
buf.append(iter.next());
if ( iter.hasNext() ) {
buf.append(separator);
}
}
return buf.toString();
}
}

View File

@ -1,4 +1,4 @@
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRLexer.g 2010-02-03 11:08:45
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRLexer.g 2010-02-03 15:37:27
/*
[The "BSD licence"]
@ -31,11 +31,6 @@ package org.antlr.v4.parse;
import org.antlr.runtime.*;
import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
/** Read in an ANTLR grammar and build an AST. Try not to do
* any actions, just build the tree.
*

View File

@ -1,4 +1,4 @@
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRParser.g 2010-02-03 11:08:48
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRParser.g 2010-02-03 15:37:30
/*
[The "BSD licence"]
@ -29,17 +29,12 @@
*/
package org.antlr.v4.parse;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.v4.tool.*;
import org.antlr.runtime.*;
import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import org.antlr.runtime.tree.*;
import java.util.List;
/** The definitive ANTLR v3 grammar to parse ANTLR v4 grammars.
* The grammar builds ASTs that are sniffed by subsequent stages.
@ -288,7 +283,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: id, rules, grammarType, prequelConstruct, DOC_COMMENT
// elements: id, DOC_COMMENT, rules, prequelConstruct, grammarType
// token labels:
// rule labels: retval
// token list labels:
@ -1127,7 +1122,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: delegateGrammar, IMPORT
// elements: IMPORT, delegateGrammar
// token labels:
// rule labels: retval
// token list labels:
@ -1408,7 +1403,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: TOKENS, tokenSpec
// elements: tokenSpec, TOKENS
// token labels:
// rule labels: retval
// token list labels:
@ -1563,7 +1558,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: STRING_LITERAL, ASSIGN, id
// elements: id, STRING_LITERAL, ASSIGN
// token labels:
// rule labels: retval
// token list labels:
@ -1703,7 +1698,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ACTION, SCOPE, id
// elements: id, SCOPE, ACTION
// token labels:
// rule labels: retval
// token list labels:
@ -1857,7 +1852,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ACTION, AT, id, actionScopeName
// elements: actionScopeName, AT, ACTION, id
// token labels:
// rule labels: retval
// token list labels:
@ -2357,7 +2352,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ARG_ACTION, id, altListAsBlock, exceptionGroup, ruleReturns, DOC_COMMENT, rulePrequel, ruleModifiers
// elements: altListAsBlock, ruleReturns, ARG_ACTION, id, ruleModifiers, DOC_COMMENT, exceptionGroup, rulePrequel
// token labels:
// rule labels: retval
// token list labels:
@ -2583,7 +2578,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: CATCH, ARG_ACTION, ACTION
// elements: ARG_ACTION, ACTION, CATCH
// token labels:
// rule labels: retval
// token list labels:
@ -2666,7 +2661,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: FINALLY, ACTION
// elements: ACTION, FINALLY
// token labels:
// rule labels: retval
// token list labels:
@ -3288,7 +3283,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: AT, id, ACTION
// elements: id, AT, ACTION
// token labels:
// rule labels: retval
// token list labels:
@ -3804,7 +3799,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: elements, rewrite
// elements: rewrite, elements
// token labels:
// rule labels: retval
// token list labels:
@ -4948,7 +4943,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: block, blockSuffixe
// elements: blockSuffixe, block
// token labels:
// rule labels: retval
// token list labels:
@ -5454,7 +5449,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: id, ruleref, DOT
// elements: DOT, id, ruleref
// token labels:
// rule labels: retval
// token list labels:
@ -5512,7 +5507,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: DOT, terminal, id
// elements: DOT, id, terminal
// token labels:
// rule labels: retval
// token list labels:
@ -5711,7 +5706,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: notTerminal, NOT
// elements: NOT, notTerminal
// token labels:
// rule labels: retval
// token list labels:
@ -5754,7 +5749,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: NOT, block
// elements: block, NOT
// token labels:
// rule labels: retval
// token list labels:
@ -6018,7 +6013,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: altList, ACTION, optionsSpec, ra
// elements: ra, ACTION, altList, optionsSpec
// token labels:
// rule labels: retval
// token list labels:
@ -6199,7 +6194,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: RULE_REF, ARG_ACTION, op
// elements: op, RULE_REF, ARG_ACTION
// token labels: op
// rule labels: retval
// token list labels:
@ -6616,7 +6611,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: elementOptions, STRING_LITERAL
// elements: STRING_LITERAL, elementOptions
// token labels:
// rule labels: retval
// token list labels:
@ -7226,7 +7221,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: nakedRewrite, predicatedRewrite
// elements: predicatedRewrite, nakedRewrite
// token labels:
// rule labels: retval
// token list labels:
@ -7314,7 +7309,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: rewriteAlt, SEMPRED, SEMPRED, rewriteAlt
// elements: rewriteAlt, SEMPRED, rewriteAlt, SEMPRED
// token labels:
// rule labels: retval
// token list labels:
@ -8066,7 +8061,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: TOKEN_REF, ARG_ACTION
// elements: ARG_ACTION, TOKEN_REF
// token labels:
// rule labels: retval
// token list labels:
@ -8249,7 +8244,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: rewriteTreeAlt, ebnfSuffix
// elements: ebnfSuffix, rewriteTreeAlt
// token labels:
// rule labels: retval
// token list labels:
@ -8386,7 +8381,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: rewriteTreeElement, rewriteTreeAtom, TREE_BEGIN
// elements: TREE_BEGIN, rewriteTreeElement, rewriteTreeAtom
// token labels:
// rule labels: retval
// token list labels:
@ -8541,7 +8536,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: str, rewriteTemplateArgs, TEMPLATE
// elements: str, TEMPLATE, rewriteTemplateArgs
// token labels: str
// rule labels: retval
// token list labels:
@ -8802,7 +8797,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: rewriteTemplateArgs, ACTION
// elements: ACTION, rewriteTemplateArgs
// token labels:
// rule labels: retval
// token list labels:
@ -9048,7 +9043,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ACTION, id
// elements: id, ACTION
// token labels:
// rule labels: retval
// token list labels:

View File

@ -1,4 +1,4 @@
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ASTVerifier.g 2010-02-03 11:08:48
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ASTVerifier.g 2010-02-03 15:37:30
/*
[The "BSD license"]
@ -26,14 +26,15 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.parse;
import org.antlr.v4.tool.*;
import org.antlr.v4.runtime.tree.CommonTree; // use updated v4 one not v3
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;import java.util.Stack;
import org.antlr.runtime.tree.TreeNodeStream;
import org.antlr.runtime.tree.TreeParser;
import org.antlr.runtime.tree.TreeRuleReturnScope;
import org.antlr.v4.runtime.tree.CommonTree;
import org.antlr.v4.tool.GrammarAST;
import java.util.List;
import java.util.ArrayList;
/** The definitive ANTLR v3 tree grammar to parse ANTLR v4 grammars.
* Parses trees created in ANTLRParser.g.

View File

@ -2,17 +2,35 @@ package org.antlr.v4.semantics;
import org.antlr.misc.MultiMap;
import org.antlr.runtime.Token;
import org.antlr.tool.*;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.GrammarAST;
import java.io.File;
import java.util.*;
/** No side-effects */
/** No side-effects; BasicSemanticTriggers.g invokes check rules for these:
*
* FILE_AND_GRAMMAR_NAME_DIFFER
* LEXER_RULES_NOT_ALLOWED
* PARSER_RULES_NOT_ALLOWED
* CANNOT_ALIAS_TOKENS_IN_LEXER
* ARGS_ON_TOKEN_REF
* ILLEGAL_OPTION
* REWRITE_OR_OP_WITH_NO_OUTPUT_OPTION
* NO_RULES
* REWRITE_FOR_MULTI_ELEMENT_ALT
* HETERO_ILLEGAL_IN_REWRITE_ALT
* AST_OP_WITH_NON_AST_OUTPUT_OPTION
* AST_OP_IN_ALT_WITH_REWRITE
* CONFLICTING_OPTION_IN_TREE_FILTER
* WILDCARD_AS_ROOT
* INVALID_IMPORT
* TOKEN_VOCAB_IN_DELEGATE
* IMPORT_NAME_CLASH
* REPEATED_PREQUEL
* TOKEN_NAMES_MUST_START_UPPER
*/
public class BasicSemanticChecks {
public static final Set legalLexerOptions =
new HashSet() {
@ -99,7 +117,9 @@ public class BasicSemanticChecks {
// TODO: track errors?
protected static void checkGrammarName(Token nameToken) {
String fileName = nameToken.getInputStream().getSourceName();
String fullyQualifiedName = nameToken.getInputStream().getSourceName();
File f = new File(fullyQualifiedName);
String fileName = f.getName();
if ( !Utils.stripFileExtension(fileName).equals(nameToken.getText()) ) {
ErrorManager.grammarError(ErrorType.FILE_AND_GRAMMAR_NAME_DIFFER,
fileName, nameToken, nameToken.getText(), fileName);
@ -384,8 +404,4 @@ public class BasicSemanticChecks {
g, delegate);
}
}
protected static void checkFOO(int gtype, Token ID) {
}
}

View File

@ -1,4 +1,4 @@
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 BasicSemanticTriggers.g 2010-02-03 13:08:25
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 BasicSemanticTriggers.g 2010-02-03 15:37:39
/*
[The "BSD license"]
@ -26,15 +26,14 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.semantics;
import org.antlr.v4.tool.*;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;import java.util.Stack;
import java.util.List;
import org.antlr.runtime.tree.TreeNodeStream;
import org.antlr.runtime.tree.TreeRuleReturnScope;
import org.antlr.v4.tool.*;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
/** Triggers for the basic semantics of the input. Side-effects:
* Set token, block, rule options in the tree. Load field option
* with grammar options. Only legal options are set.

View File

@ -1,18 +1,11 @@
package org.antlr.v4.semantics;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.BufferedTreeNodeStream;
import org.antlr.runtime.tree.TreeVisitor;
import org.antlr.runtime.tree.TreeVisitorAction;
import org.antlr.v4.Tool;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.ASTVerifier;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.GrammarASTWithOptions;
/** */
public class SemanticsPipeline {
@ -35,13 +28,17 @@ public class SemanticsPipeline {
BasicSemanticTriggers basics = new BasicSemanticTriggers(nodes,g);
basics.downup(g.ast);
// NOW DO DELEGATES (IF ANY)
// NOW DO BASIC / EASY SEMANTIC CHECKS FOR DELEGATES (IF ANY)
if ( g.getImportedGrammars()!=null ) {
for (Grammar d : g.getImportedGrammars()) {
process(d);
}
}
// DEFINE SYMBOLS
// ASSIGN TOKEN TYPES
/* dump options
TreeVisitor v = new TreeVisitor(adaptor);
v.visit(g.ast,

View File

@ -1,6 +1,5 @@
package org.antlr.v4.tool;
import org.antlr.Tool;
import org.antlr.runtime.Token;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STErrorListener;
@ -57,10 +56,6 @@ public class ErrorManager {
private static Locale locale;
private static String formatName;
// TODO: make thread local to hold this state
public static int errors;
public static int warnings;
static ANTLRErrorListener theDefaultErrorListener = new ANTLRErrorListener() {
public void info(String msg) {
if (formatWantsSingleLineMessage()) {
@ -109,8 +104,18 @@ public class ErrorManager {
public static final String FORMATS_DIR = "org/antlr/v4/tool/templates/messages/formats/";
public static final String MESSAGES_DIR = "org/antlr/v4/tool/templates/messages/languages/";
private static class ErrorState {
public ANTLRErrorListener listener;
public int errors;
public int warnings;
}
private static ThreadLocal<ErrorState> state = new ThreadLocal<ErrorState>();
// make sure that this class is ready to use after loading
static {
state.set(new ErrorState());
setErrorListener(theDefaultErrorListener);
org.stringtemplate.v4.misc.ErrorManager.setErrorListener(initSTListener);
// it is inefficient to set the default locale here if another
// piece of code is going to set the locale, but that would
@ -123,9 +128,11 @@ public class ErrorManager {
setFormat("antlr");
org.stringtemplate.v4.misc.ErrorManager.setErrorListener(theDefaultSTListener);
}
public static ANTLRErrorListener getErrorListener() {
return theDefaultErrorListener;
return state.get().listener;
}
/** Return a StringTemplate that refers to the current format used for
@ -160,14 +167,14 @@ public class ErrorManager {
}
public static void internalError(String error, Throwable e) {
errors++;
state.get().errors++;
StackTraceElement location = getLastNonErrorManagerCodeLocation(e);
String msg = "Exception "+e+"@"+location+": "+error;
System.err.println("internal error: "+msg);
}
public static void internalError(String error) {
errors++;
state.get().errors++;
StackTraceElement location =
getLastNonErrorManagerCodeLocation(new Exception());
String msg = location+": "+error;
@ -181,8 +188,8 @@ public class ErrorManager {
* @param args The arguments to pass to the StringTemplate
*/
public static void toolError(ErrorType errorType, Object... args) {
errors++;
theDefaultErrorListener.error(new ToolMessage(errorType, args));
state.get().errors++;
state.get().listener.error(new ToolMessage(errorType, args));
}
/**
@ -217,9 +224,9 @@ public class ErrorManager {
Token token,
Object... args)
{
errors++;
state.get().errors++;
Message msg = new GrammarSemanticsMessage(etype,g,token,args);
theDefaultErrorListener.error(msg);
state.get().listener.error(msg);
}
public static void grammarError(ErrorType etype,
@ -227,9 +234,9 @@ public class ErrorManager {
Token token,
Object... args)
{
errors++;
state.get().errors++;
Message msg = new GrammarSemanticsMessage(etype,fileName,token,args);
theDefaultErrorListener.error(msg);
state.get().listener.error(msg);
}
public static void grammarWarning(ErrorType etype,
@ -237,9 +244,9 @@ public class ErrorManager {
Token token,
Object... args)
{
warnings++;
state.get().warnings++;
Message msg = new GrammarSemanticsMessage(etype,fileName,token,args);
theDefaultErrorListener.warning(msg);
state.get().listener.warning(msg);
}
/** Process a new message by sending it on to the error listener associated with the current thread
@ -249,7 +256,7 @@ public class ErrorManager {
}
public static int getNumErrors() {
return errors;
return state.get().errors;
}
/** Return first non ErrorManager code location for generating messages */
@ -266,6 +273,17 @@ public class ErrorManager {
return location;
}
/** In general, you'll want all errors to go to a single spot.
* However, in a GUI, you might have two frames up with two
* different grammars. Two threads might launch to process the
* grammars--you would want errors to go to different objects
* depending on the thread. I store a single listener per
* thread.
*/
public static void setErrorListener(ANTLRErrorListener l) {
state.get().listener = l;
}
// S U P P O R T C O D E
/** We really only need a single locale for entire running ANTLR code

View File

@ -1,9 +1,13 @@
package org.antlr.v4.tool;
import org.antlr.runtime.*;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.ParserRuleReturnScope;
import org.antlr.runtime.RecognitionException;
import org.antlr.v4.Tool;
import org.antlr.v4.parse.ANTLRLexer;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.GrammarASTAdaptor;
import java.util.*;
@ -41,15 +45,18 @@ public class Grammar {
}
/** For testing */
public Grammar(String grammarText) throws RecognitionException {
public Grammar(String fileName, String grammarText) throws RecognitionException {
this.text = grammarText;
ANTLRStringStream in = new ANTLRStringStream(grammarText);
in.name = fileName;
ANTLRLexer lexer = new ANTLRLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ANTLRParser p = new ANTLRParser(tokens);
p.setTreeAdaptor(new GrammarASTAdaptor(in));
ParserRuleReturnScope r = p.grammarSpec();
ast = (GrammarRootAST) r.getTree();
System.out.println(ast.toStringTree());
ast = (GrammarRootAST)r.getTree();
this.name = ((GrammarAST)ast.getChild(0)).getText();
this.fileName = fileName;
}
public void loadImportedGrammars() {

View File

@ -27,17 +27,19 @@
*/
package org.antlr.v4.test;
import org.antlr.tool.ANTLRErrorListener;
import org.antlr.tool.Message;
import org.antlr.tool.ToolMessage;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.tool.ANTLRErrorListener;
import org.antlr.v4.tool.Message;
import org.antlr.v4.tool.ToolMessage;
import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;
public class ErrorQueue implements ANTLRErrorListener {
List infos = new LinkedList();
List errors = new LinkedList();
List warnings = new LinkedList();
public List<String> infos = new ArrayList<String>();
public List<Message> errors = new ArrayList<Message>();
public List<Message> warnings = new ArrayList<Message>();
public List<Message> all = new ArrayList<Message>();
public void info(String msg) {
infos.add(msg);
@ -45,24 +47,23 @@ public class ErrorQueue implements ANTLRErrorListener {
public void error(Message msg) {
errors.add(msg);
all.add(msg);
}
public void warning(Message msg) {
warnings.add(msg);
all.add(msg);
}
public void error(ToolMessage msg) {
errors.add(msg);
all.add(msg);
}
public int size() {
return infos.size() + errors.size() + warnings.size();
return all.size() + infos.size();
}
public String toString() {
return "infos: "+infos+
"errors: "+errors+
"warnings: "+warnings;
}
public String toString() { return Utils.join(all.iterator(), "\n"); }
}

View File

@ -0,0 +1,68 @@
package org.antlr.v4.test;
import org.antlr.runtime.RecognitionException;
import org.antlr.v4.semantics.SemanticsPipeline;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.Grammar;
import org.junit.Test;
public class TestBasicSemanticErrors extends BaseTest {
public static class InOutPair { String in, out; }
static String[] pairs = {
// INPUT
"grammar A;\n" +
"\n" +
"options {\n" +
" output=template;\n" +
"}\n" +
"\n" +
"a : ID<Foo> -> ID ;\n" +
"\n" +
"b : A^ | ((B!|C)) -> ICK;",
// YIELDS
"error(68): A.g:7:7: alts with rewrites can't use heterogeneous types left of ->\n" +
"error(77): A.g:9:4: AST operator with non-AST output option: ^\n" +
"error(77): A.g:9:11: AST operator with non-AST output option: !\n" +
"error(78): A.g:9:11: rule b alt 2 uses rewrite syntax and also an AST operator",
// INPUT
"tree grammar B;\n" +
"options {\n" +
"\tfilter=true;\n" +
"\tbacktrack=false;\n" +
"\toutput=template;\n" +
"}\n" +
"\n" +
"a : A;\n" +
"\n" +
"b : ^(. A) ;",
// YIELDS
"error(79): B.g:10:6: Wildcard invalid as root; wildcard can itself be a tree\n" +
"error(80): B.g:1:5: option backtrack=false conflicts with tree grammar filter mode\n" +
"error(80): B.g:1:5: option output=template conflicts with tree grammar filter mode",
};
@Test public void testErrors() {
for (int i = 0; i < pairs.length; i+=2) {
String input = pairs[i];
String expect = pairs[i+1];
ErrorQueue equeue = new ErrorQueue();
ErrorManager.setErrorListener(equeue);
try {
String[] lines = input.split("\n");
int lastSpace = lines[0].lastIndexOf(' ');
int semi = lines[0].lastIndexOf(';');
String fileName = lines[0].substring(lastSpace+1, semi)+".g";
Grammar g = new Grammar(fileName, input);
g.loadImportedGrammars();
SemanticsPipeline sem = new SemanticsPipeline();
sem.process(g);
}
catch (RecognitionException re) {
re.printStackTrace(System.err);
}
String actual = equeue.toString();
assertEquals(expect,actual);
}
}
}