首页 文章

在ANTLR 4中的词法分析器和解析器规则中'\n'的模糊引用

提问于
浏览
1

First: This is not a syntactic error! My grammar file does not contain any error! 我想为我的程序编写一个C#语法 . 我从CodePlex下载了这个语法:ANTLR C# 4.0 Grammar我没有找到更好的AN#4语法C#语法 . 这个语法不支持对我的程序非常重要的文档注释 . 这个语法会跳过所有注释,因此我删除了文档注释的删除并编写了我的代码以获取文档注释,但 I don't know how to say, that after "\n" has to be "///". I am afraid, that the lexer, when he recognizes "\n", skips the lexical symbol automatically and never match this: ('\n' '///')? in my parser rule . 有谁知道,如何解决这个问题?或者任何人都可以向我解释,我的代码是对的,如果是的话?

这是我的文档注释解析器规则:

//documentation comments
doc_comment :
'///' (  summary remarks?
        |remarks
        );
summary :
    '<summary' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* tag_body+ (('\n' '///')* comment_text ('\n' '///')*)* '</summary>';
remarks :
    '<remarks' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</remarks>';
tag_body :   '<c' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</c>'
            |'<code' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</code>'
            |'<example' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</example>'
            |'<exception' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</exception>'
            |'<include' 'file' '=' '\'' comment_text '\'' 'path' '=' '\'' comment_text ('[' '@name' '=' '"'identifier '"' ']')? '\'' '/' '>'
            |'<list' 'type' '=' ('"bullet"' | '"number"' | '"table"') '>' ('\n' '///')* listheader? listitem? '</list>' 
            |'<para' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</para>' 
            |'<param' 'name' '=' '"' identifier '"' '>' (('\n' '///')* comment_text ('\n' '///')*)* '</param>'
            |'<paramref' 'name' '=' '"' comment_text '"' '/' '>'
            |'<permission' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</permission>'
            |'<returns' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</returns>'
            |'<see' cref '/' '>'
            |'<seealso' cref '/' '>'
            |'<typeparam' 'name' '=' '"' comment_text '"' '>' (('\n' '///')* comment_text ('\n' '///')*)* '</typeparam>'
            |'<typeparamref' 'name' '=' '"' comment_text '"' '/' '>'
            |'<value' cref? '>' (('\n' '///')* comment_text ('\n' '///')*)* '</value>';
cref : 'cref' '=' '"' comment_text '"' ;
listheader : '<listheader>' ('<term>' (('\n' '///')* comment_text ('\n' '///')*)* '</term>')? ('<description>' (('\n' '///')* comment_text ('\n' '///')*)* '</description>')? '</listheader>';
listitem : '<listitem>' ('<term>' (('\n' '///')* comment_text ('\n' '///')*)* '</term>')? ('<description>' (('\n' '///')* comment_text ('\n' '///')*)* '</description>')? '</listitem>';

这里是白色空间的词法分析器规则(WS),comment_text的解析器规则和注释字符的词法分析器规则(ANY_CHARS):

WS:
    (' '  |  '\r'  |  '\t'  |  '\n'  ) -> skip;
comment_text : ANY_CHARS;
fragment ANY_CHARS: (.)*;

谢谢你的回复!

皮特

1 回答

  • 0

    我确信理论上可以在文件的其余部分同时解析XML文档注释,但这是一个维护噩梦,特别是对于词法分析器规则 . 例如,您将如何处理以下内容?

    /// <see
    ///      cref="Something"
    /// />
    

    您应该执行以下操作,而不是采用此方法 .

    • 将所有文档评论标记移动到他们自己的 Channels .
    @members {
        public const int DocCommentsChannel = 2;
    }
    
    DOC_COMMENT : '///' ~[\r\n]* -> channel(DocCommentsChannel);
    LINE_COMMENT : '//' ~[\r\n]* -> channel(HIDDEN);
    
    • 解析后,编写代码以检查 DocCommentsChannel 通道上所有令牌实例的 ITokenStream ,直到某个项目的声明为止,并将它们作为一个组进行处理 . 使用单独的解析器 . 通过从每行中删除前导 /// 字符并将生成的文本块放置为根元素(如 <Comment>{Your comment text here}</Comment> )的主体,可以通过创建注释的内存中XML表示来轻松执行此操作 . 然后,您可以调用XDocument.Parse加载注释并根据需要从那里处理注释 .

相关问题