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



首先:这不是语法错误!我的语法文件不包含任何错误我想为我的程序编写一个C#语法。我已从CodePlex下载了以下语法:ANTLR C#4.0语法我还没有为ANTLR 4找到更好的C#语法。这个语法不支持对我的程序非常重要的文档注释。这个语法跳过了所有的注释,所以我删除了文档注释的跳过,并为文档注释编写了代码,但我不知道如何说,"\n"之后必须是"///"。恐怕lexer在识别"\n"时,会自动跳过词法符号,并且永远不会匹配以下内容:('\n'///')?在我的解析器规则中。有人知道如何解决这个问题吗?或者有人能向我解释一下,我的代码是正确的吗?

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

//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)的lexer规则,一个用于comment_text的解析器规则,以及一个用于注释字符(ANY_chars)的lexr规则:

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

谢谢回复!

Pete

我相信理论上可以在解析文件其余部分的同时解析XML文档注释,但这是一场维护噩梦,尤其是对于lexer规则。例如,您将如何处理以下问题?

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

与其采取这种方法,您应该执行以下操作。

  1. 将所有文档注释标记移动到它们自己的通道中。

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

相关内容

  • 没有找到相关文章

最新更新