javacc 中多余的 LOOKAHEAD 会导致错误?

superfluous LOOKAHEAD in javacc causes error?

我有以下 TT.jj,如果我取消注释下面的 SomethingElse 部分,它会成功解析 create create blahblahcreate blahblah 形式的语言。但是,如果我注释掉下面的 SomethingElse 部分,但保留 LOOKAHEAD,javacc 会抱怨前瞻是不必要的并且 "ignored",但生成的解析器只接受一个空字符串。

我以为 javacc 说它是 "ignored" 所以它应该不起作用?基本上多余的 LOOKAHEAD 会导致错误。这到底是如何工作的?也许 javacc 的 LOOKAHEAD 实现不完全符合规范?

     options{
        IGNORE_CASE=true ;
        STATIC=false;
            DEBUG_PARSER=true;
        DEBUG_LOOKAHEAD=false;
        DEBUG_TOKEN_MANAGER=false;
    //  FORCE_LA_CHECK=true;
        UNICODE_INPUT=true;
    }

    PARSER_BEGIN(TT)

    import java.util.*;

    /**
     * The parser generated by JavaCC
     */
    public class TT {

    }

    PARSER_END(TT)


    ///////////////////////////////////////////// main stuff concerned
    void Statement() :
    { }
    {
    LOOKAHEAD(2)
    CreateTable()
    //|
    //SomethingElse()
    }

    void CreateTable():
    {
    }
    {
            <K_CREATE> <K_CREATE> <S_IDENTIFIER>
    }

    //void SomethingElse():
    //{}{
    //      <K_CREATE> <S_IDENTIFIER>
    //}
    //
    //////////////////////////////////////////////////////////


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

TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
{
<K_CREATE: "CREATE">
}


TOKEN : /* Numeric Constants */
{
   < S_DOUBLE: ((<S_LONG>)? "." <S_LONG> ( ["e","E"] (["+", "-"])? <S_LONG>)?
                        |
                        <S_LONG> "." (["e","E"] (["+", "-"])? <S_LONG>)?
                        |
                        <S_LONG> ["e","E"] (["+", "-"])? <S_LONG>
                        )>
  |     < S_LONG: ( <DIGIT> )+ >
  |     < #DIGIT: ["0" - "9"] >
}


TOKEN:
{
        < S_IDENTIFIER: ( <LETTER> | <ADDITIONAL_LETTERS> )+ ( <DIGIT> | <LETTER> | <ADDITIONAL_LETTERS> | <SPECIAL_CHARS>)* >
|       < #LETTER: ["a"-"z", "A"-"Z", "_", "$"] >
|   < #SPECIAL_CHARS: "$" | "_" | "#" | "@">
|   < S_CHAR_LITERAL: "'" (~["'"])* "'" ("'" (~["'"])* "'")*>
|   < S_QUOTED_IDENTIFIER: "\"" (~["\n","\r","\""])+ "\"" | ("`" (~["\n","\r","`"])+ "`") | ( "[" ~["0"-"9","]"] (~["\n","\r","]"])* "]" ) >

/*
To deal with database names (columns, tables) using not only latin base characters, one
can expand the following rule to accept additional letters. Here is the addition of german umlauts.

There seems to be no way to recognize letters by an external function to allow
a configurable addition. One must rebuild JSqlParser with this new "Letterset".
*/
|   < #ADDITIONAL_LETTERS: ["ä","ö","ü","Ä","Ö","Ü","ß"] >
}

JavaCC 说它正在忽略的前瞻规范并没有被忽略。道德:不要在非选择点放置前瞻性规范。

更详细。当先行(除了纯语义先行)出现在非选择点时,它似乎生成一个总是 returns false 的先行方法,因此先行失败,并且没有其他选择,抛出异常。

这是从错误的 .jj 生成的代码

      final public void Statement() throws ParseException {
    trace_call("Statement");
    try {
      if (jj_2_1(5)) {

      } else {
        jj_consume_token(-1);
        throw new ParseException();
      }   
      CreateTable();
    } finally {
      trace_return("Statement");
    }     
  }

这是最好的:

  final public void Statement() throws ParseException {
    trace_call("Statement");
    try {
      if (jj_2_1(3)) {
        CreateTable();
      } else {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case K_CREATE:
          SomethingElse();
          break;
        default:
          jj_la1[0] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
      } 
    } finally {
      trace_return("Statement");
    } 
  }  

即多余的 LOOKAHEAD 根本没有被忽略,javacc 机械地尝试列出 if-else 结构中的所有选项(在坏情况下是 none)并导致直接查找 EOF[=12= 的语法]