基于表达式的计算器 ExprEval
答:如图所示,显然这个语法存在二义性,因为对于 1+1*1
可以构造出两棵parsing tree。ExprEval可以使用OOP运算符优先文法处理表达式。
本程序的用到的Token
有:
- 数值类型的常量 Number := [0‐9]+(.[0‐9]+)?(e(+|‐)?[0‐9]+)?
- 布尔类型的常量
Bool := true|false - 运算符 Sign := [+‐*/^()!&|?:>=<]
- 预定义运算符 Func := max|min|sin|cos
- 标点符号 Sign := [,]
其中, 除了运算符和预定义运算符属于同一类外,其余符号各自为类,对于预定义函数名和布尔常量的识别问题,只需要按照本文2.2的状态转换图3,逐个判断其字符即可,而为了处理科学记数法表示的数值常量以及处理字符串的边界等,依然需要按照状态转换图去编程。
其余关键字直接进行字符匹配,其状态转换图形式类比下图min
的状态转换图。
其他直接进行字母归类
表格注释:
- 右结合意味着该运算符遇到自身的时候是做shift操作。左结合则是reduce操作
(
的优先级最低,而)
的优先级最高,
也是一个Token,所以必须具有优先级。其优先级等同于(
- Re代表6个关系运算合集
- 对于减号和负号,在scanner阶段获取token就进行判断,记录下前一个获取到token的类型,若前一个token为
decimal
或)
, 则判定-
为减号,否则判定为负号。