синтаксический анализ — неожиданная ошибка грамматики Antlr4 (цель C ++)

Я использую цель C ++ в Antlr 4.7.1, и некоторые входные строки вызывают неожиданную ошибку.

Строка, которая не анализируется с файлом грамматики как есть:

keys abc-def;

Ошибка дана:

Line(1:5) Error(mismatched input 'abc-def' expecting {KEY_NAME_PATTERN, STRING_LITERAL})

Странно то, что если я поменяю местами положения правил для KEY_NAME_IDENTIFIER и KEY_NAME_PATTERN в файле грамматики, то приведенная выше строка анализируется нормально, но следующая строка теперь не выполняется (что прошло без замены позиций правила):

get key abc-def;

Так что я подозреваю ошибку в Antlr, но не уверен на 100%.

Файл грамматики:

grammar ModelKeyValue;

start : keyvalue_statements ;

keyvalue_statements: ( del_statement | get_statement | set_statement | keys_statement ) ';'
;

del_statement:
KEYWORD_DEL key_name
;

get_statement:
KEYWORD_GET key_name
;

set_statement:
KEYWORD_SET key_name literal_value
;

keys_statement:
KEYWORD_KEYS key_name_pattern
;

keyword:
KEYWORD_DEL
| KEYWORD_GET
| KEYWORD_SET
| KEYWORD_KEYS
;

key_name:
KEY_NAME_IDENTIFIER
| STRING_LITERAL
;

key_name_pattern:
KEY_NAME_PATTERN
| STRING_LITERAL
;

literal_value:
STRING_LITERAL
;

KEYWORD_DEL: D E L;
KEYWORD_GET: G E T;
KEYWORD_SET: S E T;
KEYWORD_KEYS: K E Y S;

KEY_NAME_IDENTIFIER: ([a-z]|[A-Z]|[0-9]|'!'|'@'|'#'|'$'|':'|'-')+;

KEY_NAME_PATTERN: ([a-z]|[A-Z]|[0-9]|'!'|'@'|'#'|'$'|':'|'-'|'_'|'%')+;

STRING_LITERAL:
'\'' ( ~'\'' | '\'\'' )* '\''
| '"' ('\\' ~('\r' | '\n') | ~('\\' | '"'| '\r' | '\n'))* '"'
;

fragment A: [aA];
fragment B: [bB];
fragment C: [cC];
fragment D: [dD];
fragment E: [eE];
fragment F: [fF];
fragment G: [gG];
fragment H: [hH];
fragment I: [iI];
fragment J: [jJ];
fragment K: [kK];
fragment L: [lL];
fragment M: [mM];
fragment N: [nN];
fragment O: [oO];
fragment P: [pP];
fragment Q: [qQ];
fragment R: [rR];
fragment S: [sS];
fragment T: [tT];
fragment U: [uU];
fragment V: [vV];
fragment W: [wW];
fragment X: [xX];
fragment Y: [yY];
fragment Z: [zZ];

WS: [ \t\r\n]+ -> skip ;

Если кто-то может проверить эту проблему или предложить решение, которое очень поможет, спасибо.

1

Решение

Нет, это не ошибка. Вы неправильно понимаете, как работает токенизация. Это так: всякий раз, когда есть 2 (или более) правила, которые соответствуют одинаковому количеству символов, например KEY_NAME_IDENTIFIER а также KEY_NAME_PATTERN для ввода keys abc-def;Правило определило первые «выигрыши». Лексер не «слушает» анализатор (как работает анализатор без сканера). Обойти это невозможно.

Чтобы это исправить, просто включите KEY_NAME_IDENTIFIER в вашем key_name_pattern производство:

key_name_pattern
: KEY_NAME_IDENTIFIER
| KEY_NAME_PATTERN
| STRING_LITERAL
;
1

Другие решения

Других решений пока нет …