简体   繁体   中英

JavaCC: Choice conflict in star expansion

I've been working with JavaCC to put together a parser grammar for a sort of "picture script" program I wrote in Java. The program takes a series of scripted commands, which are largely mapped right onto java.awt.Graphics method calls, processes them directly, and outputs an image to a file. I'm using JavaCC to build a parser for this because I want to start adding more complex constructs (such as looping, or functions).
Right now, I'm using JJTree to build the input as an AST. Anyway, I'm getting a warning from JavaCC (JJTree is ok with the .jjt file):
Warning: Choice conflict in (...)* construct at line 320, column 9. Expansion nested within construct and expansion following construct have common prefixes, one of which is "+"
Consider using a lookahead of 2 or more for nested expansion.
Because the source grammar is in "PicParse.jjt", I think that this is the offending construct from that file:

(
    MulTerm()
    ( //line 320 in the file, column 9 starts at open parens
        "+"
        MulTerm()
        {jjtThis.setName("+");}
    |
        "-"
        MulTerm()
        {jjtThis.setName("-");}
    )*
)#Plus(>1)

Lastly, while I did come across this , replacing the star operator ('*') with the question-mark operator ('?') did nothing to remove the warning.
Ultimately, What I want is to be able to use this production rule (the MulTerm() rule is identical, to this rule ("AddTerm()")) such that it preserves the operator that is matched in either choice, which will allow me to differentiate between adding and subtracting, with just one node type to represent each.

Fixed it! The problem was not in my additive term after all, but in my unary rule:

(
    <OPAR> Expr() <CPAR> 
| 
    ((t=<PLUS> 
    | t=<MINUS>) Expr() ) #Unary
| 
    Integer() 
| 
    Float() 
| 
    Double()
)
{ if(t != null) jjtThis.setName(t.image); }

The recursion caused by the second choice (Expr()->AddTerm()->MulTerm()->Unary()->Expr()) was behind the warning. I solved this by moving the second choice to a separate production rule, which only recurses back to unary:

void PrimaryExpr() #PrimaryExpr(>1) :
{ Token t=null; }
{
    t=<PLUS>
    Unary()
    {if(t != null) jjtThis.setName(t.image);}
|
    t=<MINUS>
    Unary()
    {if(t != null) jjtThis.setName(t.image);}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM