数学表达式的语法规则(无左递归)

Grammar Rule for Math Expressions (No Left-Recursion)

我正在尝试找出任何数学表达式的语法规则。

我正在使用 EBNF(下面链接的维基文章)来推导语法规则。

我设法想出了一个可以用一段时间的方法,但是语法规则失败 onScreenTime + (((count) - 1) * 0.9)

规则如下:

math ::= MINUS? LPAREN math RPAREN
       | mathOperand (mathRhs)+

mathRhs ::= mathOperator mathRhsGroup
          | mathOperator mathOperand mathRhs?

mathRhsGroup ::= MINUS? LPAREN mathOperand (mathRhs | (mathOperator mathOperand))+ RPAREN

您可以安全地假设 mathOperand 是正数或负数,或变量。 您还可以假设 mathOperator 表示任何数学运算符,如 + 或 -。

另外,LPARENRPAREN 分别是 '(' 和 ')'。

EBNF: https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form

编辑 忘记提及它在 (count) - 1 上失败了。它说 RPAREN 预期而不是 - 1.

编辑 2 我修改后的 EBNF 现在看起来像这样:

number ::= NUMBER_LITERAL //positive integer

mathExp ::= term_ ((PLUS | MINUS) term_)* // * is zero-or-more.

private term_ ::= factor_ ((ASTERISK | FSLASH) factor_)*

private factor_ ::= PLUS factor_
                  | MINUS factor_
                  | primary_

private primary_ ::= number
                   | IDENTIFIER
                   | LPAREN mathExp RPAREN

看看任何编程语言的表达式语法:

expression
    : term
    | expression '+' term
    | expression '-' term
    ;

term
    : factor
    | term '*' factor
    | term '/' factor
    | term '%' factor
    ;

factor
    : primary
    | '-' factor
    | '+' factor
    ;

primary
    : IDENTIFIER
    | INTEGER
    | FLOATING_POINT_LITERAL
    | '(' expression ')'
    ;

作为 reader 的练习留下的求幂:请注意,求幂运算符是 right-associative。这是在 yacc 表示法中。注意您使用的是 EBNF,而不是 BNF。

EDIT 我的 non-left-recursive EBNF 不如我的 yacc 强,但是要分解 left-recursions 你需要一个像这样的方案例如:

expression
    ::= term ((PLUS|MINUS) term)*
term
    ::= factor ((FSLASH|ASTERISK) factor)*

等,其中 * 表示 'zero or more'。我在下面对此的评论大多是不正确的,应该被忽略。

您可能想看一下通常使用递归下降解析器实现的语言的表达式语法,其中需要 LL(1) 语法,不允许左递归。大多数(如果不是全部)Wirth 的语言都属于这一组。下面是经典 Modula-2 语法的示例。 EBNF 链接显示在每个规则旁边。

http://modula-2.info/m2pim/pmwiki.php/SyntaxDiagrams/PIM4NonTerminals#expression