1

对于 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 产生式,$第一条规则中的 是文件结束标记。

4

2 回答 2

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(*),因为它们允许您编写更易于维护的语法。

于 2012-06-30T22:04:25.090 回答
0

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

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

于 2012-06-30T20:19:27.943 回答