Java 涉及两个扩展的选择冲突:

Java 涉及两个扩展的选择冲突:,java,parsing,javacc,left-recursion,Java,Parsing,Javacc,Left Recursion,我正在尝试创建自己的分析器/解析器 我有一个问题,我理解为什么它不起作用,但我不确定如何解决它 这是我的解析器的问题部分的代码 void Expression() : {}{ Term() ((<PLUS> | <MINUS>) Term())* } void Term() : {}{ Factor()((<MULTIPLY> | <DIVIDE>) Factor())* } void Factor() : {}{ (

我正在尝试创建自己的分析器/解析器

我有一个问题,我理解为什么它不起作用,但我不确定如何解决它

这是我的解析器的问题部分的代码

void Expression() : {}{
    Term() ((<PLUS> | <MINUS>) Term())*
}

void Term() : {}{
     Factor()((<MULTIPLY> | <DIVIDE>) Factor())*
}

void Factor() : {}{
    (<ID> | <NUMBER> | ((<PLUS> | <MINUS>)?<OPEN_PARENTHESIS> Expression() <CLOSE_PARENTHESIS>))
}

void Condition() : {}{
    (
        (<NOT> Condition()) |
        (<OPEN_PARENTHESIS> Condition() (<AND> | <OR>) Condition() <CLOSE_PARENTHESIS>) |
        (Expression() (<EQUAL_CHECK> | <NOT_EQUAL> | <LESS> | <LESS_EQUAL> | <GREATER> | <GREATER_EQUAL>) Expression())     
    )
}

上述方法将失败,因为它需要使用第三种替代方法,但由于('导致解析器调用第二个选项。

对所有表达式使用单一语法并为所有运算符定义优先级应该可以解决您的问题,但代价是为表达式类型添加语义检查

Expr -> AndExpr (<OR> AndExpr)*
AndExpr -> NotExpr (<AND> NotExpr)*
NotExpr -> <NOT>* RelExpr
RelExpr -> NumExpr () (<RELOP> NumExpr)?

NumExpr -> Term ((<PLUS>|<MINUS>) Term)*
Term -> Factor ((<MULTIPLY>|<DIVIDE>) Factor)*
Factor -> (<PLUS>|<MINUS>)* Atom
Atom -> <ID> | <NUMBER> | <OPEN_PARENTHESIS> Expr <CLOSE_PARENTHESIS>
Expr->AndExpr(AndExpr)*
AndExpr->NotExpr(NotExpr)*
NotExpr->*重新expr
RelExpr->NumExpr()(NumExpr)?
NumExpr->术语((|)术语)*
术语->系数((|)系数)*
因子->(|)*原子
原子->表达式
标记
表示您的关系运算符

请注意,此语法允许您混合布尔表达式和数值表达式,因此您应该检查错误


例如,对于
Expr->AndExpr
,返回的类型将是AndExpr的类型。但是对于
AndExpr AndExpr
,您应该检查AndExpr都是布尔表达式,并且Expr返回的类型将是布尔的。

您可以通过语法先行解决这个问题

void CompOp() : {} { <EQUAL_CHECK> | <NOT_EQUAL> | <LESS> | <LESS_EQUAL> | <GREATER> | <GREATER_EQUAL> }

void Condition() : {}{
        <NOT> Condition()
    |
        LOOKAHEAD(Expression() CompOp()) 
        Expression()
        CompOp()
        Expression()   
    |
        <OPEN_PARENTHESIS>
        Condition()
        (<AND> | <OR>)
        Condition()
        <CLOSE_PARENTHESIS>
}

有趣的解决方案!非常感谢。与“前瞻”相比,此解决方案是否有优势上面提供的解决方案在效率方面?正如@TheodoreNorvell所指出的,通过这种方式,将布尔变量添加到您的语言中会更容易。我认为您不会注意到解析普通程序时的性能差异。您可以通过使用优先级爬升使这种方法高效。很好的解决方案,非常有效-真的很有用“前瞻”功能是否有效?它应该合理有效。许多语言(例如java、C++、Python、Haskell、ML)采取不在语法上区分条件和表达式的方法。其中一个原因是布尔变量非常有用。一旦有了布尔变量,你就会想要像这样的if语句
if q do…stop
和像这样的赋值语句
q=a
olean表达式和其他语法上分离的表达式是无用的。所以你应该考虑@1010的答案。
Expr -> AndExpr (<OR> AndExpr)*
AndExpr -> NotExpr (<AND> NotExpr)*
NotExpr -> <NOT>* RelExpr
RelExpr -> NumExpr () (<RELOP> NumExpr)?

NumExpr -> Term ((<PLUS>|<MINUS>) Term)*
Term -> Factor ((<MULTIPLY>|<DIVIDE>) Factor)*
Factor -> (<PLUS>|<MINUS>)* Atom
Atom -> <ID> | <NUMBER> | <OPEN_PARENTHESIS> Expr <CLOSE_PARENTHESIS>
void CompOp() : {} { <EQUAL_CHECK> | <NOT_EQUAL> | <LESS> | <LESS_EQUAL> | <GREATER> | <GREATER_EQUAL> }

void Condition() : {}{
        <NOT> Condition()
    |
        LOOKAHEAD(Expression() CompOp()) 
        Expression()
        CompOp()
        Expression()   
    |
        <OPEN_PARENTHESIS>
        Condition()
        (<AND> | <OR>)
        Condition()
        <CLOSE_PARENTHESIS>
}
void Condition() : {}{
        <NOT> Condition()
    |   LOOKAHEAD( <OPEN_PARENTHESIS> )
        (
            LOOKAHEAD(Expression() CompOp()) 
            Expression()
            CompOp()
            Expression() 
        |
            <OPEN_PARENTHESIS>
            Condition()
            (<AND> | <OR>)
            Condition()
            <CLOSE_PARENTHESIS>
        )
    |
        Expression()
        CompOp()
        Expression()   
}