我已经为一种预处理器语言编写了标记器和表达式求值器,我计划在以后的项目中使用它。我开始想,也许我应该用EBNF(扩展Backus-Naur形式)来描述语言,以使语法更易于维护,或者甚至使用它来生成解析器的后续版本。
我的第一印象是EBNF用于标记过程和语法验证。后来我发现它也可以用来描述操作符优先级,就像这篇文章或维基百科的文章:
expression ::= equality-expression
equality-expression ::= additive-expression ( ( '==' | '!=' ) additive-expression ) *
additive-expression ::= multiplicative-expression ( ( '+' | '-' ) multiplicative-expression ) *
multiplicative-expression ::= primary ( ( '*' | '/' ) primary ) *
primary ::= '(' expression ')' | NUMBER | VARIABLE | '-' primary
我可以看到如何允许生成器生成代码与操作符优先级内置,但这真的是优先级应该如何表达?难道运算符优先级不是更多地关注语义而EBNF不是更多地关注语法吗?如果我决定在EBNF中编写语言的描述,我应该在编写时考虑运算符优先级,还是将其放在单独的部分中进行记录?
我也是这么做的。
我建议不要使用操作符优先特性,即使看起来像"语法糖"一样容易。
为什么?因为大多数语言要用EBNF来描述,使用了许多具有不同特征的运算符,这些运算符更好地描述了&更新,使用EBNF表达式,而不是操作符优先级。
有些操作符是一元前缀,有些是一元后缀,有些是二进制(也称为二进制)。"中缀"),一些二进制从左到右求值,&有些是从右到左求值。有些符号在某些上下文中是操作符,并在其他上下文中用作其他标记,例如"+","-",它们可以是二进制操作符("x -y"),一元前缀操作符("x -y")或文字的一部分("x + -5")。
根据我的经验,用EBNF表达式来描述它们更"安全"。除非你描述的编程语言非常小,语法操作符非常少且相似(例如:全二进制,或全前缀一元)。
我的2美分。