2014-10-25 3 views
2

У меня есть следующие Antlr4 грамматика:ANTLR4. Комментарии не поглотило лексер

grammar Smarty; 

/* 
* Parser Rules 
*/ 

parse: smartyBody 
    ; 

smartyBody: include 
      | bodyText? 
      ; 

include: INCLUDE fileName CB 
      ; 

bodyText: BODY_TEXT 
     ; 

fileName: FILENAME 
     ; 
/* 
* Lexer Rules 
*/ 
COMMENT: '{*' .*? '*}'  -> skip; 

INCLUDE: '{include' SPACE+ 'file='?; 

BODY_TEXT: ANY_CHAR+; 

CB: SPACE? '}'; 

FILENAME: '\'' FILE_NAME '\'' 
    | '"' FILE_NAME '"'; 

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

fragment FILE_NAME: PATH_CHARACTERS+; 
fragment PATH_CHARACTERS: ~[\u0000-\u001f"*:<>?\\/|\u007f-\uffff]; 
fragment ANY_CHAR: [ -~]; 

Теперь, если я пытаюсь использовать комментарии, они передаются обратно и не проглочены.

Текст передается анализатору: {* {включаемый файл = «ххххх»} *} zzzzzzzz

Если я переопределить EnterBodyText и передать текстовую строку в парсер переменной Text в слушателе получить исходный текст, включая комментарии.

internal partial class BaseListener : SmartyBaseListener 
{ 
    public override void EnterBodyText(SmartyParser.BodyTextContext context) 
    { 
     var Text = context.BODY_TEXT().GetText(); 
     // Text gets: {* {include file='xxxxx'} *} zzzzzzzz 
     // not just zzzzzzzz 
    } 
} 

Любая помощь оценивается.

ответ

2

Лексер ANTLR постарается максимально соответствовать. Таким образом, вход {* {include file='xxxxx'} *} zzzzzzzz полностью совпадает с BODY_TEXT.

Одним из способов решения этой проблемы является сделать BODY_TEXT правила синтаксического анализа вместо:

body_text: ANY_CHAR+; 

... 

COMMENT: '{*' .*? '*}' -> skip; 

... 

// No fragment anymore. And keep this as the last lexer rule! 
ANY_CHAR: [ -~]; 
+0

Спасибо, что помогает много. Несмотря на то, что я думал, что COMMENT объявлен до BODY_TEXT, он имел бы приоритет над BODY_TEXT. – Terry151151

+1

@ Terry151151, 'COMMENT' имеет только приоритет над' BODY_TEXT', если оба соответствуют одинаковому количеству символов. Как только одно из правил будет соответствовать больше, оно «победит». –

+0

Как примечание, это действительно делает обработку неэффективной. Если у меня есть 2-килобайтный документ без тегов, я заканчиваю на 2 тыс. Узлов, каждый из которых содержит один символ. Который мне тогда нужно выполнить цикл GetText() для каждого отдельного символа вместо того, чтобы просто получать одну строку из lexer. – Terry151151

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