got error handling with v4 ST working; no error loops etc...

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6641]
This commit is contained in:
parrt 2010-01-31 13:08:09 -08:00
parent c9d6efc7c5
commit 08d8a0db23
15 changed files with 316 additions and 182 deletions

View File

@ -26,17 +26,15 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
New style messages. This file contains the actual layout of the messages emitted by ANTLR.
This file contains the actual layout of the messages emitted by ANTLR.
The text itself is coming out of the languages/*stg files, according to the chosen locale.
This file contains the default format ANTLR uses.
*/
group antlr;
location(file, line, column) ::= "<file>:<line>:<column>:"
message(id, text) ::= "(<id>) <text>"
report(location, message, type) ::= "<type>(<message.id>): <location> <message.text>"
wantsSingleLineMessage() ::= "false"
wantsSingleLineMessage() ::= "false"

View File

@ -26,17 +26,15 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
New style messages. This file contains the actual layout of the messages emitted by ANTLR.
This file contains the actual layout of the messages emitted by ANTLR.
The text itself is coming out of the languages/*stg files, according to the chosen locale.
This file contains the format that mimicks GCC output.
*/
group gnu;
location(file, line, column) ::= "<file>:<line>:"
message(id, text) ::= "<text> (<id>)"
report(location, message, type) ::= "<location> <type>: <message>"
wantsSingleLineMessage() ::= "true"
wantsSingleLineMessage() ::= "true"

View File

@ -26,13 +26,11 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
New style messages. This file contains the actual layout of the messages emitted by ANTLR.
This file contains the actual layout of the messages emitted by ANTLR.
The text itself is coming out of the languages/*stg files, according to the chosen locale.
This file contains the default format ANTLR uses.
*/
group antlr;
location(file, line, column) ::= "<file>(<line>,<column>)"
message(id, text) ::= "error <id> : <text>"

View File

@ -26,13 +26,11 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
New style messages. This file only contains the messages in English, but no
This file only contains the messages in English, but no
information about which file, line, or column it occurred in.
The location and message ids are taken out of the formats directory.
Kay Roepke
*/
group en_US;
// TOOL ERRORS
// file errors
CANNOT_WRITE_FILE(arg,exception,stackTrace) ::= <<
@ -46,8 +44,8 @@ problem reading token vocabulary file <arg>: <exception>
<stackTrace; separator="\n">
>>
DIR_NOT_FOUND(arg,exception,stackTrace) ::= "directory not found: <arg>"
OUTPUT_DIR_IS_FILE(arg,exception,stackTrace) ::= "output directory is a file: <arg>"
CANNOT_OPEN_FILE(arg,exception,stackTrace) ::= "cannot find or open file: <arg><if(exception)>; reason: <exception><endif>"
OUTPUT_DIR_IS_FILE(arg,arg2) ::= "output directory is a file: <arg>"
CANNOT_OPEN_FILE(arg,exception) ::= "cannot find or open file: <arg><if(exception)>; reason: <exception><endif>"
CIRCULAR_DEPENDENCY() ::= "your grammars contain a circular dependency and cannot be sorted into a valid build order."
INTERNAL_ERROR(arg,arg2,exception,stackTrace) ::= <<

View File

@ -7,6 +7,7 @@ import org.antlr.v4.semantics.SemanticsPipeline;
import org.antlr.v4.tool.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class Tool {
@ -66,18 +67,18 @@ public class Tool {
/** An adaptor that tells ANTLR to build CymbalAST nodes */
public static TreeAdaptor astAdaptor = new GrammarASTAdaptor();
public static void main(String[] args) throws Exception {
public static void main(String[] args) {
Tool antlr = new Tool(args);
if (!exitNow) {
antlr.process();
if (ErrorManager.getNumErrors() > 0) {
System.exit(1);
antlr.exit(1);
}
// System.exit(0);
antlr.exit(0);
}
}
public Tool() {
}
@ -85,6 +86,14 @@ public class Tool {
processArgs(args);
}
public void exit(int e) {
System.exit(e);
}
public void panic() {
throw new Error("ANTLR panic");
}
public void processArgs(String[] args) {
if (verbose) {
ErrorManager.info("ANTLR Parser Generator Version " + VERSION);
@ -114,7 +123,7 @@ public class Tool {
File outDir = new File(outputDirectory);
haveOutputDir = true;
if (outDir.exists() && !outDir.isDirectory()) {
ErrorManager.error(ErrorType.OUTPUT_DIR_IS_FILE, outputDirectory);
ErrorManager.toolError(ErrorType.OUTPUT_DIR_IS_FILE, outputDirectory);
libDirectory = ".";
}
}
@ -132,7 +141,7 @@ public class Tool {
}
File outDir = new File(libDirectory);
if (!outDir.exists()) {
ErrorManager.error(ErrorType.DIR_NOT_FOUND, libDirectory);
ErrorManager.toolError(ErrorType.DIR_NOT_FOUND, libDirectory);
libDirectory = ".";
}
}
@ -282,22 +291,32 @@ public class Tool {
}
}
public Grammar load(String fileName) throws Exception {
ANTLRFileStream in = new ANTLRFileStream(fileName);
ANTLRLexer lexer = new ANTLRLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ANTLRParser p = new ANTLRParser(tokens);
p.setTreeAdaptor(astAdaptor);
ParserRuleReturnScope r = p.grammarSpec();
GrammarAST t = (GrammarAST) r.getTree();
System.out.println(t.toStringTree());
Grammar g = new Grammar(this, t);
g.fileName = fileName;
grammars.put(g.name, g);
public Grammar load(String fileName) {
Grammar g = null;
try {
ANTLRFileStream in = new ANTLRFileStream(fileName);
ANTLRLexer lexer = new ANTLRLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ANTLRParser p = new ANTLRParser(tokens);
p.setTreeAdaptor(astAdaptor);
ParserRuleReturnScope r = p.grammarSpec();
GrammarAST t = (GrammarAST) r.getTree();
System.out.println(t.toStringTree());
g = new Grammar(this, t);
g.fileName = fileName;
grammars.put(g.name, g);
}
catch (IOException ioe) {
ErrorManager.toolError(ErrorType.CANNOT_OPEN_FILE, fileName, ioe);
}
catch (RecognitionException re) {
// TODO: do we gen errors now?
ErrorManager.internalError("can't generate this message at moment; antlr recovers");
}
return g;
}
public void process() throws Exception {
public void process() {
// testing parser
Grammar g = load(grammarFileNames.get(0));
g.loadImportedGrammars();

View File

@ -1,4 +1,4 @@
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRLexer.g 2010-01-30 14:28:45
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRLexer.g 2010-01-31 12:53:18
/*
[The "BSD licence"]

View File

@ -1,4 +1,4 @@
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRParser.g 2010-01-30 14:28:48
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ANTLRParser.g 2010-01-31 12:53:20
/*
[The "BSD licence"]
@ -292,7 +292,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: grammarType, DOC_COMMENT, prequelConstruct, rules, id
// elements: rules, DOC_COMMENT, prequelConstruct, id, grammarType
// token labels:
// rule labels: retval
// token list labels:
@ -1396,7 +1396,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: TOKENS, tokenSpec
// elements: tokenSpec, TOKENS
// token labels:
// rule labels: retval
// token list labels:
@ -1572,7 +1572,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: lit, ASSIGN, TOKEN_REF
// elements: ASSIGN, lit, TOKEN_REF
// token labels: lit
// rule labels: retval
// token list labels:
@ -1713,7 +1713,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ACTION, SCOPE, id
// elements: ACTION, id, SCOPE
// token labels:
// rule labels: retval
// token list labels:
@ -1858,7 +1858,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ACTION, id, actionScopeName, AT
// elements: actionScopeName, ACTION, id, AT
// token labels:
// rule labels: retval
// token list labels:
@ -2357,7 +2357,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ruleReturns, exceptionGroup, ruleModifiers, DOC_COMMENT, id, altListAsBlock, rulePrequel, ARG_ACTION
// elements: rulePrequel, DOC_COMMENT, ARG_ACTION, ruleReturns, exceptionGroup, ruleModifiers, altListAsBlock, id
// token labels:
// rule labels: retval
// token list labels:
@ -2583,7 +2583,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ACTION, ARG_ACTION, CATCH
// elements: ACTION, CATCH, ARG_ACTION
// token labels:
// rule labels: retval
// token list labels:
@ -3189,7 +3189,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: SCOPE, id
// elements: id, SCOPE
// token labels:
// rule labels: retval
// token list labels:
@ -3804,7 +3804,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: elements, rewrite
// elements: rewrite, elements
// token labels:
// rule labels: retval
// token list labels:
@ -4357,7 +4357,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ebnfSuffix, atom
// elements: atom, ebnfSuffix
// token labels:
// rule labels: retval
// token list labels:
@ -4582,7 +4582,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: treeSpec, ebnfSuffix
// elements: ebnfSuffix, treeSpec
// token labels:
// rule labels: retval
// token list labels:
@ -5022,7 +5022,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: blockSuffixe, block
// elements: block, blockSuffixe
// token labels:
// rule labels: retval
// token list labels:
@ -5586,7 +5586,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: id, terminal
// elements: terminal, id
// token labels:
// rule labels: retval
// token list labels:
@ -6092,7 +6092,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: optionsSpec, altList, ra, ACTION
// elements: ra, optionsSpec, altList, ACTION
// token labels:
// rule labels: retval
// token list labels:
@ -6273,7 +6273,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: op, RULE_REF, ARG_ACTION
// elements: RULE_REF, ARG_ACTION, op
// token labels: op
// rule labels: retval
// token list labels:
@ -6609,7 +6609,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: CHAR_LITERAL, elementOptions
// elements: elementOptions, CHAR_LITERAL
// token labels:
// rule labels: retval
// token list labels:
@ -6694,7 +6694,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: elementOptions, ARG_ACTION, TOKEN_REF
// elements: TOKEN_REF, elementOptions, ARG_ACTION
// token labels:
// rule labels: retval
// token list labels:
@ -6765,7 +6765,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: STRING_LITERAL, elementOptions
// elements: elementOptions, STRING_LITERAL
// token labels:
// rule labels: retval
// token list labels:
@ -6886,7 +6886,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: terminal, ROOT
// elements: ROOT, terminal
// token labels:
// rule labels: retval
// token list labels:
@ -7440,7 +7440,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: rewriteAlt, rewriteAlt, SEMPRED, SEMPRED
// elements: rewriteAlt, SEMPRED, SEMPRED, rewriteAlt
// token labels:
// rule labels: retval
// token list labels:
@ -7982,7 +7982,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: rewriteTree, ebnfSuffix
// elements: ebnfSuffix, rewriteTree
// token labels:
// rule labels: retval
// token list labels:
@ -8212,7 +8212,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:
@ -8532,7 +8532,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: TREE_BEGIN, rewriteTreeElement, rewriteTreeAtom
// elements: rewriteTreeAtom, TREE_BEGIN, rewriteTreeElement
// token labels:
// rule labels: retval
// token list labels:
@ -8716,7 +8716,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: str, rewriteTemplateArgs, TEMPLATE
// elements: rewriteTemplateArgs, str, TEMPLATE
// token labels: str
// rule labels: retval
// token list labels:
@ -8977,7 +8977,7 @@ public class ANTLRParser extends Parser {
// AST REWRITE
// elements: ACTION, rewriteTemplateArgs
// elements: rewriteTemplateArgs, 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-01-30 14:28:48
// $ANTLR 3.2.1-SNAPSHOT Jan 26, 2010 15:12:28 ASTVerifier.g 2010-01-31 12:53:21
/*
[The "BSD license"]

View File

@ -102,6 +102,14 @@ package org.antlr.v4.semantics;
import org.antlr.v4.tool.*;
}
@members {
Grammar g; // which grammar are we checking
public BasicSemanticsChecker(TreeNodeStream input, Grammar g) {
this(input);
this.g = g;
}
}
topdown
: grammarSpec
| optionsSpec
@ -111,7 +119,10 @@ topdown
grammarSpec
: ^(grammarType ID .*)
{
System.out.println("gname = "+$ID.text);
if ( !g.fileName.equals($ID.text) ) {
ErrorManager.grammarError(ErrorType.FILE_AND_GRAMMAR_NAME_DIFFER,
g, $ID.token, $ID.text, g.fileName);
}
}
;

View File

@ -5,7 +5,6 @@ import org.antlr.runtime.tree.BufferedTreeNodeStream;
import org.antlr.v4.Tool;
import org.antlr.v4.parse.ASTVerifier;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
/** */
@ -14,17 +13,17 @@ public class SemanticsPipeline {
// VALIDATE AST STRUCTURE
// use buffered node stream as we will look around in stream
// to give good error messages.
// TODO: send errors to buffer not stderr
// TODO: send parse errors to buffer not stderr
BufferedTreeNodeStream nodes = new BufferedTreeNodeStream(Tool.astAdaptor,g.ast);
ASTVerifier walker = new ASTVerifier(nodes);
try {walker.grammarSpec();}
catch (RecognitionException re) {
ErrorManager.error(ErrorType.BAD_AST_STRUCTURE, re.toString());
ErrorManager.internalError("bad grammar AST structure", re);
}
// DO BASIC / EASY SEMANTIC CHECKS
nodes.reset();
BasicSemanticsChecker basics = new BasicSemanticsChecker(nodes);
BasicSemanticsChecker basics = new BasicSemanticsChecker(nodes,g);
basics.downup(g.ast);
}
}

View File

@ -1,11 +1,15 @@
package org.antlr.v4.tool;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.tree.CommonTree;
import org.stringtemplate.ST;
import org.stringtemplate.STGroup;
import org.antlr.Tool;
import org.antlr.runtime.Token;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STErrorListener;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STGroupFile;
import org.stringtemplate.v4.misc.ErrorBuffer;
import org.stringtemplate.v4.misc.STMessage;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Locale;
/** Defines all the errors ANTLR can generator for both the tool and for
@ -53,11 +57,6 @@ public class ErrorManager {
private static Locale locale;
private static String formatName;
/** From a msgID how can I get the name of the template that describes
* the error or warning?
*/
private static String[] idToMessageTemplateName = new String[ErrorType.values().length];
static ANTLRErrorListener theDefaultErrorListener = new ANTLRErrorListener() {
public void info(String msg) {
if (formatWantsSingleLineMessage()) {
@ -83,6 +82,44 @@ public class ErrorManager {
}
};
static ErrorBuffer initSTListener = new ErrorBuffer();
static STErrorListener theDefaultSTListener =
new STErrorListener() {
public void compileTimeError(STMessage msg) {
ErrorManager.internalError(msg.toString());
}
public void runTimeError(STMessage msg) {
ErrorManager.internalError(msg.toString());
}
public void IOError(STMessage msg) {
ErrorManager.internalError(msg.toString());
}
public void internalError(STMessage msg) {
ErrorManager.internalError(msg.toString());
}
};
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/";
// make sure that this class is ready to use after loading
static {
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
// require that a user call an init() function or something. I prefer
// that this class be ready to go when loaded as I'm absentminded ;)
setLocale(Locale.getDefault());
// try to load the message format group
// the user might have specified one on the command line
// if not, or if the user has given an illegal value, we will fall back to "antlr"
setFormat("antlr");
org.stringtemplate.v4.misc.ErrorManager.setErrorListener(theDefaultSTListener);
}
public static ANTLRErrorListener getErrorListener() {
return theDefaultErrorListener;
}
@ -103,7 +140,7 @@ public class ErrorManager {
return format.getInstanceOf("wantsSingleLineMessage").toString().equals("true");
}
public static ST getMessageTemplate(ErrorType etype) {
String msgName = idToMessageTemplateName[etype.ordinal()];
String msgName = etype.toString();
return messages.getInstanceOf(msgName);
}
@ -117,24 +154,24 @@ public class ErrorManager {
public static void internalError(String error, Throwable e) {
StackTraceElement location = getLastNonErrorManagerCodeLocation(e);
String msg = "Exception "+e+"@"+location+": "+error;
theDefaultErrorListener.error(new ToolMessage(ErrorType.INTERNAL_ERROR, msg));
System.err.println("internal error: "+msg);
}
public static void internalError(String error) {
StackTraceElement location =
getLastNonErrorManagerCodeLocation(new Exception());
String msg = location+": "+error;
theDefaultErrorListener.error(new ToolMessage(ErrorType.INTERNAL_ERROR, msg));
System.err.println("internal error: "+msg);
}
/**
* Raise a predefined message with some number of paramters for the StringTemplate but for which there
* is no location information possible.
* @param errorType The Message Descriptor
* @param args The arguments to pass to the StringTemplate
*/
public static void error(ErrorType errorType, Object... args) {
public static void toolError(ErrorType errorType, Object... args) {
theDefaultErrorListener.error(new ToolMessage(errorType, args));
}
/**
@ -143,9 +180,9 @@ public class ErrorManager {
*
* @param errorType The Message Descriptor
* @param args The arguments to pass to the StringTemplate
*/
public static void error(ErrorType errorType, int line, int column, int absOffset, int endLine, int endColumn, int endAbsOffset, Object... args) {
public static void toolError(ErrorType errorType, int line, int column, int absOffset, int endLine, int endColumn, int endAbsOffset, Object... args) {
}
*/
/**
* Raise a predefined message with some number of paramters for the StringTemplate, for which there is a CommonToken
@ -153,20 +190,25 @@ public class ErrorManager {
* @param errorType The message descriptor.
* @param t The token that contains our location information
* @param args The varargs array of values that will be set in the StrngTemplate as arg0, arg1, ... argn
*/
public static void error(ErrorType errorType, CommonToken t, Object... args) {
}
*/
/**
* Construct a message when we have a node stream and AST node that we can extract location
* from and possbily some arguments for the StringTemplate that will construct this message.
*
* @param errorType The message descriptor
* @param node The node that gives us the information we need
* @param args The varargs array of values that will be set in the StrngTemplate as arg0, arg1, ... argn
*/
public static void error(ErrorType errorType, CommonTree node, Object... args) {
}
*/
public static void grammarError(ErrorType etype,
Grammar g,
Token token,
Object... args)
{
Message msg = new GrammarSemanticsMessage(etype,g,token,args);
theDefaultErrorListener.error(msg);
}
/** Process a new message by sending it on to the error listener associated with the current thread
* and recording any information we need in the error state for the current thread.
@ -194,35 +236,88 @@ public class ErrorManager {
// S U P P O R T C O D E
protected static boolean initIdToMessageNameMapping() {
// make sure a message exists, even if it's just to indicate a problem
for (int i = 0; i < idToMessageTemplateName.length; i++) {
idToMessageTemplateName[i] = "INVALID MESSAGE ID: "+i;
/** We really only need a single locale for entire running ANTLR code
* in a single VM. Only pay attention to the language, not the country
* so that French Canadians and French Frenchies all get the same
* template file, fr.stg. Just easier this way.
*/
public static void setLocale(Locale locale) {
ErrorManager.locale = locale;
String language = locale.getLanguage();
String fileName = MESSAGES_DIR +language+".stg";
ClassLoader cl = Thread.currentThread().getContextClassLoader();
URL url = cl.getResource(fileName);
if ( url==null ) {
cl = ErrorManager.class.getClassLoader();
url = cl.getResource(fileName);
}
// get list of fields and use it to fill in idToMessageTemplateName mapping
Field[] fields = ErrorManager.class.getFields();
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
String fieldName = f.getName();
if ( !fieldName.startsWith("MSG_") ) {
continue;
}
String templateName =
fieldName.substring("MSG_".length(),fieldName.length());
int msgID = 0;
try {
// get the constant value from this class object
msgID = f.getInt(ErrorManager.class);
}
catch (IllegalAccessException iae) {
System.err.println("cannot get const value for "+f.getName());
continue;
}
if ( fieldName.startsWith("MSG_") ) {
idToMessageTemplateName[msgID] = templateName;
}
if ( url==null && language.equals(Locale.US.getLanguage()) ) {
rawError("ANTLR installation corrupted; cannot find English messages file "+fileName);
panic();
}
else if ( url==null ) {
//rawError("no such locale file "+fileName+" retrying with English locale");
setLocale(Locale.US); // recurse on this rule, trying the US locale
return;
}
messages = new STGroupFile(fileName, "UTF-8");
messages.load();
if ( initSTListener.errors.size()>0 ) {
rawError("ANTLR installation corrupted; can't load messages format file:\n"+
initSTListener.toString());
panic();
}
boolean messagesOK = verifyMessages();
if ( !messagesOK && language.equals(Locale.US.getLanguage()) ) {
rawError("ANTLR installation corrupted; English messages file "+language+".stg incomplete");
panic();
}
else if ( !messagesOK ) {
setLocale(Locale.US); // try US to see if that will work
}
}
/** The format gets reset either from the Tool if the user supplied a command line option to that effect
* Otherwise we just use the default "antlr".
*/
public static void setFormat(String formatName) {
ErrorManager.formatName = formatName;
String fileName = FORMATS_DIR +formatName+".stg";
ClassLoader cl = Thread.currentThread().getContextClassLoader();
URL url = cl.getResource(fileName);
if ( url==null ) {
cl = ErrorManager.class.getClassLoader();
url = cl.getResource(fileName);
}
if ( url==null && formatName.equals("antlr") ) {
rawError("ANTLR installation corrupted; cannot find ANTLR messages format file "+fileName);
panic();
}
else if ( url==null ) {
rawError("no such message format file "+fileName+" retrying with default ANTLR format");
setFormat("antlr"); // recurse on this rule, trying the default message format
return;
}
format = new STGroupFile(fileName, "UTF-8");
format.load();
if ( initSTListener.errors.size()>0 ) {
rawError("ANTLR installation corrupted; can't load messages format file:\n"+
initSTListener.toString());
panic();
}
boolean formatOK = verifyFormat();
if ( !formatOK && formatName.equals("antlr") ) {
rawError("ANTLR installation corrupted; ANTLR messages format file "+formatName+".stg incomplete");
panic();
}
else if ( !formatOK ) {
setFormat("antlr"); // recurse on this rule, trying the default message format
}
return true;
}
/** Use reflection to find list of MSG_ fields and then verify a
@ -230,18 +325,13 @@ public class ErrorManager {
*/
protected static boolean verifyMessages() {
boolean ok = true;
Field[] fields = ErrorManager.class.getFields();
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
String fieldName = f.getName();
String templateName =
fieldName.substring("MSG_".length(),fieldName.length());
if ( fieldName.startsWith("MSG_") ) {
if ( !messages.isDefined(templateName) ) {
System.err.println("Message "+templateName+" in locale "+
locale+" not found");
ok = false;
}
ErrorType[] errors = ErrorType.values();
for (int i = 0; i < errors.length; i++) {
ErrorType e = errors[i];
if ( !messages.isDefined(e.toString()) ) {
System.err.println("Message "+e.toString()+" in locale "+
locale+" not found");
ok = false;
}
}
// check for special templates
@ -287,6 +377,8 @@ public class ErrorManager {
}
public static void panic() {
// can't call tool.panic since there may be multiple tools; just
// one error manager
throw new Error("ANTLR ErrorManager panic");
}
}

View File

@ -54,7 +54,6 @@ public enum ErrorType {
ERROR_CREATING_ARTIFICIAL_RULE(ErrorSeverity.ERROR, true, true),
TOKENS_FILE_SYNTAX_ERROR(ErrorSeverity.ERROR, true, true),
CANNOT_GEN_DOT_FILE(ErrorSeverity.ERROR, true, true),
BAD_AST_STRUCTURE(ErrorSeverity.ERROR, true, true),
// Code generation errors
MISSING_CODE_GEN_TEMPLATES(ErrorSeverity.ERROR, false, true),
@ -125,7 +124,7 @@ public enum ErrorType {
WILDCARD_AS_ROOT(ErrorSeverity.ERROR, true, true),
CONFLICTING_OPTION_IN_TREE_FILTER(ErrorSeverity.ERROR, true, true),
/** Documentation comment is unterminated */
UNTERMINATED_DOC_COMMENT(ErrorSeverity.ERROR, true, true),
//UNTERMINATED_DOC_COMMENT(ErrorSeverity.ERROR, true, true),
// Dependency sorting errors
//
@ -135,33 +134,33 @@ public enum ErrorType {
// Simple informational messages
//
/** A standby generic message that jsut spits out the arguments it is given */
GENERIC_INFO(ErrorSeverity.INFO, false, false),
/** How to print out the version of the ANTLR tool that we are */
ANTLR_VERSION(ErrorSeverity.INFO, false, false),
// Command line tool errors/warnings
/** -fo option was incorrectly formed */
MISSING_OUTPUT_FO(ErrorSeverity.WARNING, false, false),
/** -lib option is missing a directory argument */
MISSING_LIBDIR(ErrorSeverity.WARNING, false, false),
/** -format option was not given the name of a message format */
MISSING_FORMAT(ErrorSeverity.WARNING, false, false),
/** Max state count missing from the option */
MISSING_MAXSTATES(ErrorSeverity.WARNING, false, false),
/** Max labels in a switch argument is missing */
MISSING_MAXSWITCH(ErrorSeverity.WARNING, false, false),
/** Min labels in a switch argument is missing */
MISSING_MINSWITCH(ErrorSeverity.WARNING, false, false),
/** Missing recursion limit argument */
MISSING_MAXRECUR(ErrorSeverity.WARNING, false, false),
/** Missing max edges argument */
MISSING_MAXEDGE(ErrorSeverity.WARNING, false, false),
/** Misng ms timeout argument */
MISSING_MAXTIME(ErrorSeverity.WARNING, false, false),
// Help messages
HELP_USAGE(ErrorSeverity.INFO, false, false),
HELP_EXTENDED(ErrorSeverity.INFO, false, false),
// GENERIC_INFO(ErrorSeverity.INFO, false, false),
// /** How to print out the version of the ANTLR tool that we are */
// ANTLR_VERSION(ErrorSeverity.INFO, false, false),
//
// // Command line tool errors/warnings
// /** -fo option was incorrectly formed */
// MISSING_OUTPUT_FO(ErrorSeverity.WARNING, false, false),
// /** -lib option is missing a directory argument */
// MISSING_LIBDIR(ErrorSeverity.WARNING, false, false),
// /** -format option was not given the name of a message format */
// MISSING_FORMAT(ErrorSeverity.WARNING, false, false),
// /** Max state count missing from the option */
// MISSING_MAXSTATES(ErrorSeverity.WARNING, false, false),
// /** Max labels in a switch argument is missing */
// MISSING_MAXSWITCH(ErrorSeverity.WARNING, false, false),
// /** Min labels in a switch argument is missing */
// MISSING_MINSWITCH(ErrorSeverity.WARNING, false, false),
// /** Missing recursion limit argument */
// MISSING_MAXRECUR(ErrorSeverity.WARNING, false, false),
// /** Missing max edges argument */
// MISSING_MAXEDGE(ErrorSeverity.WARNING, false, false),
// /** Misng ms timeout argument */
// MISSING_MAXTIME(ErrorSeverity.WARNING, false, false),
//
// // Help messages
// HELP_USAGE(ErrorSeverity.INFO, false, false),
// HELP_EXTENDED(ErrorSeverity.INFO, false, false),
;

View File

@ -0,0 +1,30 @@
package org.antlr.v4.tool;
import org.antlr.runtime.Token;
/** A problem with the symbols and/or meaning of a grammar such as rule
* redefinition.
*/
public class GrammarSemanticsMessage extends Message {
public Grammar g;
/** Most of the time, we'll have a token such as an undefined rule ref
* and so this will be set.
*/
public Token offendingToken;
public GrammarSemanticsMessage(ErrorType etype,
Grammar g,
Token offendingToken,
Object... args)
{
super(etype,args);
this.g = g;
if ( g!=null ) file = g.fileName;
this.offendingToken = offendingToken;
if ( offendingToken!=null ) {
line = offendingToken.getLine();
column = offendingToken.getCharPositionInLine();
}
}
}

View File

@ -1,19 +1,12 @@
package org.antlr.v4.tool;
import org.stringtemplate.ST;
import org.stringtemplate.v4.ST;
/** */
public class Message {
// msgST is the actual text of the message
public ST msgST;
// these are for supporting different output formats
public ST locationST;
public ST reportST;
public ST messageFormatST;
public ErrorType errorType;
public Object[] args;
public Throwable e;
// used for location template
public String file;
public int line = -1;
@ -40,19 +33,16 @@ public class Message {
* a Message.
*/
public ST getMessageTemplate() {
return ErrorManager.getMessageTemplate(errorType);
}
public String toString() {
// setup the location
locationST = ErrorManager.getLocationFormat();
reportST = ErrorManager.getReportFormat();
messageFormatST = ErrorManager.getMessageFormat();
ST messageST = getMessageTemplate();
ST messageST = ErrorManager.getMessageTemplate(errorType);
ST locationST = ErrorManager.getLocationFormat();
ST reportST = ErrorManager.getReportFormat();
ST messageFormatST = ErrorManager.getMessageFormat();
if ( args!=null ) { // fill in arg1, arg2, ...
for (int i=0; i<args.length; i++) {
messageST.add("args"+(i+1), args[i]);
String attr = "arg";
if ( i>0 ) attr += i + 1;
messageST.add(attr, args[i]);
}
}
if ( e!=null ) {
@ -82,8 +72,10 @@ public class Message {
}
reportST.add("message", messageFormatST);
reportST.add("type", errorType.getSeverity());
return reportST.toString();
return messageST;
}
public String toString() {
return getMessageTemplate().render();
}
}

View File

@ -40,7 +40,7 @@ import org.antlr.v4.tool.Message;
import org.junit.Before;
import org.junit.After;
import org.junit.Assert;
import org.stringtemplate.ST;
import org.stringtemplate.v4.ST;
import java.io.*;
import java.util.*;