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

如何处理多分隔符与空语句?ANTLR算术语法优化咨询

算术表达式解析的ANTLR语法优化建议

示例输入

1+1
2+2; 2+4;
;

5+5
5+7

现有ANTLR语法

grammar Calc;

program
    : expressions
    ;

expressions
    : expression (SEPARATOR expression)* SEPARATOR*
    ;

expression
    : '(' expression ')'            // parenExpression has highest precedence
    | expression MULDIV expression  // then multDivExpression
    | expression ADDSUB expression  // then addSubExpression
    | OPERAND                       // finally the operand itself
    ;

MULDIV
    : [*/]
    ;

ADDSUB
    : [-+]
    ;

// 12 or .12 or 2. or 2.38
OPERAND
    : [0-9]+ ('.' [0-9]*)?
    | '.' [0-9]+
    ;

SEPARATOR
    : [\n;]+
    ;

关于SEPARATOR的优化方案

当前把连续的\n和;合并为单个SEPARATOR令牌的写法虽然能运行,但逻辑不够直观,也不利于后续扩展(比如需要区分分号和换行的场景)。更清晰的定义方式是拆分令牌职责:

  1. 单独定义空白字符(空格、制表符等)并跳过,避免干扰表达式解析
  2. 将单个;或\n作为独立的分隔符令牌

修改后的令牌规则如下:

// 跳过空格、制表符等空白(换行除外,因为换行是分隔符)
WS : [ \t]+ -> skip;

// 单个分号或换行作为分隔符
SEPARATOR : ';' | '\n';

这种方式的优势:

  • 令牌职责单一,逻辑清晰,便于维护和调试
  • 后续如果需要针对分号/换行做不同处理(比如语法校验),可以直接区分令牌类型
  • 避免将混合的分隔符(比如;\n)当成一个令牌,符合常规的语法设计习惯

关于expressions规则的合理性分析

原规则expression (SEPARATOR expression)* SEPARATOR*在逻辑上是可行的,但结合优化后的SEPARATOR定义,需要做一点调整:

因为单个SEPARATOR是独立令牌,连续的分隔符需要用+匹配,所以修改为:

expressions
    : expression (SEPARATOR+ expression)* SEPARATOR*
    ;

如果想进一步简化,也可以写成更灵活的形式:

expressions
    : (expression SEPARATOR*)*
    ;

这种写法会匹配零个或多个表达式,每个表达式后面可以跟任意数量的分隔符,自动忽略连续的分隔符(因为没有表达式的分隔符不会触发expression匹配)。如果需要确保解析覆盖整个输入,建议加上EOF:

expressions
    : (expression SEPARATOR*)* EOF
    ;

原规则的核心逻辑是合理的——允许表达式之间用分隔符分隔,同时忽略开头/结尾的多余分隔符。优化后的写法只是让规则更贴合清晰的令牌定义,逻辑一致性更强。


内容的提问来源于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 22:18:10