【问题标题】:How to walk the parse tree to check for syntax errors in ANTLR如何遍历解析树以检查 ANTLR 中的语法错误
【发布时间】:2023-03-04 15:17:01
【问题描述】:

我在 ANTLR 中编写了一种相当简单的语言。在实际解释用户编写的代码之前,我希望解析代码并检查语法错误。如果发现我希望输出错误的原因并退出。如何检查代码中的语法错误并输出相应的错误。请注意,出于我的目的,类似于 ANTLR 工具生成的错误语句已经绰绰有余。例如

line 3:0 missing ';'

【问题讨论】:

  • 好吧,只需通过您生成的解析器运行查询并从中获取错误消息。

标签: parsing syntax-error grammar antlr4


【解决方案1】:

您可以使用 ErrorListener 获取更多信息。

例如:

...
FormulaParser parser = new FormulaParser(tokens);
parser.IsCompletion = options.IsForCompletion;
ErrorListener errListener = new ErrorListener();
parser.AddErrorListener(errListener);
IParseTree tree = parser.formula();

您唯一需要做的就是将 ErrorListener 附加到解析器。 这是ErrorListener的代码。

    /// <summary>
    /// Error listener recording all errors that Antlr parser raises during parsing.
    /// </summary>
    internal class ErrorListener : BaseErrorListener
    {
        private const string Eof = "the end of formula";

        public ErrorListener()
        {
            ErrorMessages = new List<ErrorInfo>();
        }

        public bool ErrorOccured { get; private set; }
        public List<ErrorInfo> ErrorMessages { get; private set; }

        public override void SyntaxError(IRecognizer recognizer, IToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e)
        {
            ErrorOccured = true;

            if (e == null || e.GetType() != typeof(NoViableAltException))
            {
                ErrorMessages.Add(new ErrorInfo() 
                { 
                    Message = ConvertMessage(msg), 
                    StartIndex = offendingSymbol.StartIndex,
                    Column = offendingSymbol.Column + 1, 
                    Line = offendingSymbol.Line, 
                    Length = offendingSymbol.Text.Length
                });
                return;
            }

            ErrorMessages.Add(new ErrorInfo() 
            { 
                Message = string.Format("{0}{1}", ConvertToken(offendingSymbol.Text), " unexpected"), 
                StartIndex = offendingSymbol.StartIndex,
                Column = offendingSymbol.Column + 1, 
                Line = offendingSymbol.Line,
                Length = offendingSymbol.Text.Length
            });
        }

        public override void ReportAmbiguity(Antlr4.Runtime.Parser recognizer, DFA dfa, int startIndex, int stopIndex, bool exact, BitSet ambigAlts, ATNConfigSet configs)
        {
            ErrorOccured = true;
            ErrorMessages.Add(new ErrorInfo()
                              {
                                  Message = "Ambiguity", Column = startIndex, StartIndex = startIndex
                              });
            base.ReportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs);
        }

        private string ConvertToken(string token)
        {
            return string.Equals(token, "<EOF>", StringComparison.InvariantCultureIgnoreCase) 
                ? Eof 
                : token;
        }

        private string ConvertMessage(string message)
        {
            StringBuilder builder = new StringBuilder(message);
            builder.Replace("<EOF>", Eof);
            return builder.ToString();
        }
    }

这是一个虚拟的监听器,但你可以看到它的作用。并且您可以判断错误是语法错误还是一些歧义错误。解析后可以直接询问errorListener,是否有错误发生。

【讨论】:

  • 能否详细说明。我是初学者,如果你能给我一些例子或指出从哪里开始,那将非常有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
  • 2016-11-09
  • 1970-01-01
  • 2021-08-15
相关资源
最近更新 更多