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

Choice Conflict Involving Two Expansions:

我正在尝试创建自己的 analyser/parser。

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

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

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())     
    )
}

如您所见,问题出在 OR 部分三个选项中最后两个选项的 Condition() 方法中。这是因为 Expression() 最终可以变成 "( Expression() )" 因此第三个和第二个选项都可以以左括号标记开头.

但是,我不确定如何解决这个问题。我之前在解析器中解决了一个类似的问题,但是我不能在这里使用相同的逻辑,因为 Expression() --> Term 的方式会非常混乱() --> Factor() 问题代码一直在 Factor() 方法中。

如有任何建议,我们将不胜感激。

谢谢,

托马斯。

编辑:

有关详细信息,我将提供应与此解析器一起使用但由于上述错误而无法使用的代码示例。

fun succesful_method()
    start
        var i = 1;
        if(i > 0 and i < 2)
        do
            i = 2;
        stop
    stop

start
    successful_method()
stop

上述方法会 运行 成功,因为它使用了 Condition() 方法的第二种选择。

fun succesful_method()
    start
        var i = 1;
        if(i > 0)
        do
            i = 2;
        stop
    stop

start
    successful_method()
stop

上述方法会失败,因为它需要使用第三个备选方案,但是由于“(”导致解析器调用第二个备选方案,它无法访问此方法。

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

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>

令牌<RELOP>代表您的关系运算符。

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

例如,对于 Expr -> AndExpr,返回的类型将是 AndExpr 的类型。但是对于 AndExpr <OR> 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>
}

效率稍微高一点的是只在有 ( 时向前看。

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