лишний LOOKAHEAD в javacc вызывает ошибку?

У меня есть следующий TT.jj, если я раскомментирую часть SomethingElse ниже, он успешно разберет язык формы create create blahblah или create blahblah. Но если я закомментирую часть SomethingElse ниже, но оставлю LOOKAHEAD, javacc жалуется, что просмотр вперед не нужен и «игнорируется», но результирующий синтаксический анализатор принимает только пустую строку.

Я думал, что javacc сказал, что он «игнорируется», поэтому он не должен иметь никакого эффекта? в основном лишний LOOKAHEAD вызывает ошибку. Как это работает? может быть, реализация LOOKAHEAD в javacc не совсем соответствует спецификации?

     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: ["ä","ö","ü","Ä","Ö","Ü","ß"] >
}

person teddy teddy    schedule 06.05.2015    source источник


Ответы (2)


Упреждающая спецификация, которую JavaCC игнорирует, не игнорируется. Мораль: не размещайте прогнозные спецификации в точках, где нет выбора.

Более детально. Когда просмотр вперед (отличный от чисто семантического просмотра) появляется в точке, не являющейся выбором, он, по-видимому, генерирует метод просмотра вперед, который всегда возвращает false, поэтому просмотр вперед терпит неудачу, и, поскольку нет другого выбора, генерируется исключение.

person Theodore Norvell    schedule 07.05.2015
comment
Спасибо, имеет смысл, я внимательно проверю сгенерированный код. - person teddy teddy; 07.05.2015

вот сгенерированный код из плохого .jj

      final public void Statement() throws ParseException {
    trace_call("Statement");
    try {
      if (jj
  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");
    } 
  }  
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 и приводит к грамматике, которая ищет непосредственно EOF

person teddy teddy    schedule 07.05.2015