Ошибка маркера пробела Antlr


У меня есть следующая грамматика, и я хочу соответствовать строке "{name1, name2}". Мне просто нужны списки имен / интергеров с хотя бы одним элементом. Однако я получаю ошибку:
строка 1: 6 нет жизнеспособной альтернативы у символа ''
строка 1: 11 нет жизнеспособной альтернативы в символе'} '
строка 1: 7 несовпадение входных данных 'name' ожидание SIMPLE_VAR_TYPE

Я ожидал бы, что пробелы и такие игнорируются... Также интересно, что ошибка не возникает при вводе " {name1, name2} "(нет пробела после ","). Вот мой грамар

grammar NusmvInput;
options {
  language = Java;
}
@header {
  package secltlmc.grammar;
}
@lexer::header {
  package secltlmc.grammar;
}
specification : 
     SIMPLE_VAR_TYPE EOF
     ;     
INTEGER 
    : ('0'..'9')+
    ;
SIMPLE_VAR_TYPE 
    : ('{' (NAME | INTEGER) (',' (NAME | INTEGER))* '}'  )
    ;
NAME 
    : ('A'..'Z' | 'a'..'z') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$' | '#' | '-')*
    ;
WS 
    : (' ' | 't' | 'n' | 'r')+ {$channel = HIDDEN;} 
    ;

И это мой тестовый код

package secltlmc;
public class Main {
    public static void main(String[] args) throws 
            IOException, RecognitionException {
        CharStream stream = new ANTLRStringStream("{name1, name2}");
        NusmvInputLexer lexer = new NusmvInputLexer(stream);
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        NusmvInputParser parser = new NusmvInputParser(tokenStream);
        parser.specification();
    }
}

Спасибо за помощь.

2 2

2 ответа:

Проблема заключается в том, что вы пытаетесь разобрать SIMPLE_VAR_TYPE с помощью лексера, то есть вы пытаетесь сделать его единственным маркером. На самом деле, похоже, что вы хотите создать мульти-токен, так как вы хотите, чтобы пробелы были перенаправлены в скрытый канал через WS.

Вы должны изменить SIMPLE_VAR_TYPE С правила лексера на правило синтаксического анализатора, изменив его начальную букву (или, еще лучше, все имя) на нижний регистр.

specification : 
     simple_var_type EOF
     ;    

simple_var_type 
    : ('{' (NAME | INTEGER) (',' (NAME | INTEGER))* '}'  )
    ;

Определение SIMPLE_VAR_TYPE задает следующее выражение:

  • открыть {
  • , за которым следует один из NAME или INTEGER
  • за которым следует ноль или более из:
    • запятая (,), за которой следует одна из NAME или INTEGER
  • с последующим закрытием }

Нигде он не допускает пробелов во входных данных (ни NAME, ни INTEGER не допускает этого), поэтому вы получаете ошибку, когда вы предоставляете один

Попробуйте:

SIMPLE_VAR_TYPE 
: ('{' (NAME | INTEGER) (WS* ',' WS* (NAME | INTEGER))* '}'  )
;