【问题标题】:Grammar Rule for Math Expressions (No Left-Recursion)数学表达式的语法规则(无左递归)
【发布时间】:2016-01-05 01:54:15
【问题描述】:

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

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

我设法想出了一个工作了一段时间,但语法规则失败了 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

EDIT 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

【问题讨论】:

    标签: syntax expression grammar ebnf


    【解决方案1】:

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

    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 ')'
        ;
    

    求幂留作读者练习:请注意求幂运算符是右结合的。这是在 yacc 表示法中。注意:您使用的是 EBNF,而不是 BNF。

    编辑我的非左递归 EBNF 不如我的 yacc 强,但要排除左递归,您需要一个方案,例如:

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

    等,其中* 表示“零或更多”。下面我的 cmets 大多是不正确的,应该忽略。

    【讨论】:

    • 这太棒了,我知道它是如何工作的,但不幸的是我的生成器不允许“左递归”。我怎样才能修改它以使没有左递归?
    • 改成expression: term '+' term
    • 这样做虽然不允许所有表达式。例如,2 * (3 * 3) + 1 + 1 失败。
    • 失败怎么办?你是如何实现这个语法的?
    • 我正在为 Intellij IDE 制作自定义语言插件。基本上,我输入语法并单击一个按钮来生成解析器代码。然后解析器代码创建一个 AST。解析器告诉我它期望某些标记的位置,例如 Java 编译器。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      • 1970-01-01
      • 2013-10-22
      相关资源
      最近更新 更多