Conflict selection involving two extensions:

I am trying to create my own analyzer / parser.

I have a problem that I understand why it doesn't work, but I'm not sure how to solve it.

This is the code for part of my analyzer's problem.

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

      

As you can see, the problem occurs in the Condition () method of the last two of the three parameters in the OR section. This is because expression () may end up becoming "(expression ())", so both the third and second options can start with an open parenthesis token.

However, I am not sure how I will resolve this issue. I solved a similar problem earlier in the parser, however I cannot use the same logic here without being extremely messy due to the way Expression () -> Term () -> Factor () and the problem code is all the way down in the Factor () method.

Any advice would be greatly appreciated.

Thank,

Thomas.

EDIT:

For more information, I'll share some code examples that should work with this parser, but not due to the error described above.

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

start
    successful_method()
stop

      

The above method will work successfully because it uses the second variant of the Condition () method.

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

start
    successful_method()
stop

      

The above method will fail as it requires the use of the third alternative, however it cannot access this due to "(" causes the parser to call the second alternative. "

+3


source to share


2 answers


You can solve this problem with parsing.



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

      

+1


source


Using a single grammar for all expressions and prioritizing all operators should solve your problem by adding semantic checks for the type of expressions.

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>

      

The token <RELOP>

represents your relational operators.



Note that this grammar allows you to mix boolean and numeric expressions, so you should check for errors.

For example, the Expr -> AndExpr

return type will be of type AndExpr. But for AndExpr <OR> AndExpr

you have to check that both ANDExpr are boolean expressions and that the return type of Expr is boolean.

+1


source







All Articles