使用antlr4解析百分比表达式

时间:2013-09-21 23:48:00

标签: parsing antlr antlr4

我试图用ANTLR4解析代数表达式。我尝试用解析器完成的一个功能是"智能"处理百分比表达式。

修改:目标是让餐厅的折扣或小费更容易计算。例如。如果你看到广告" 30%折扣"你可以输入价格 - 30%"并得到正确的结果。或者在餐馆,您可以输入您的餐点价格加15%并获得您需要支付的金额,包括15%的小费。但是,只有当表达式看起来像"表达式1( - 或+)表达式2"时才会出现这种解释。在所有其他情况下,百分号应该像往常一样解释。 Google搜索框计算器的行为与此类似。 /编辑

100-30%应该返回 70
100-(20+10)%也应该返回 70
3+(100-(20+10)%)应返回 73

5%应返回 0.05
(5+5)%应返回 0.10

我的语法看起来像这样:

expr:
 e EOF   
;

e:
   '-'a=e                          
 | '(' a=e ')'                     
 | a=e op=(ADD|SUB) b=e '%'        
 | a=e op=(ADD|SUB) b=e            
 | a=e'%'                          //**PERCENTRULE**
 | FLT                             
 ;

ADD :  '+' ;
SUB :  '-' ;
FLT: [0-9]+(('.'|',')[0-9]+)?;
NEWLINE:'\r'? '\n' ;
WS : [ \t\n]+ -> skip ;

对于表达式100-30%,我期望这棵树:
Expected parse tree for the expression "100-30%"

但我明白了:
parse tree for the expression "100-30%
如何获取正确的树(不删除PERCENTRULE)?

1 个答案:

答案 0 :(得分:0)

我删除了原来基于语法的答案,因为我意识到我对你想要完成什么样的处理有一个非常不同的想法。听起来您希望X op Y %形式的任何内容成为X * (1 op (Y/100))。那是准确的吗?

  

我尝试使用解析器完成的一项功能是对表达式百分比进行“智能”处理:

你确定你的规格足够坚固甚至可以开始编码吗?这对我来说看起来很混乱,特别是因为%更像是一个单位指定。

例如,我原本期望50-30%成为以下任何一种:

  • (50 - 0.3) = 49.3
  • (50 - 30) / 100 = 0.20

...但你所要求的还是陌生的:50 * (1 - 0.3) = 35

这开启了额外的怪异。这两个都不是真的吗?

  • 0+5%将成为0 * (1 + 0.05) = 0
  • 5%将成为5 / 100 = 0.05

这很奇怪,因为加零通常不会改变数字的含义。


限制性更强的版本

好吧,只有在用户避免歧义时才允许基于百分比的更改?一种方法是创建新的二元运算符,如A -% BA +% B,但这不是以人为中心的,那么如何:

expr: e EOF ;

e
 : SUB e                          
 | parenExpr
 | percentOp        
 | binaryOp
 | FLT                             
 ;
parenExpr
 : LPAREN e RPAREN
 ;
percentOp
 : (FLT|parenExpr) (ADD|SUB) (FLT|parenExpr) PCT
 ;
binaryOp
 : e (ADD|SUB|MUL|DIV) e
 ;

PCT : '%';
LPAREN : '(';
RPAREN : ')';
ADD :  '+' ;
SUB :  '-' ;
MUL :  '*' ;
DIV :  '/' ;
FLT: [0-9]+(('.'|',')[0-9]+)?;
NEWLINE:'\r'? '\n' ;
WS : [ \t\n]+ -> skip ;

这意味着:

  • 50-5-4%被视为100-(5-4%)以获得45.2。
  • 5%无效(单独使用)
  • 5%+4无效