ANTLR 4.5 中的额外通道

6
我正在使用antlr 4.5构建一个解析器,用于处理包含多个特殊注释格式的语言,并希望将其流式传输到不同的频道。看起来antlr 4.5已经通过一个新的声明额外词法分析器频道的结构进行了扩展:
文档中摘录的:
自版本4.5起,您还可以像枚举一样定义通道名称,如以下构造方法位于词法分析器规则上方: channels { 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

如果我将词法分析器和语法分析器拆分为两个不同的文件,并使用import语句将词法分析器导入到语法分析器中,我仍然会得到与上面相同的错误。
在组合语法中使用整数常量代替名称。
-> channel(10000)

产生以下错误。
error(164): Scade6.g4:8:0: custom channels are not supported in combined grammars

如果我将词法分析器和语法分析器分为两个文件,并使用整数常量,就没有警告了,但这对于可读性来说并不是很令人满意。有什么办法可以使额外的通道被正确命名吗?(无论是使用合并还是分离的词法分析器/语法分析器规范,都没有特别偏爱)祝好!
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" 这本书,我建议你去获取一下。它会为你节省很多时间。上面的例子就来自于这本书。


4
事实上,你推荐的书中的解决方案无效,并且会产生我在帖子中描述的症状。ANTLR 不知道 WHITESPACE 和 COMMENTS 被定义为词法分析器成员并发出警告。该错误报告是针对版本 4.2 的,请参见 链接链接,直到 v4.5 才引入了 channels { } 结构来解决这个问题,但不幸的是,它似乎并没有像预期的那样起作用,至少从我的实验结果来看。 - remi
2
这本书的解决方案是有效的。刚刚在antlr4.4上进行了测试。它确实会产生相同的警告,但根据此处所述,错误仅适用于解释器。我的猜测是,您的实际应用程序将使用生成的代码,因此此警告不相关。 - user3890638
1
在Antlr4.7.1中使用通道生成:错误(50):语法错误:“channels {”让我完全惊讶 - garyM
@garyM 尝试将通道放在顶部,就在 lexer grammar blah; 之后。 - v.oddou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接