你能用这个例子帮我吗?我该怎么做这个大小的左递归消除?我知道如何做更简单的例子。
Expr1 ::= Number ExprB
| String ExprB
| `true` ExprB
| `false` ExprB
| `undefined` ExprB
| Ident AfterIdent ExprB
| `[` Exprs `]`
| `[` `for` `(` Ident `of` Expr `)` ArrayCompr Expr `]`
| `(` Expr `)`
ExprB ::= ϵ
| `+` Expr1 ExprB
| `-` Expr1 ExprB
| `*` Expr1 ExprB
| `%` Expr1 ExprB
| `<` Expr1 ExprB
| `===` Expr1 ExprB
这是解决方案吗?
static void method1( ... ) for ( i: parameters ) print( i )
// or
static void method1( int a, ... ) for ( f=a; f < parameters.count(); f++) print( parameters[ i] );
答案 0 :(得分:1)
我学到的技巧是引入建设性的非终端,以便在任何一个地点获得更少的语法规则。你仍然会在语言中固有一些讨厌的扩展,但你可以在每一步都让这个过程更容易。
Scalar ::= Number | String | `true` | `false` | `undefined`
Op ::= '+' | '-' | '*' | '%' | '<' | '==='
OpExpr ::= Expr1 Op Expr1
ParenExpr ::=
`[` Exprs `]`
| `[` `for` `(` Ident `of` Expr `)` ArrayCompr Expr `]`
| `(` Expr `)`
Expr1 ::=
Scalar
| OpExpr
| ParenExpr
| Ident AfterIdent
这里主要有两个好处。一个是如果你正在实现解析器,那么规则现在更接近于处理系列。您可以对分类减少采取某些共同行动。第二,你可以简化你的递归消除:你有相同数量的终端开始 Expr1 ,但只有一个规则要扩展,OpExpr的定义。
我知道我还没有为你完成练习,但我希望这有助于让你感动。您可能还想查看运算符优先级语法:它们以优雅的方式处理其中一些,具体取决于您的应用程序。