【问题标题】:ANTLR lexer for C-style comment用于 C 风格注释的 ANTLR 词法分析器
【发布时间】:2015-03-22 03:08:31
【问题描述】:

我目前正在研究支持 C 样式注释的 ANTLR 词法分析器规则。对于这样的目标,有一个广泛推荐的规则:

C_COMMENT
:
'/*' (options {greedy=false;}: .)* '*/'
{ $channel=HIDDEN; }
;

但是我想要的是另一种选择:'+' 不允许成为评论正文的第一个非空格字符,例如/* +blablabla*/ 不是有效的评论。 然后我尝试了这样的事情:

C_COMMENT
:
'/*' (' '|'\r'|'\t'|'\n')* ~(' '|'\r'|'\t'|'\n'|'+') (options {greedy=false;}: .)* '*/'
{ $channel=HIDDEN; }
;

除了空的 cmets /* */ 之外,它几乎成功了。所以我尝试了这样的事情:

C_COMMENT
:
'/*' (' '|'\r'|'\t'|'\n')*
(
'*/'
|
(~(' '|'\r'|'\t'|'\n'|'+') (options {greedy=false;}: .)* '*/')
)
{ $channel=HIDDEN; }
;

它,以及我没有列出的一堆类似的,从来没有工作过。 /* */ 中的 * / 总是属于 ~(' '|'\r'|'\t'|'\n'|'+') 部分。

最后我得到了这样的工作:

C_COMMENT
:
'/*' (' '|'\r'|'\t'|'\n')* '*/'
{ $channel=HIDDEN; }
|
'/*' (' '|'\r'|'\t'|'\n')*
(
'*/'
|
(~(' '|'\r'|'\t'|'\n'|'+') (options {greedy=false;}: .)* '*/')
)
{ $channel=HIDDEN; }
;

尽管 ANTLR 警告说 /* */ 之类的模式可以匹配这两种选择。

谁能帮我理解这一切?我的意思是,为什么在最后一个之上没有任何效果。

提前致谢。

【问题讨论】:

    标签: regex parsing antlr grammar lexer


    【解决方案1】:

    为什么不这样做:

    grammar T;
    
    parse
     : ( c_comment
       | plus_comment
       )* 
       EOF
     ;
    
    c_comment
     : C_COMMENT
     ;
    
    plus_comment
     : PLUS_COMMENT
     ;
    
    PLUS_COMMENT
     : '/*' S* '+' .* '*/'
     ;
    
    C_COMMENT
     : '/*' .* '*/'
     ;
    
    SPACES
     : S+ {skip();}
     ;
    
    fragment S
     : ' ' | '\t' | '\r' | '\n'
     ;
    

    它将解析输入:

    /**/
    /* + as*/
    /* sdcdcds sdcds */

    如下:

    这里的技巧是定义PLUS_COMMENT 之前 C_COMMENT。这样,如果词法分析器偶然发现"/* s",它会从PLUS_COMMENT 回退到C_COMMENT,因为它无法匹配+

    【讨论】:

    • 嗨,巴特,感谢您的回答。我很抱歉我没有完全解决我的问题。我没有制定 /*+ ... * / 词法分析器规则的原因是存在 /*+ ... * / 的遗留解析器规则。所以我的意思是在词法分析器中处理 /* ... * / (... 以非'+'字符开头) 并让 /*+ ... * / 仍然命中解析器,其中有子规则对于 /*+ 和 * / 之间的内容。所以我仍然想专注于我以前的问题,即为什么“ /* * / 中的 * / 总是属于 ~(' '|'\r'|'\t'|'\n'|'+') 部分。 "
    • 我不明白。您仍然可以将C_COMMENT 放在HIDDEN 频道上,同时让PLUS_COMMENT 访问解析器。
    • 我的意思是,PLUS_COMMENT 中的 .* 意味着另一个解析器规则。我不确定如何抽象 .* 部分并让解析器规则处理它。
    • 我的建议是为/* + ... */ 中的任何内容编写一个单独的语法(并按照我的建议将其标记为单个标记)。尝试处理您的 PLUS 评论中的任何内容(并尝试让 C_COMMENT not 匹配可选空格和开头的 +)使其变得一团糟。使其工作将涉及自定义(Java)代码和谓词:它不会像您现在尝试做的那样工作。也许 ANTLRv4 的词法分析器可以在没有自定义代码的情况下处理它?祝你好运!
    • 是的,巴特,我想我会保持现在的状态,直到有一天我们转向 V4。谢谢你的帮助。真的很感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    相关资源
    最近更新 更多