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

基于LALR(1)的Lark数学解析器添加隐式乘法的问题

解决Lark LALR(1)解析器中隐式乘法与减法的歧义问题

我之前用Lark构建数学解析器时也踩过这个坑——直接把乘法运算符*设为可选会让LALR(1)解析器混淆二元减法和一元负号的上下文,导致x-y被错误解析成x*-y。核心原因是隐式乘法的优先级高于减法,解析器会优先选择更高优先级的规则,把减号当成一元负号处理,进而触发隐式乘法。

解决方案:重新梳理规则层次,明确上下文区分

我们需要调整语法规则,让二元减法的触发优先级高于隐式乘法的错误匹配,同时保证隐式乘法只在合理的上下文(比如变量、数字、括号表达式相邻)中触发。以下是修改后的完整语法:

?start: expression
?expression: sub

# 处理加减运算:允许表达式以一元运算开头,后续用二元加减连接项
?sub: unary | plus (MINUS plus)*
?plus: times (PLUS times)*

# 处理乘除运算:同时支持显式*和隐式拼接的乘法
?times: factor ( (STAR | "") factor )*
?divide: power (SLASH power)?

# 处理幂运算
?power: atom (CARET atom)*

# 一元正负号:作用于完整的加减表达式,避免和前面的表达式触发隐式乘法
?unary: MINUS plus | PLUS plus

# 原子表达式:括号、数字、变量
?atom: "(" expression ")" | numeric | symbol

# 基础类型与运算符定义
numeric: FLOAT | INT
symbol: WORD
MINUS: "-"
PLUS: "+"
STAR: "*"
SLASH: "/"
CARET: "^"

%import common.WORD
%import common.INT
%import common.FLOAT
%import common.WS_INLINE
%ignore WS_INLINE

关键细节解释

  1. 二元减法的正确匹配:
    sub规则分为两种情况:要么是一个一元运算表达式(比如-x+y开头的-x),要么是用二元-连接的多个plus项。当解析x-y时,解析器会优先匹配plus (MINUS plus)*,把-当成连接x和y的二元减法运算符,而非一元负号。

  2. 隐式乘法的合理触发:
    times规则限定隐式乘法只能发生在两个factor之间,而factor是幂运算或括号表达式(不包含一元负号开头的表达式)。只有当变量、数字、括号表达式相邻时,才会触发隐式乘法,比如xy、x(1+2)、(x+y)z都能正确识别为乘法,而x-y不会被误解析。

  3. 一元负号的上下文限制:
    unary规则让一元正负号作用于完整的plus表达式(加减项),确保它只会出现在表达式的开头,或者在+、-、*等运算符之后,不会和前面的表达式触发隐式乘法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 17:02:39