Antlr4 区分“减号”运算符和负号

最近用Antlr4开发解释器,在识别带减号“-”的表达式遭遇语法错误,例如

a = 2-1

原因是将“2-1”识别为了2和-1两个token,而我的预期是2、-、1三个token
当然,我也知道之所以这样识别,是因为我定义数字字面量的规则时,支持负号

LiteralInt: '-'?[0-9]+;

当然,我也可以通过如下语法规避此问题,即负号和1之间加个空格,但这样毕竟不易用

a = 2 - 1

我在token规则层面上想了好久都没有解决办法,后来我想到了查看一下python解释器是如何区分的,这也让我找到了答案

import ast

root = ast.parse("a=2-1")
root1 = ast.parse("a=1")
root2 = ast.parse("a=-1")
print(ast.dump(root))
print(ast.dump(root1))
print(ast.dump(root2))

结果如下:

Module(body=[Assign(targets=[Name(id='a', ctx=Store())], value=BinOp(left=Constant(value=2), op=Sub(), right=Constant(value=1)))], type_ignores=[])
Module(body=[Assign(targets=[Name(id='a', ctx=Store())], value=Constant(value=1))], type_ignores=[])
Module(body=[Assign(targets=[Name(id='a', ctx=Store())], value=UnaryOp(op=USub(), operand=Constant(value=1)))], type_ignores=[])

通过三个表达式的解析结果,我发现表达式a=-1中,-1并不是与1一样识别为constant,而是UnaryOp(op=USub(), operand=Constant(value=1)),即一元运算符“-”和常量1

这让我茅塞顿开,马上开始修改我定义的语法

unaryOp: ('+'|'-') expr;
expr
	: constant
	| ...
	;
constant
	: LiteralInt
	| LiteralFloat
	;
// 定义数字字面量,没有负号
LiteralInt: [0-9]+;

至此, 问题解决~

你可能感兴趣的:(ANTLR,python,antlr)