1

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

编辑:目标是使餐厅的折扣或小费计算更容易。例如,如果您看到“30% 折扣”的广告,您可以输入“价格 - 30%”并获得正确的结果。或者在餐厅,您可以输入餐费加上 15%,然后得到您必须支付的金额,包括 15% 的小费。但这种解释只有在表达式看起来像“表达式 1(- 或 +)表达式 2”时才会出现。在所有其他情况下,百分号应照常解释。谷歌搜索框计算器的行为就是这样。/编辑

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%,我希望这棵树:
表达式的预期解析树

但我明白了:
表达式的解析树
我怎样才能得到正确的树(不删除 PERCENTRULE)?

4

1 回答 1

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 -% Bor A +% 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无效
于 2013-09-22T03:43:16.907 回答