Parsing LL(1)语法问题

Parsing LL(1)语法问题,parsing,grammar,ambiguity,ll,left-recursion,Parsing,Grammar,Ambiguity,Ll,Left Recursion,我有一个26规则的小Java子语法。这种语法应该是非面向对象的。不管怎样,我一直在尝试左因子,并删除左递归。然而,我用JFLAP测试它,它告诉我它不是LL(1)。我遵循了Aho Sethi书中算法的每一步 你能给我一些提示吗 Goal ::= MainClass $ MainClass ::= class <IDENTIFIER> { MethodDeclarations public static void main ( ) { VarDeclarations Statem

我有一个26规则的小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 
Goal::=MainClass$
MainClass::=类{MethodDeclarations公共静态void main(){
VarDeclarations语句}
VarDeclarations::=vardeclarationvardeclarations | e
VarDeclaration::=类型;
方法声明::=MethodDeclaration方法声明| e
MethodDeclaration::=公共静态类型(参数){
VarDeclarations语句返回GenExpression;}
参数::=类型参数| e
参数::=,类型参数| e
类型::=boolean | int
语句::=语句语句| e
语句::={Statements}
|if(GenExpression)语句else语句
|while(GenExpression)语句
|System.out.println(GenExpression);
|=基因表达;
基因表达式::=表达式|重新表达式
表达式::=术语表达式REST
ExpressionRest::=e |+术语表达式rest |-术语表达式rest
术语::=系数术语
TermRest::=e |*因子TermRest
因子::=(表达式)
|真的
|假的
|   
|论据列表
ArgumentList::=e |(参数)
RelExpression::=RelTerm RelExpressionRest
RelExpressionRest::=e |&RelTerm relexpressioned
relexpressioned::=e | RelExpressionRest
RelTerm::=术语RelTermRest
RelTermRest::==表达式|<表达式|表达式rest RelTermEnding
relterminding::==表达式|<表达式
参数::=表达式参数|重新表达式参数| e
参数::=,基因表达式参数| e

每个
都是一个有效的Java标识符,
是一个简单的整数。每个
e
产品代表一个epsilon产品,第一条规则中的
$
是文件结尾标记。

是否有任何措施防止标识符与您的一个保留字相同?如果不是这样,你的语法就会模棱两可。不过,我没有看到其他任何东西


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

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

问题1

在你们班上

MethodDeclarations public static void main
方法声明是

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

问题2

两种表达方式:

Expression ::= Term ExpressionRest
RelExpression ::= RelTerm RelExpressionRest
RelTerm ::= Term RelTermRest
。。。和重新表达:

Expression ::= Term ExpressionRest
RelExpression ::= RelTerm RelExpressionRest
RelTerm ::= Term RelTermRest
。。。以“术语”开头,这样也就不是LL(1)了


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

标识符保证不是关键字。考虑{所有单词不是从数字}{{java关键字}开始。谢谢。好吧,那是两个,我想还有更多。难道没有一种方法可以检查这些漏洞吗?最快速、最可靠的方法可能是让您的解析器生成器执行LL(1)条件检查。检查它自己基本上需要您找出每个规则可以开始的所有终端符号。您知道,如果规则的某些条件以相同的端子符号开始,则它不是LL(1)。这与您的解析器生成器所做的和我在查看语法时所做的几乎相同。在使用语法一段时间后,您会对它有很好的感觉,但可以肯定的是,请询问解析器生成器:)上的Wikipedia条目提供了此方法的详细描述。最后一句话很重要:“如果表的每个单元格中最多包含一条规则,那么解析器将始终知道必须使用哪条规则,因此可以在不回溯的情况下解析字符串。正是在这种情况下,该语法被称为LL(1)语法。”谢谢。我会这样做的。我知道这类问题没有精确的“答案”,因此我将接受你的答案,并在这方面做更多的工作。最后,我使用ANTLRWorks修复语法并生成正确的解析器,尽管结果不是LL(1),而是LL(*)。