E -> E+T | E-T | T
T -> T*F | T/F | F
F -> i | (E)
如何修改此语法以允许取幂操作^
,以便我可以编写i+i^i*i
?既然我们知道^
的操作顺序更高,那么我所知道的就是我必须使其正确关联。
答案 0 :(得分:8)
在EBNF(Extended Backus-Naur Form)中,这可能如下所示:
expr -> term [ ('+' | '-') term ]*
term -> factor [ ('*' | '/') factor ]*
factor -> base [ '^' exponent ]*
base -> '(' expr ')' | identifier | number
exponent -> '(' expr ')' | identifier | number
(摘自here)
翻译成您的符号(数字和标识符之间没有区别):
E -> E+T | E-T | T
T -> T*F | T/F | F
F -> F^X | B
B -> i | (E)
X -> i | (E)
为了清楚起见,可以合并“B”和“X”。
答案 1 :(得分:3)
对称如下。
E -> E + T | E - T | T
T -> T * F | T / F | X
X -> X ^ Y | Y
Y -> i | (E)
说明:
==========
注意这个语法是明确的。要生成由运算符^
,*
,/
,+
,-
组成的表达式,首先我们需要开始编写较低优先级运算符的步骤,以便可以在较高的+
之前添加-
,*
,/
,^
。然后可以在目标表达式中添加^
。因此,在抽象语法树(parse-tree)中,运算符^
将出现在底部(朝向叶子)。这样,如果我们根据树计算表达式,X -> O ^ Y
将首先执行。
注意:根据语法规则,以感情形式+
,我们无法返回添加-
,E+T | E-T | T
..,但如果您有任何感性形式, i + i ^ i * i
然后我们可以再次添加其他运营商。所以在这种形式的语法中,我们可以控制任何有效表达式(字符串)的生成流属于语法语言。(这是如何在明确的情况下控制运算符优先级)。
例如,为了生成表达式E --> T --> X ---> X ^ Y
,我们不能像X ^ Y
那样,因为一旦有+
,就无法添加-
,{{1} }(不带括号(E)
)。
生成表达式i + i ^ i * i
的可能选择如下:
E --> E - T --> E + T - T --> E + X - T --> E + X ^ Y - T --*--> i+i^i*i
`--*-->` means more than one step
注意操作符^
在最后一步添加(因此可以显示在树的底部,如下图所示):
树将是这样的:
E
/ | \
/ | \
E - T <-- - evaluates 3rd
/ | \ '
/ | \ '
E + T i <-- + evaluates 2nd
' |
' |
i X
/ | \
/ | \
X ^ Y <-- ^ evaluates first
' '
' '
i i
NOTE:
in tree ' means more than one steps
'
^ has higher precedence
because of Left to right associativity + evaluated before then -
当您开始评估此树时,将首先评估^
。
记住高优先级运算符总是在底部添加,因此语法应该是以后可以添加运算符(在句子合成中)。
(你应该理解为什么你的语法+
和-
可以通过E
和T
直接生成,你可以添加{{ 1}},*
。为什么其他明确的版本/
,E -> E*T | E/T | T
不正确!这个语法生成的语言和你的语法是等价的。原因是你的语法生成了正确的树从评估角度来看)
此外,如果您正在使用YACC工具编写解析器。你可以使用这个语法的模糊版本,生成规则数量较少,并在语法规则之外指定运算符优先级(这将大致了解首先要评估哪个运算符,因此应该如何构建树)。这将是比这种明确的形式更好的方式,因为较少数量的制作规则在较高的情况下构建较小的树(因此有效的编译器 - 花费较少的时间来解析)。
答案 2 :(得分:2)
这里提供的两个答案都是错误的。在这些答案中,^关联到左边,而实际上它应该与右边相关联。正确修改的语法应该是:
E -> E+T | E-T | T
T -> T*X | T/X | X
X -> F^X | F //Note: it's F^X not X^F
F -> i | (E)
通过这种方式,您的语法按预期工作,其表达式如下:
a+b^c^d^e*f
谢谢!