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

如何让ANTLR语法规则更模块化?解决互左递归问题

问题描述

我有如下表达式语法规则,所有逻辑都集中在expr规则中,运行正常:

grammar MyGrammar;

expr
    : '(' expr ')'

    // BoolExressions -- cannot move these out or else get Left-Recursion
    | expr ('=' | '!=') expr
    | expr 'AND' expr
    | expr 'OR' expr

    | ATOM
    ;

ATOM: [a-z]+ | [0-9]+;
WHITESPACE: [ \t\r\n] -> skip;

现在想把布尔表达式相关逻辑拆分成独立的boolExpr规则,方便其他规则单独使用布尔表达式,但拆分后出现相互左递归错误:

grammar MyGrammar;

expr
    : '(' expr ')'
    | boolExpr
    | ATOM
    ;

boolExpr
    : expr ('=' | '!=') expr
    | expr 'AND' expr
    | expr 'OR' expr
    ;

ATOM: [a-z]+ | [0-9]+;

WHITESPACE: [ \t\r\n] -> skip;

// error(119): The following sets of rules are 
// mutually left-recursive [expr, boolExpr]

需要找到合理的拆分方式,实现布尔表达式的独立分离。

解决方案

要解决相互左递归问题,核心是打破expr和boolExpr的循环引用,同时明确语法层级和运算优先级,重构后的语法如下:

grammar MyGrammar;

// 顶层表达式:可直接使用布尔表达式或基础表达式
expr
    : boolExpr
    | primaryExpr
    ;

// 独立的布尔表达式规则,仅处理布尔运算
boolExpr
    : primaryExpr ('=' | '!=') primaryExpr
    | boolExpr 'AND' primaryExpr
    | boolExpr 'OR' primaryExpr
    ;

// 基础表达式单元:原子值和括号包裹的任意表达式
primaryExpr
    : ATOM
    | '(' expr ')'
    ;

ATOM: [a-z]+ | [0-9]+;
WHITESPACE: [ \t\r\n] -> skip;

关键说明

  • 层级拆分:

    • primaryExpr作为最基础的表达式单元,包含原子值和括号嵌套的任意表达式(保证括号可以包裹布尔表达式或普通表达式)
    • boolExpr仅处理布尔运算,通过左递归定义保证AND/OR的左结合性(符合常规运算逻辑),操作数使用primaryExpr避免和expr形成循环引用
    • expr作为顶层入口,兼容布尔表达式和基础表达式,其他规则如果只需要布尔表达式,直接引用boolExpr即可
  • 规避左递归:
    原错误源于expr和boolExpr互相引用形成循环,现在让布尔表达式的操作数指向优先级更高的primaryExpr,彻底打破循环,同时ANTLR支持规则内部的左递归(如boolExpr 'AND' primaryExpr这种形式是合法的)

  • 语义兼容:
    重构后的语法完全兼容原规则的所有合法输入,同时实现了布尔表达式的独立分离,满足"其他规则单独使用布尔表达式"的需求。

内容的提问来源于stack exchange,提问作者carl.hiass

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 07:18:20