gpt4 book ai didi

antlr - 如何捕捉小错误?

转载 作者:行者123 更新时间:2023-12-02 17:06:16 25 4
gpt4 key购买 nike

我有一点 ANTLR v4 语法,我正在用它实现一个访问者。

假设这是一个简单的计算器,每个输入都必须以“;”结尾

e.g. x=4+5;

如果我不放;最后,它也能正常工作,但我得到了终端的输出。

line 1:56 missing ';' at '<EOF>'

似乎它可以找到规则并且或多或少地忽略了丢失的终端“;”。

我更喜欢严格的错误或异常而不是这些软信息。

输出由行生成

ParseTree tree = parser.input ()

有没有一种方法可以加强错误处理并检查此类错误?

最佳答案

是的,你可以。和您一样,我希望对用户提交的文本进行 100% 完美的解析,因此创建了一个严格的错误处理程序,即使是简单的错误也能防止恢复。

第一步是删除默认错误监听器并添加您自己的 STRICT 错误处理程序:

 AntlrInputStream inputStream = new AntlrInputStream(stream);
BailLexer lexer = new BailLexer(inputStream); // TALK ABOUT THIS AT BOTTOM

CommonTokenStream tokenStream = new CommonTokenStream(lexer);
LISBASICParser parser = new LISBASICParser(tokenStream);
parser.RemoveErrorListeners(); // UNHOOK ERROR HANDLER
parser.ErrorHandler = new StrictErrorStrategy(); // REPLACE WITH YOUR OWN
LISBASICParser.CalculationContext context = parser.calculation();
CalculationVisitor visitor = new CalculationVisitor();
visitor.VisitCalculation(context);

这是我的 StrictErrorStrategy 类。它继承自 DefaultErrorStrategy 类并覆盖两个“恢复”方法,这两个方法可以恢复像分号错误这样的小错误:

public class StrictErrorStrategy : DefaultErrorStrategy
{
public override void Recover(Parser recognizer, RecognitionException e)
{
IToken token = recognizer.CurrentToken;
string message = string.Format("parse error at line {0}, position {1} right before {2} ", token.Line, token.Column, GetTokenErrorDisplay(token));
throw new Exception(message, e);
}


public override IToken RecoverInline(Parser recognizer)
{
IToken token = recognizer.CurrentToken;
string message = string.Format("parse error at line {0}, position {1} right before {2} ", token.Line, token.Column, GetTokenErrorDisplay(token));
throw new Exception(message, new InputMismatchException(recognizer));
}


public override void Sync(Parser recognizer) { }
}

重写这两个方法允许您在出现任何解析器错误时停止(在本例中有一个在其他地方捕获的异常)。将 Sync 方法设为空可以防止发生正常的“错误后重新同步”行为。

最后一步是捕获所有 LEXER 错误。为此,您可以创建一个继承自主词法分析器类的新类;它像这样覆盖 Recover() 方法:

public class BailLexer : LISBASICLexer
{
public BailLexer(ICharStream input) : base(input) { }

public override void Recover(LexerNoViableAltException e)
{
string message = string.Format("lex error after token {0} at position {1}", _lasttoken.Text, e.StartIndex);
BasicEnvironment.SyntaxError = message;
BasicEnvironment.ErrorStartIndex = e.StartIndex;
throw new ParseCanceledException(BasicEnvironment.SyntaxError);
}
}

(编辑:在此代码中,BasicEnvironment 是我在应用程序中用来保存设置、错误、结果等的高级上下文对象。因此,如果您决定使用它,要么正如另一位读者在下面评论的那样,或替换为您自己的上下文/容器。)

有了这个,即使是词法分析步骤中的小错误也会被捕获。有了这两个重写的类,我的应用程序的用户必须提供绝对完美的语法才能成功执行。给你!

关于antlr - 如何捕捉小错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51683104/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com