5

我正在使用 antlr 4.5 为具有几种特殊注释格式的语言构建解析器,我想将其流式传输到不同的频道。

似乎 antlr 4.5 已经扩展了一个新的结构来声明额外的词法分析器通道:

从文档https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Lexer+Rules中提取

从 4.5 开始,您还可以在词法分析器规则上方使用以下构造定义通道名称,例如枚举:

频道 { WSCHANNEL, MYHIDDEN }

我的词法和解析规则在一个文件中,我的代码如下所示:

    channels {
       ANNOT_CHANNEL,
       FORMAL_SPEC_CHANNEL,
       DOC_CHANNEL,
       COMMENT_CHANNEL,
       PRAGMAS_CHANNEL
    }

...解析规则...

// expression annotation (sent to a special channel)
    ANNOT: (EOL_ANNOT | LUS_ANNOT | C_ANNOT) -> channel(ANNOT_CHANNEL) ;
    fragment LUS_ANNOT: '(*!' ( COMMENT | . )*? '*)' ;
    fragment C_ANNOT: '/*!' ( COMMENT | . )*? '*/' ;
    fragment EOL_ANNOT: ('--!' | '//!') .*? EOL ;

    // formal specification annotations (sent to a special channel)
    FORMAL_SPEC: (EOL_SPEC | LUS_SPEC | C_SPEC ) -> channel(FORMAL_SPEC_CHANNEL) ;
    fragment LUS_SPEC: '(*@' ( COMMENT | . )*? '*)' ;
    fragment C_SPEC: '/*@' ( COMMENT | . )*? '*/' ;
    fragment EOL_SPEC: ('--@' | '//@' | '--%') .*? EOL;

    // documentation annotation (sent to a special channel)
    DOC: ( EOL_DOC |LUS_DOC | C_DOC ) -> channel(DOC_CHANNEL);
    fragment LUS_DOC: '(**' ( COMMENT | . )*? '*)' ;
    fragment C_DOC: '/**' ( COMMENT | . )*? '*/' ;
    fragment EOL_DOC: ('--*' | '//*') .*? EOL;

    // standard comment (sent to a special channel)
    COMMENT: ( EOL_COMMENT | LUS_COMMENT | C_COMMENT ) -> channel(COMMENT_CHANNEL);
    fragment LUS_COMMENT: '(*' ( COMMENT | . )*? '*)' ;
    fragment C_COMMENT: '/*' ( COMMENT |. )*? '*/' ;
    fragment EOL_COMMENT: ('--' | '//') .*? EOL;

    // pragmas are sent to a special channel
    PRAGMA: '#pragma' CHARACTER* '#end' -> channel(PRAGMAS_CHANNEL);

但是我仍然收到类似 4.4 的错误

warning(155): Scade6.g4:550:52: rule ANNOT contains a lexer command with an unrecognized constant value; lexer interpreters may produce incorrect output
warning(155): Scade6.g4:556:56: rule FORMAL_SPEC contains a lexer command with an unrecognized constant value; lexer interpreters may produce incorrect output
warning(155): Scade6.g4:562:45: rule DOC contains a lexer command with an unrecognized constant value; lexer interpreters may produce incorrect output
warning(155): Scade6.g4:568:62: rule COMMENT contains a lexer command with an unrecognized constant value; lexer interpreters may produce incorrect output
warning(155): Scade6.g4:574:47: rule PRAGMA contains a lexer command with an unrecognized constant value; lexer interpreters may produce incorrect output

如果我将词法分析器和解析器拆分为两个不同的文件并使用导入语句将词法分析器导入解析器中,我仍然会遇到与上述相同的错误,

使用整数常量而不是名称与组合语法

-> channel(10000)

产生以下错误

error(164): Scade6.g4:8:0: custom channels are not supported in combined grammars

如果我将词法分析器和解析器分成两个文件并使用整数常量没有警告,但是它的可读性并不令人满意。

我可以做些什么来正确命名额外的频道吗?(使用组合或单独的词法分析器/解析器规范,无偏好)

问候,

4

1 回答 1

0

我可以做些什么来正确命名额外的频道吗?

不确定v4.5(没有使用过),但在v4.x中你总是可以像这样定义通道(假设使用java):

grammar MyGrammar;

@lexer::members {
    public static final int WHITESPACE = 1;
    public static final int COMMENTS = 2;
}

...the rest of your grammar goes here...

WS  :   [ \t\n\r]+ -> channel(WHITESPACE) ;  // channel(1)

SL_COMMENT
    :   '//' .*? '\n' -> channel(COMMENTS)   // channel(2)
    ;

如果你还没有《The Definitive ANTLR 4 Reference》一书,我建议你去拿它。将为您节省大量时间。上面的例子来自那本书。

于 2015-01-29T10:17:26.280 回答