как разрешить простую двусмысленность

Я только начал использовать Antlr и застрял. У меня есть приведенная ниже грамматика, и я пытаюсь устранить неоднозначность для анализа ввода, такого как Field:ValueString.

expression : Field ':' ValueString;
Field : Letter LetterOrDigit*;
ValueString : ~[:];
Letter : [a-zA-Z];
LetterOrDigit : [a-zA-Z0-9];
WS: [ \t\r\n\u000C]+ -> skip;

предположим, что a:b передается в грамматику, a и b идентифицируются как Field. Как решить эту проблему в Antlr4 (С#)?


person Kuzey    schedule 13.02.2015    source источник


Ответы (2)


Вы можете использовать семантический предикат в правилах лексера для выполнения просмотра вперед (или назад) без использования символов (ANTLR4 отрицательный просмотр в лексере)

В вашем случае, чтобы устранить двусмысленность, вы можете проверить, является ли символ после правила Field :, или вы можете проверить, является ли символ перед ValueString :.

В первом случае:

expression : Field ':' ValueString;
Field : Letter LetterOrDigit* {_input.LA(1) == ':'}?;
ValueString : ~[:];
Letter : [a-zA-Z];
LetterOrDigit : [a-zA-Z0-9];
WS: [ \t\r\n\u000C]+ -> skip;

Во втором (обратите внимание, что Field и ValueString поменялись местами):

expression : Field ':' ValueString;
ValueString : {_input.LA(-1) == ':'}? ~[:];
Field : Letter LetterOrDigit*;
Letter : [a-zA-Z];
LetterOrDigit : [a-zA-Z0-9];
WS: [ \t\r\n\u000C]+ -> skip;

Также рассмотрите возможность использования ключевого слова fragment для Letter и LetterOrDigit.

fragment Letter : [a-zA-Z];
fragment LetterOrDigit : [a-zA-Z0-9];

«[С ключевым словом фрагмента] Вы также можете определить правила, которые не являются токенами, а скорее помогают в распознавании токенов. Эти правила фрагментов не приводят к тому, что токены видны синтаксическому анализатору». (источник https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Lexer+Rules)

person Vincent Aranega    schedule 13.02.2015

Способ решить эту проблему без просмотра вперед — просто определить правило синтаксического анализатора, которое может быть любым из этих двух токенов лексера:

expression : Field ':' value;
value : Field | ValueString;
Field : Letter LetterOrDigit*;
ValueString : ~[:];
Letter : [a-zA-Z];
LetterOrDigit : [a-zA-Z0-9];
WS: [ \t\r\n\u000C]+ -> skip;

Синтаксический анализатор будет работать, как и ожидалось, а грамматика останется простой, но вам может потребоваться добавить метод к реализации вашего посетителя или слушателя.

person Mephy    schedule 13.02.2015