package org.deved.antlride.runtime; import java.lang.reflect.Field; import java.lang.reflect.Method; import antlr.FileLineFormatter; import antlr.MismatchedTokenException; import antlr.NoViableAltException; import antlr.RecognitionException; import antlr.Token; import antlr.TokenStreamRecognitionException; import org.antlr.tool.ANTLRErrorListener; import org.antlr.tool.ErrorManager; import org.antlr.tool.GrammarSemanticsMessage; import org.antlr.tool.GrammarSyntaxMessage; import org.antlr.tool.Message; import org.antlr.tool.ToolMessage; public class AntlrErrorListener extends FileLineFormatter implements ANTLRErrorListener { private static final int ERROR = Integer.parseInt(System.getProperty( "gERROR", "0")); private static final int WARNING = Integer.parseInt(System.getProperty( "gWARNING", "1")); private static final String PATTERN = System.getProperty("gPATTERN"); private static final String LINE_ESCAPE = System .getProperty("gLINE_ESCAPE"); private static final String CRETURNS_ESCAPE = System .getProperty("gCREUTRNS_ESCAPE"); private static final boolean includeStacktrace = Boolean .parseBoolean(System.getProperty("gINCLUDE_STACKTRACE", "false")); private static final String FILE = System.getProperty("gFILE"); /** * Since 3.4 ANTLR use org.antlr.runtime.Token instead of * antlr.Token. This class acts like a dynamic binding between the two. */ private static class DynamicToken { private Object token; public DynamicToken(Object token) { this.token = token; } public Object invokeMethod(String name) { try { Method method = token.getClass().getMethod(name, new Class[0]); return method.invoke(token, new Object[0]); } catch (Exception e) { throw new IllegalStateException(e); } } public int getLine() { return ((Integer) invokeMethod("getLine")).intValue(); } public int getColumn() { try { return ((Integer) invokeMethod("getColumn")).intValue(); } catch (IllegalStateException ex) { return ((Integer) invokeMethod("getCharPositionInLine")) .intValue(); } } public String getText() { return ((String) invokeMethod("getText")); } public static DynamicToken offendingToken(Object source) { try { Field field = source.getClass().getDeclaredField( "offendingToken"); return new DynamicToken(field.get(source)); } catch (Exception e) { throw new IllegalStateException(e); } } } public AntlrErrorListener() { } public void info(String message) { System.out.println(escapeNL(message)); } public void warning(Message re) { message(re); } public void error(Message re) { message(re); } public void error(ToolMessage message) { message(message); } private void message(Message re) { String message = ErrorManager.getMessageType(re.msgID); if (message.startsWith("error")) { report(ERROR, re); } else { report(WARNING, re); } } private void report(int severity, Message message) { // first call Message.toString, toString method update location info String strMessage = getMessage(message, message.msgID); // retrive location int line = message.line > 0 ? message.line : -1; int column = message.column > 0 ? message.column : 0; int start = 0; int end = 0; int offset = 0; int id = message.msgID; DynamicToken token = extractToken(message); if (token != null) { line = token.getLine(); column = token.getColumn(); if (token.getText() != null) offset = token.getText().length(); } report(severity, id, line, column, start, end, offset, strMessage); } private String escapeNL(String s) { return s == null ? "" : s.replaceAll("\n", LINE_ESCAPE).replaceAll( "\r", CRETURNS_ESCAPE); } private void report(int severity, int id, int line, int column, int start, int end, int offset, String strMessage) { // encode new line System.out.println(new StringBuffer().append(PATTERN).append(severity) .append(PATTERN).append(id).append(PATTERN).append(line) .append(PATTERN).append(column).append(PATTERN).append(start) .append(PATTERN).append(end).append(PATTERN).append(offset) .append(PATTERN).append(escapeNL(strMessage)).toString()); } private DynamicToken extractToken(Message message) { if (message.e instanceof TokenStreamRecognitionException) { return extractToken(((TokenStreamRecognitionException) message.e).recog); } else if (message instanceof GrammarSyntaxMessage) { return DynamicToken.offendingToken(message); } else if (message instanceof GrammarSemanticsMessage) { return DynamicToken.offendingToken(message); } return null; } private DynamicToken extractToken(RecognitionException rex) { if (rex == null) return null; if (rex instanceof NoViableAltException) { return new DynamicToken(((NoViableAltException) rex).token); } if (rex instanceof MismatchedTokenException) { return new DynamicToken(((MismatchedTokenException) rex).token); } final int line = rex.line; if (line > 0) { int column = rex.column; Token t = new Token(); t.setColumn(column); t.setLine(line); return new DynamicToken(t); } return null; } private String getMessage(Message message, int msgID) { String strMessage = message.toString(); // if (message instanceof ToolMessage) { // ToolMessage toolMessage = (ToolMessage) message; // if (toolMessage.e != null) { // StringTemplate messageTemplate = toolMessage // .getMessageTemplate(); // if (toolMessage.arg != null) { // messageTemplate.setAttribute("arg", toolMessage.arg); // } // if (toolMessage.arg2 != null) { // messageTemplate.setAttribute("arg2", toolMessage.arg2); // } // messageTemplate.setAttribute("exception", toolMessage.e); // if (includeStacktrace) { // messageTemplate.setAttribute("stackTrace", // toolMessage.e.getStackTrace()); // } // strMessage = toolMessage.toString(messageTemplate); // } else { // if (msgID == ErrorManager.MSG_FILE_AND_GRAMMAR_NAME_DIFFER) { // toolMessage.arg2 = FILE; // } else if (msgID == ErrorManager.MSG_NO_RULES) { // toolMessage.arg = FILE; // } // strMessage = message.toString(); // } // } else { // strMessage = message.toString(); // } // // System.out.println(strMessage); return strMessage.trim(); } public String getFormatString(String fileName, int line, int column) { return ""; } }