forked from jasder/antlr
got basic test harness for grammar errors
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6659]
This commit is contained in:
parent
6829fc9e47
commit
81bcfe56dc
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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"); }
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue