【问题标题】:Ambiguous reference of '\n' in lexer and parser rules in ANTLR 4ANTLR 4 中词法分析器和解析器规则中“\n”的模糊引用
【发布时间】:2014-03-25 08:10:21
【问题描述】:

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

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

//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: (.)*;

感谢回复!

皮特

【问题讨论】:

  • 我不使用 ANTLR,所以这只是我的观点:我认为您最好保留忽略 cmets 的原始解析器,使用它来识别您可能是的所有方法声明或其他标识符感兴趣,然后在手头有这些信息,重新扫描源文件的行,直到找到任何文档 cmets 的标识符。 cmets 语法与常规的上下文无关 C# 语法有些正交,我认为这使得编写一个可以同时处理这两种语法而又不会变得非常混乱的统一语法变得困难。
  • 您似乎确定您的语法不包含语法错误,但 C# 文档 cmets 不限于您上面描述的项目。在我的代码中实际使用的其他一些包括&lt;strong&lt;em&lt;threadsafety&lt;preliminary

标签: c# parsing c#-4.0 antlr antlr4


【解决方案1】:

我确信理论上可以在解析文件的其余部分的同时解析 XML 文档 cmets,但这是维护的噩梦,尤其是对于词法分析器规则。例如,您将如何处理以下情况?

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

您应该执行以下操作,而不是采用这种方法。

  1. 将所有文档评论令牌移动到他们自己的频道。

    @members {
        public const int DocCommentsChannel = 2;
    }
    
    DOC_COMMENT : '///' ~[\r\n]* -> channel(DocCommentsChannel);
    LINE_COMMENT : '//' ~[\r\n]* -> channel(HIDDEN);
    
  2. 解析后,编写代码检查ITokenStream 上的所有令牌实例,以获取导致某些项目声明的DocCommentsChannel 通道上的令牌,并将它们作为一个组进行处理。使用单独的解析器。这将通过从每行中删除前导 /// 字符并将生成的文本块作为根元素的主体(如 &lt;Comment&gt;{Your comment text here}&lt;/Comment&gt;)来创建注释的内存中 XML 表示来最容易地执行。然后,您可以调用 XDocument.Parse 来加载评论并在您认为合适的时候从那里处理它。

【讨论】:

  • 这不是我想要的,但可以这样做,谢谢。我需要文档 cmets 中的规则,因为它在 C# 中有一些规则。有些标签具有不同的含义,我必须将其解析为通用 XML。我将通过与所有其他语言(例如 Java)相同的方法处理一般 XML 中的文档。 Java有不同的cmets,这就是为什么我必须转移它。
  • @user3245590 如果您将文档 cmets 的规则添加到 C# 解析器,则 cmets 中的错误可能会阻止解析器继续解析您的 C# 代码并输出大多数人难以理解的错误消息.通过将您的 cmets 与其他代码分开分析,您可以生成更好的错误消息,并确保只有实际代码中的解析错误会影响解析器生成解析树的能力。
猜你喜欢
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-29
  • 2014-06-29
  • 1970-01-01
  • 2011-01-30
相关资源
最近更新 更多