javaCC 解析限制

javaCC Parsing Limitation

我正在尝试通过 javaCC 解析文本文件。该文件由多个句子组成,以换行符分隔。每行可以包含 "a" 和 "b" 的任意序列,但应以 "a" 结尾,然后是换行符之前的 "b" 。 JavaCC 不解析相同的内容并将终端标记 a 和 b 作为可选系列的一部分使用。

这应该被 JavaCC 成功解析:

aa ab aab
aab

jjt文件如下:

    options {
STATIC = false ;
FORCE_LA_CHECK = true;
LOOKAHEAD = 20000;
DEBUG_PARSER = true;
DEBUG_LOOKAHEAD = true;
OTHER_AMBIGUITY_CHECK = 3;
}

PARSER_BEGIN(Test)
class Test {
public static void main( String[] args )
throws ParseException {
    Test act = new Test (System.in);
    SimpleNode root = act.Start() ; 
    root.dump (" ");
    //ystem.out.println("Total = "+val);
}
}PARSER_END(Test)

TOKEN_MGR_DECLS :
{
  int stringSize;
}  

SKIP : { < WS : " " >   }
SKIP : {"\t" | "\r" | "\uFFFF" | "\u201a" | "\u00c4" | "\u00ee" | "\u00fa" | "\u00f9" | "\u00ec" | "\u2013" }

TOKEN [IGNORE_CASE] :
{
    < A : "a" >
|   < B : "b" >
|   < NEWLINE : (("\n")+ ) >
}   


SimpleNode Start() throws NumberFormatException :
{
    int i ;
    int value=0 ;
} {
chapter()
{ 
    return jjtThis; }   
}

void chapter() :
{ } {
    (LOOKAHEAD (part_sentence()) part_sentence())+ (newline())? <EOF>
}
void part_sentence() :
{ } {
    <NEWLINE> ( a() | b())+ a() b() 
}
void a() :
{ } {
    <A>
}
void b() :
{ } {
    <B>
}
void newline() throws NumberFormatException :
{ }{
    <NEWLINE> 
    {   System.out.print ("N# ");   }
}

需要说明的是,非终结符 a() 和 b() 不能用标记替换;它们被视为 "a" 和 "b" 只是为了简单起见。此外,由于其他限制,"NEWLINE" 不能移动到非终结符 "part_sentence" 的末尾。

过去 4 天我一直被这个问题困扰。我最后的希望是语义解析 - LOOKAHEAD ({!( getToken(1).kind==a() && getToken(2).kind==b() && getToken(3).kind==newline()}) 但是无法获得非终端句柄!任何帮助将不胜感激。

[注意:您说的是任何以 "ab" 结尾的 a 和 b 序列,但您的代码使用的是 + 而不是 *。我假设您确实指的是任何以 "ab" 结尾的序列,包括 "ab" 的序列。尾注。]

需要在look ahead的基础上退出循环。你要做的是这个

( LOOKAHEAD( x ) 
  (a() | b() )
)*
a() b() <NEWLINE>

其中 x 表示如果输入的下一项 不匹配 a() b() <NEWLINE>。不幸的是,无法使用句法前瞻来表示 "do not match"。诀窍是用递归替换循环。

void oneLine() : {} {
    LOOKAHEAD( a() b() <NEWLINE> )
    a() b() <NEWLINE>
|
    a() oneLine()
|
    b() oneLine()
}

你说你想要 <NEWLINE> 在制作的开始。由于 FAQ 中解释的原因,我不喜欢使用超出手头选择范围的句法前瞻。但可以做到以下几点。

void oneLine() : {} { <NEWLINE> oneLinePrime() }

void oneLinePrime() : {} {
    LOOKAHEAD( a() b() <NEWLINE> )
    a() b()
|
    a() oneLinePrime()
|
    b() oneLinePrime()
}