如何让二元+运算符优先级高于带符号数字以解决词法歧义?
解决词法分析中数字符号与二元运算符的歧义问题
问题描述
当前语法支持带正负号的数字格式:
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
相关产品推荐
相关产品推荐

