- 如何在字符串列表中获取 Antlr 的所有解析错误?
我按如下方式使用 antlr:
ANTLRInputStream input = new ANTLRInputStream(System.in);
grLexer lexer = new grLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
grParser parser = new grParser(tokens);
ParseTree tree = parser.formula();
System.out.println(tree.toStringTree(parser));
例如
line 1:0 token recognition error at: '('
line 1:1 token recognition error at: ')'
line 1:2 token recognition error at: '('
- 如何确定解析已执行而没有错误?如果只有一个解析错误,我会停止。
例如
if(tree.hasError()) // FOR EXAMPLE
return;
-
您需要提供
ANTLRErrorListener
的实现,以收集有关发生的错误的信息。例如,IntelliJ 插件使用其SyntaxErrorListener
来跟踪此信息。 -
您可以在解析完成后检查
Parser.getNumberOfSyntaxErrors()
以查看是否发生了错误。请注意,这不会报告来自词法分析器的错误。确保正确报告所有错误的最佳方法是编写词法分析器,使其本身永远不会遇到语法错误,而是将无效标记传递给解析器进行处理。
与Sam Harwell
描述的方式类似,以下代码演示了在调用分析器规则(如C
分析器functionDefinition
)后获取语法错误列表:
语法检查器:
import c.grammar.CLexer;
import c.grammar.CParser;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import java.util.List;
import static org.antlr.v4.runtime.CharStreams.fromString;
public class CSyntaxChecker
{
public static List<SyntaxError> getSyntaxErrors(String sourceCode)
{
CodePointCharStream inputStream = fromString(sourceCode);
CLexer lexer = new CLexer(inputStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
CParser parser = new CParser(commonTokenStream);
SyntaxErrorListener listener = new SyntaxErrorListener();
parser.addErrorListener(listener);
parser.functionDefinition();
return listener.getSyntaxErrors();
}
}
语法错误侦听器:
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.misc.Utils;
import java.util.ArrayList;
import java.util.List;
public class SyntaxErrorListener extends BaseErrorListener
{
private final List<SyntaxError> syntaxErrors = new ArrayList<>();
SyntaxErrorListener()
{
}
List<SyntaxError> getSyntaxErrors()
{
return syntaxErrors;
}
@Override
public void syntaxError(Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line, int charPositionInLine,
String msg, RecognitionException e)
{
syntaxErrors.add(new SyntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e));
}
@Override
public String toString()
{
return Utils.join(syntaxErrors.iterator(), "n");
}
}
语法错误:
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
public class SyntaxError
{
private final Recognizer<?, ?> recognizer;
private final Object offendingSymbol;
private final int line;
private final int charPositionInLine;
private final String message;
private final RecognitionException e;
SyntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
{
this.recognizer = recognizer;
this.offendingSymbol = offendingSymbol;
this.line = line;
this.charPositionInLine = charPositionInLine;
this.message = msg;
this.e = e;
}
public Recognizer<?, ?> getRecognizer()
{
return recognizer;
}
public Object getOffendingSymbol()
{
return offendingSymbol;
}
public int getLine()
{
return line;
}
public int getCharPositionInLine()
{
return charPositionInLine;
}
public String getMessage()
{
return message;
}
public RecognitionException getException()
{
return e;
}
}