Ошибка маркера пробела 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 ответа:
Проблема заключается в том, что вы пытаетесь разобрать
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))* '}' ) ;