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

ANTLR中如何为多行语句复用解析规则?报错求助

解决ANTLR多行语句解析错误的方案

我帮你梳理下问题根源和解决办法:

问题核心原因

你遇到的错误line 2:0 extraneous input 'SafetyGoal' expecting {, 'AND', 'OR'},本质是入口规则调用错误:
你在代码里调用的是parser.expr(),但这个规则只能解析单个表达式。当输入有多行多个独立的顶层元素(比如第二行的SafetyGoal)时,解析完第一个expr后,剩余输入无法被expr规则匹配,因此抛出“多余输入”的错误。

你的语法里其实定义了正确的顶层规则condition((expr+)? EOF),但它的设计存在缺陷:没有明确支持多个独立表达式的分隔逻辑(比如换行),而且你也没在代码里调用它。


步骤1:修正语法规则

调整语法,明确支持多行独立语句,同时修复几个小问题:

grammar Condition;

// 顶层规则:处理整个输入,允许多个语句(每行一个)
condition : (statement NEWLINE*)+ EOF | EOF;

// 单个语句对应原来的表达式
statement : expr;

// 保留原表达式逻辑,修复重复的标签名
expr : expr And expr # andExpr
     | expr Or expr # orExpr
     | LPar expr RPar # parExpr
     | prop MIN Numerical expr # eqExpr
     | prop some expr # someExpr
     | prop only expr # onlyExpr
     | prop value dataValue # valueExpr
     | id # idExpr
     | not id # notExpr; // 原规则重复使用idExpr标签,改为notExpr区分

id : Identifier;
prop: Identifier;
dataValue: Identifier;

/* Lexical Tokens */
And : 'AND';
Or : 'OR';
LPar : '(';
RPar : ')';
Equals : '=';
some : 'some';
only : 'only';
MIN : 'MIN';
value: 'value';
not: 'not';
NEWLINE: '\n'; // 不再跳过换行,用作语句分隔符
Numerical : [1-9] [0-9]*;
Data : 'true' | 'false' | 'A' | 'B' | 'C' | 'D' ; // 修复原写法:[true]是字符集,改为字符串字面量
Identifier : [a-zA-Z_] [a-zA-Z0-9_]*;
WhiteSpace : [ \t\r]+ -> channel(HIDDEN); // 移除换行,交给NEWLINE处理
InvalidChar : .;

关键修改点:

  • 新增statement规则,将每行视为一个独立语句
  • 顶层condition规则改为匹配多个statement,用换行分隔
  • 修复Data规则的错误写法(原[true]会匹配单个t/r/u/e字符)
  • 修复expr规则里重复的标签名,避免ANTLR编译报错
  • 不再跳过换行,而是将其作为语句分隔符保留

步骤2:修正调用代码

将入口规则从expr()改为顶层的condition(),这样才能解析整个多行输入:

Stream<String> stream = Files.lines(Paths.get("C:\\test\\RulesTest.txt"), StandardCharsets.UTF_8);
stream.forEach(s -> contentBuilder.append(s).append("\n"));
String input = contentBuilder.toString();
InputStream inStream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8));
org.antlr.v4.runtime.ANTLRInputStream in = new org.antlr.v4.runtime.ANTLRInputStream(inStream);
System.out.println("These are the lines:" + contentBuilder);
ConditionLexer lexer = new ConditionLexer(in);
org.antlr.v4.runtime.CommonTokenStream tokens = new org.antlr.v4.runtime.CommonTokenStream(lexer);
ConditionParser parser = new ConditionParser(tokens);
ParseTree tree = parser.condition(); // 这里改为调用condition()而非expr()
MyVisitor vis = new MyVisitor();
vis.visit(tree);

额外说明

如果你的多行输入是单个跨多行的表达式(比如一个长表达式拆成多行书写),那不需要修改语法,只需要把入口规则改成parser.condition()即可——因为原condition规则已经包含EOF,且空格(含换行)会被隐藏通道处理,跨多行的表达式会被正确解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:49:21