LL(1)语法的问题

时间:2012-06-30 19:42:57

标签: parsing grammar ambiguity ll left-recursion

我对Mini Java的子语法有26条规则语法。该语法应该是非面向对象的。无论如何,我一直在尝试左击它并删除左递归。但是我用JFLAP测试它,但它告诉我它不是LL(1)。我已经按照Aho-Sethi书中的算法的每一步进行了操作。

你能给我一些提示吗?

Goal ::= MainClass $
MainClass ::= class <IDENTIFIER> { MethodDeclarations public static void main ( ) {
    VarDeclarations Statements } }
    VarDeclarations ::= VarDeclaration VarDeclarations | e
VarDeclaration ::= Type <IDENTIFIER> ;
MethodDeclarations ::= MethodDeclaration MethodDeclarations | e
MethodDeclaration ::= public static Type <IDENTIFIER> ( Parameters ) {
    VarDeclarations Statements return GenExpression ; }
Parameters ::= Type <IDENTIFIER> Parameter | e
Parameter ::= , Type <IDENTIFIER> Parameter | e
Type ::= boolean | int
Statements ::= Statement Statements | e
Statement ::= { Statements }
        |   if ( GenExpression ) Statement else Statement
        |   while ( GenExpression ) Statement
        |   System.out.println ( GenExpression ) ;
        |   <IDENTIFIER> = GenExpression ;
GenExpression ::= Expression | RelExpression
Expression ::= Term ExpressionRest
ExpressionRest ::= e | + Term ExpressionRest | - Term ExpressionRest
Term ::= Factor TermRest
TermRest ::= e | * Factor TermRest
Factor ::= ( Expression )
        |   true
        |   false
        |   <INTEGER-LITERAL>
        |   <IDENTIFIER> ArgumentList
ArgumentList ::= e | ( Arguments )
RelExpression ::= RelTerm RelExpressionRest
RelExpressionRest ::= e | && RelTerm RelExpressionEnd
RelExpressionEnd ::= e | RelExpressionRest
RelTerm ::= Term RelTermRest
RelTermRest ::= == Expression | < Expression | ExpressionRest RelTermEnding
RelTermEnding ::= == Expression | < Expression
Arguments ::= Expression Argument | RelExpression Argument | e
Argument ::= , GenExpression Argument | e 

每个<IDENTIFIER>都是有效的Java标识符,<INTEGER-LITERAL>是一个简单的整数。每个e生产代表epsilon生产,第一个规则中的$代表文件结束标记。

2 个答案:

答案 0 :(得分:2)

我想我发现了两个问题(可能还有更多):

问题#1

在MainClass中你有

MethodDeclarations public static void main

MethodDeclaration是

public static Type | e

这不是LL(1),因为当解析器看到“public”时,它无法判断它是MethodDeclaration还是“public static void main”方法。

问题#2

Arguments ::= Expression Argument | RelExpression Argument | e

表达式:

Expression ::= Term ExpressionRest

...和RelExpression:

RelExpression ::= RelTerm RelExpressionRest
RelTerm ::= Term RelTermRest

...以“Term”开头,这样也不是LL(1)。

我只是选择LL(k)或LL(*),因为它们允许你编写更多可维护的语法。

答案 1 :(得分:0)

有什么可以防止IDENTIFIER与你的一个保留字相同吗?如果没有,那么你的语法就会模棱两可。我没有看到任何其他东西。

如果所有其他方法都失败了,我会删除除语法最后一行之外的所有内容,并对其进行测试。如果通过,我会一次添加一行,直到找到问题行。