我有一个26规则语法,用于Mini Java的子语法。这种语法应该是非面向对象的。无论如何,我一直在尝试左因子并删除左递归。但是,我用 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 生产,第一条规则中的$
是文件结束标记。
我想我发现了两个问题(可能还有更多):
问题#1
在主类中,你有
MethodDeclarations public static void main
方法声明是
public static Type | e
这不是 LL(1),因为当解析器看到"公共"时,它无法判断它是 MethodStatement 还是 "public static void main" 方法。
问题#2
Arguments ::= Expression Argument | RelExpression Argument | e
两种表达式:
Expression ::= Term ExpressionRest
。和相对表达:
RelExpression ::= RelTerm RelExpressionRest
RelTerm ::= Term RelTermRest
。以"术语"开头,所以也不是LL(1)。
我只会选择LL(k)或LL(*),因为它们允许您编写更易于维护的语法。
有什么可以防止标识符与您的保留字之一相同吗? 如果不是,那么你的语法将是模棱两可的。不过我没有看到其他任何东西。
如果所有其他方法都失败了,我会删除语法的最后一行以外的所有内容,并对其进行测试。如果通过,我会一次添加一行,直到找到问题行。