Синтаксис комментариев ASN.1 / SMI для ANTLR 3 - PullRequest
1 голос
/ 07 января 2012

В ANTLR 2 синтаксис комментария такой,

// Single-line comments
SL_COMMENT
    : (options {warnWhenFollowAmbig=false;} 
    : '--'(  { LA(2)!='-' }? '-'    |   ~('-'|'\n'|'\r'))*  ( (('\r')? '\n') { newline(); }| '--') )
        {$setType(Token.SKIP);  }
    ;

Однако при портировании на ANTLR 3,

SL_COMMENT
    : (
    : '--'(  { input.LA(2)!='-' }? '-'  |   ~('-'|'\n'|'\r'))*  ( (('\r')? '\n') | '--') )
        {$channel = HIDDEN;}
    ;

, поскольку больше нет вариантов {warnWhenFollowAmbig=false;}, следующий комментарий не может быть правильно проанализирован,

-- some comment -- some not comment

Тогда, как можно определить это правило SL_COMMENT для ANTLR 3?

Ответы [ 2 ]

1 голос
/ 08 января 2012

Лично мне нравится держать грамматические правила настолько «пустыми», насколько это возможно. В этом случае я бы создал метод лексера, который возвращает true, если следующие два символа на входе - "--". Пока это не регистр, сопоставьте любой символ, кроме \r и \n, и повторяйте это ноль или более раз, пока не встретите необязательный "--". Обратите внимание, что я не ставил новую строку в конце, потому что не обязательно новая строка в конце (это также может быть EOF). Кроме того, \r и \n, скорее всего, будут соответствовать правилу SPACE, установленному на канале HIDDEN: так что, как я советую, делать это не вредно.

Демонстрация:

...

@lexer::members {
  private boolean endCommentAhead() {
    return input.LA(1) == '-' && input.LA(2) == '-';
  }
}

...

SL_COMMENT 
 : '--' ({!endCommentAhead()}?=> ~('\r' | '\n'))* '--'?
 ;

...

И если вам не нравится блок членов lexer, вы просто делаете:

SL_COMMENT 
 : '--' ({!(input.LA(1) == '-' && input.LA(2) == '-')}?=> ~('\r' | '\n'))* '--'?
 ;

EDIT

Небольшая полная демонстрация:

grammar T;

@parser::members {
  public static void main(String[] args) throws Exception {
    String source = "12 - 34 -- foo - bar -- 42 \n - - 5678 -- more comments 666\n--\n--";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}

@lexer::members {
  private boolean endCommentAhead() {
    return input.LA(1) == '-' && input.LA(2) == '-';
  }
}

parse
 : (t=. {System.out.printf("\%-15s\%s\n", tokenNames[$t.type], $t.text);})* EOF
 ;

SL_COMMENT 
 : '--' ({!endCommentAhead()}?=> ~('\r' | '\n'))* '--'?
 ;

MINUS
 : '-'
 ;

INT
 : '0'..'9'+
 ;

SPACE
 : (' ' | '\t' | '\r' | '\n') {skip();}
 ;

который после разбора ввода:

12 - 34 -- foo - bar -- 42
- - 5678 -- more comments 666

напечатает:

INT            12
MINUS          -
INT            34
SL_COMMENT     -- foo - bar --
INT            42
MINUS          -
MINUS          -
INT            5678
SL_COMMENT     -- more comments 666
SL_COMMENT     --
SL_COMMENT     --
0 голосов
/ 07 января 2012

Я наконец нашел решение,

SL_COMMENT: COMMENT (({input.LA (2)! = '-'}? '-') => '-' | ~ ('-'| '\ n' | '\ r')) * ((('\ r')? '\ n') | КОММЕНТАРИЙ) {$ channel = HIDDEN;};

...