关于C#语言规范中ASTERISK* Not_Slash_Or_Asterisk规则的疑问
C#多行注释产生式规则解读
先贴出原规则代码:
fragment Delimited_Comment : '/*' Delimited_Comment_Section* ASTERISK+ '/' ; fragment Delimited_Comment_Section : SLASH | ASTERISK* Not_Slash_Or_Asterisk ; fragment Not_Slash_Or_Asterisk : ~('/' | '*') // Any except SLASH or ASTERISK ;
核心疑问解答:ASTERISK* Not_Slash_Or_Asterisk的逻辑
你觉得的「矛盾点」其实是规则的分组设计,本质是把两种情况打包成一个分支:
ASTERISK*:匹配0个或多个连续星号Not_Slash_Or_Asterisk:必须跟一个非星号、非斜杠的字符
这个组合的作用是:专门处理注释内部「星号串+普通字符」或者「纯普通字符」的片段,同时确保这个片段的结尾不会是星号或斜杠——这样就不会和注释的结束标记*/混淆。
举个实际例子:
- 注释里的
***xyz会被拆成:ASTERISK*(3个*)+Not_Slash_Or_Asterisk(x),剩下的y、z会各自匹配「0个星号+普通字符」的分支 - 如果是单独的
***(后面没普通字符),这个分支不会匹配,而是留到规则末尾的ASTERISK+处理——因为C#允许注释结尾有任意多个星号(比如/***/是合法的多行注释)
各片段的分工拆解
Delimited_Comment:定义整个多行注释的完整结构- 开头固定是
/* - 中间可以有任意数量的
Delimited_Comment_Section(即注释内容) - 结尾必须是「1个或多个星号 +
/」,确保注释是正确闭合的
- 开头固定是
Delimited_Comment_Section:处理注释内部的两种合法内容- 分支1:单独的
SLASH(斜杠)——因为注释里单独的/不会触发结束,只有*/才是结束标记 - 分支2:
ASTERISK* Not_Slash_Or_Asterisk——覆盖「星号+普通字符」和「纯普通字符」两种场景
- 分支1:单独的
Not_Slash_Or_Asterisk:匹配除/和*之外的任意单个字符,核心是防止提前触发注释结束的判断
设计目的:避免歧义
这个规则是为了精准区分「注释内部的星号」和「注释结尾的星号」:只有当星号后面直接跟着/时,才会被识别为注释结束;如果星号后面跟着的是普通字符,就会被归为注释内容的一部分。
比如注释/* test * comment */,中间的*后面跟着空格(属于普通字符),所以不会被误判为结束,直到最后面的*紧跟/才会触发注释结束逻辑。
内容的提问来源于stack exchange,提问作者Logeshkumar S.
相关产品推荐
相关产品推荐

