2013-11-13 7 views
2

У меня есть следующие ANTLR 4 в сочетании Грамматика:Перекрытие Лексемы в ANTLR 4

grammar Example; 

fieldList: field* ; 

field:  'field' identifier '{' note '}' ; 

note:  NOTE ; 
identifier: IDENTIFIER ; 

NOTE:  [A-Ga-g] ; 
IDENTIFIER: [A-Za-z0-9]+ ; 
WS:   [ \t\r\n]+ -> skip ; 

Это разбирает:

field x { A } 
field x { B } 

Это не:

field a { A } 
field b { B } 

В случае, когда разбор сбой, я думаю, что лексер запутался и выпустил маркер NOTE, где я хочу, чтобы он выдал токен IDENTIFIER.

Edit:

В токенах выходит из лексера, «Примечание» маркер появляется, когда анализатор ожидает «IDENTIFIER». «ПРИМЕЧАНИЕ» имеет более высокий приоритет, потому что он показан сначала в грамматике. Итак, я могу придумать два способа исправить это ... во-первых, я мог бы изменить грамматику, чтобы устранить неоднозначность «NOTE» и «IDENTIFIER» (например, добавить «$» перед «NOTE»). Или я мог бы просто использовать «IDENTIFIER», где я буду использовать заметку, а затем заниматься обнаружением проблем, когда я иду по дереву разбора. Ни один из них не чувствует себя оптимально. Неужели должен быть способ исправить это?

+0

Возможно, вы можете использовать лексические режимы для решения проблемы, но это работает не в комбинированных грамматиках. См. Здесь: http://www.antlr.org/wiki/display/ANTLR4/Lexer+Rules – FunThomas424242

+0

ANTLR работает должным образом. Когда токен может соответствовать нескольким правилам лексера (при прочих равных условиях) первое правило сопоставляется первым. Поэтому «a» должен соответствовать NOTE, а не IDENTIFIER. –

ответ

0

Быстрое и грязное исправление для вашей проблемы: Изменить IDENTIFIER чтобы соответствовать только дополнению NOTE. Затем вы складываете их в identifier.

Результирующая грамматика:

grammar Example; 

fieldList: field* ; 

field:  'field' identifier '{' note '}' ; 

note:  NOTE ; 
identifier: (NOTE|IDENTIFIER_C)+ ; 

NOTE:  [A-Ga-g] ; 
IDENTIFIER_C: [H-Zh-z0-9] ; 
WS:   [ \t\r\n]+ -> skip ; 

Минусом этого решения является то, что вы не получите идентификатор в качестве маркеров и вы разметить каждый персонаж.

2

Я на самом деле в конечном итоге решение так:

grammar Example; 

fieldList: field* ; 

field:  'field' identifier '{' note '}' ; 

note:  NOTE ; 
identifier: IDENTIFIER | NOTE ; 

NOTE:  [A-Ga-g] ; 
IDENTIFIER: [A-Za-z0-9]+ ; 
WS:   [ \t\r\n]+ -> skip ; 

Мой дерево разбора все еще заканчивает тем, как хотелось бы.

Фактическая грамматика, которую я разрабатываю, сложнее, как и обходной путь, основанный на этом подходе. Но в целом подход работает хорошо.

Смежные вопросы