1

对于某些输入,解析器会显示“可能的较长匹配类型:{ <EXPRESSION>, <TEXT> } ”,但由于某些奇怪的原因,它选择了错误的。

这是来源:


SKIP :
{
  " "  
| "\r"
| "\t"
| "\n"
}

TOKEN :
{
  < DOT : "." >
| < LBRACE : "{" >
| < RBRACE : "}" >
| < LBRACKET: "[" >
| < RBRACKET: "]" >
| < #LETTER : [ "a"-"z" ] >
| < #DIGIT : [ "0"-"9" ] >
| < #IDENTIFIER: < LETTER > (< LETTER >)* >
| < EXPRESSION : (< IDENTIFIER> < DOT > < IDENTIFIER> < DOT > < IDENTIFIER> ((< DOT > < IDENTIFIER> )* | < LBRACKET > (< DIGIT>)* < RBRACKET >)*)*>
| < TEXT : (( < DOT >)* ( < LETTER > )+ (< DOT >)*)* >
}

void q0() :
{Token token = null;}
{
    (
        < LBRACE > expression() < RBRACE >
    |   ( token = < TEXT >
            {
              getTextTokens().add( token.image );
            }
        )
    )* < EOF >
}


void expression() :
{Token token = null;}
{
  < EXPRESSION >
}

如果我们尝试使用这个语法解析“a.bc.d”,它会说“FOUND A <EXPRESSION> MATCH (a.bc.d)”

我的问题是为什么它选择将输入解析为<EXPRESSION> 而不是 <TEXT>

另外,如何强制解析器选择正确的路径?我尝试了无数的 LOOKAHEAD 场景,但都没有成功。

例如,当使用 "a.bc.d"作为输入时,正确的路径是 <TEXT>,而对于" { a.bc.d } " 则使用<EXPRESSION>

提前致谢。

4

2 回答 2

2

JavaCC 常见问题解答

如果多个正则表达式描述了可能的最长前缀,则使用 .jj 文件中最先出现的正则表达式。

因此,可以通过相应地对模棱两可的定义进行排序来建立偏好。

于 2013-05-18T07:57:25.247 回答
1

如果表达式只出现在 { 大括号 } 中,只有表达式(和空格)出现在大括号中,并且大括号仅用于分隔表达式,那么您可以执行以下操作。如果您不熟悉词汇状态,请参阅常见问题解答中的问题 3.11。

// The following abbreviations hold in any state.
TOKEN : {
  < #LETTER : [ "a"-"z" ] >
| < #DIGIT : [ "0"-"9" ] >
| < #IDENTIFIER: < LETTER > (< LETTER >)* >
}

// Skip white space in either state
<DEFAULT,INBRACES> SKIP : { " "  | "\r" | "\t" | "\n" }

// The following are recognized in the default state.
// A left brace forces a switch to the INBRACES state.
<DEFAULT> TOKEN : {
  < DOT : "." >
| < LBRACE : "{" > : INBRACES
| < LBRACKET: "[" >
| < RBRACKET: "]" >
| < TEXT : (( < DOT >)* ( < LETTER > )+ (< DOT >)*)* >
}

// A right brace forces a switch to the DEFAULT state.
<DEFAULT, INBRACES > TOKEN {
  < RBRACE : "}"  > : DEFAULT
}

// Expressions are only recognized in the INBRACES state.
<INBRACES> TOKEN : {
  < EXPRESSION : (< IDENTIFIER> < DOT > < IDENTIFIER> < DOT > < IDENTIFIER> ((< DOT > < IDENTIFIER> )* | < LBRACKET > (< DIGIT>)* < RBRACKET >)*)*>
}

DOT 在一种状态下定义并在另一种状态下使用看起来有点狡猾。但是,我认为它工作正常。

于 2013-05-20T16:27:15.437 回答