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

如何让二元+运算符优先级高于带符号数字以解决词法歧义?

解决词法分析中数字符号与二元运算符的歧义问题

问题描述

当前语法支持带正负号的数字格式:

2
+2.5
-2.7

但词法分析时,输入如2+2.5会被错误识别为两个token:

`2` -- number
`+2.5` -- number

无法正确识别出二元+运算符,导致表达式解析错误。

当前相关解析器代码

parser grammar DBParser;
options { tokenVocab = DBLexer;}

root
    : selectStatement? (SEMI selectStatement)* SEMI EOF?    // for testing only
    ;

selectStatement
    : SELECT selectItem (COMMA selectItem)* COMMA?
    ;

selectItem
    : expr (AS? IDENTIFIER)?
    ;

expr
    : atom
    | atom PLUS expr
    ;

atom
    : NUMBER
    | STRING
    ;

测试输入

SELECT 1;
SELECT 1+2;
SELECT +3, -2;
SELECT 'hello' AS word;
SELECT 'hello' word;
SELECT 'hello' word, 1, 3,;

解决方案

核心思路是不在数字token中包含正负号,将符号单独作为一元/二元运算符处理,具体步骤如下:

1. 修改词法分析器(DBLexer)

调整NUMBER规则,仅匹配无符号数字(如2、2.5),将+和-单独定义为PLUS、MINUS运算符token。

2. 调整解析器规则,区分一元与二元运算符

在表达式规则中优先定义一元运算符(优先级更高),再定义二元运算符,确保解析器能正确区分两种场景:

parser grammar DBParser;
options { tokenVocab = DBLexer;}

root
    : selectStatement? (SEMI selectStatement)* SEMI EOF?    // for testing only
    ;

selectStatement
    : SELECT selectItem (COMMA selectItem)* COMMA?
    ;

selectItem
    : expr (AS? IDENTIFIER)?
    ;

// 一元运算符优先级高于二元运算符,因此先定义
expr
    : atom
    | PLUS expr       // 一元正号:匹配开头的+,如+3
    | MINUS expr      // 一元负号:匹配开头的-,如-2
    | expr PLUS expr  // 二元加号:匹配两个表达式之间的+,如1+2
    ;

atom
    : NUMBER
    | STRING
    ;

效果说明

修改后,输入2+2.5会被词法分析拆分为2(NUMBER)、+(PLUS)、2.5(NUMBER)三个token,解析器会优先匹配二元PLUS规则,正确解析为1 + 2的表达式;而+3、-2这类开头带符号的输入,会被解析为一元运算符作用于数字,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 21:27:28