You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ANTLR语法未定义EOF Token却触发EOF错误及解析规则问题

解答

1. 错误原因

调用parser.name()时,解析器已经消费了所有有效token("John"、空格、"Smith"),此时token流的指针停在了EOF位置。后续再调用parser.firstname()和parser.firstname()时,解析器试图从当前位置(EOF)匹配STRING token,但已经没有可用的token了,因此抛出“missing STRING”的错误。

ANTLR的CommonTokenStream是向前消费的,一旦解析器完成某个规则的匹配,token指针不会自动重置,重复调用解析方法不是正确的用法——解析器的设计是基于完整的语法树来获取结构信息。

2. 正确获取firstname和lastname的方式

你不需要重复调用解析器方法,而是应该从parser.name()返回的语法树节点中提取firstname和lastname的内容,具体有两种常用方式:

方式一:直接访问语法树子节点

解析得到的nameContext包含了对应的firstnameContext和lastnameContext,可以直接获取它们的文本:

var nameContext = parser.name();
var firstName = nameContext.firstname().GetText();
var lastName = nameContext.lastname().GetText();

Console.WriteLine("Person:");
Console.WriteLine($"firstname {firstName}");
Console.WriteLine($"lastname {lastName}");
方式二:使用ANTLR的访问器/监听器(推荐)

对于复杂语法,更规范的方式是实现gdxBaseVisitor或gdxBaseListener来遍历语法树,提取所需信息:

public class NameVisitor : gdxBaseVisitor<string>
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }

    public override string VisitFirstname(gdxParser.FirstnameContext context)
    {
        FirstName = context.GetText();
        return base.VisitFirstname(context);
    }

    public override string VisitLastname(gdxParser.LastnameContext context)
    {
        LastName = context.GetText();
        return base.VisitLastname(context);
    }
}

// 使用示例
var visitor = new NameVisitor();
visitor.Visit(tree);

Console.WriteLine("Person:");
Console.WriteLine($"firstname {visitor.FirstName}");
Console.WriteLine($"lastname {visitor.LastName}");

对应ANTLR书籍章节

在《The Definitive ANTLR 4 Reference》中:

  • 关于语法树的基本使用和获取子节点,参考第4章 Parsing with ANTLR(解析器返回的上下文对象、获取节点文本等内容)。
  • 关于访问器/监听器的使用,参考第5章 Building a Parse Tree and Walking It(遍历语法树的两种模式:访问器和监听器)。

内容的提问来源于stack exchange,提问作者Michael EstrinOne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:50:19