Parsing 同时分析多行注释和字符串文字的语法

Parsing 同时分析多行注释和字符串文字的语法,parsing,antlr,grammar,lexer,Parsing,Antlr,Grammar,Lexer,我正在尝试解析C++/Java风格的源文件,并希望将注释、字符串文本和空格作为标记进行隔离 对于空格和注释,通常建议的解决方案是(使用ANTLR语法): 但是,问题是我的源文件也由字符串文本组成,例如 printf(" /* something looks like comment and whitespace \n"); printf(" something looks like comment and whitespace */ \n"); 内部的“东西”应该被认为是单个令牌,但

我正在尝试解析C++/Java风格的源文件,并希望将注释、字符串文本和空格作为标记进行隔离

对于空格和注释,通常建议的解决方案是(使用ANTLR语法):

但是,问题是我的源文件也由字符串文本组成,例如

printf("   /* something looks like comment and whitespace \n");
printf("    something looks like comment and whitespace */ \n");

内部的“东西”应该被认为是单个令牌,但是我的ANTLR词条规则显然会把它们看作是MLY注释令牌:

    /* something looks like comment and whitespace \n");
printf("    something looks like comment and whitespace */
但我无法创建另一个lexer规则来将令牌定义为一对内的某个东西(假设\“转义序列得到正确处理),因为这将被错误地视为字符串令牌:

/*  comment...."comment that looks */   /*like a string literal"...more comment */
简而言之,2对/**/和“”将相互干扰,因为每对都可以包含另一对的开头作为其有效内容。那么我们应该如何定义一个lexer语法来处理这两种情况呢

JavaMan写道:

我正在尝试解析C++/Java风格的源文件,并希望将注释、字符串文字和空白分隔为标记

您不应该也匹配字符文本吗?考虑:

charc='”;
不应将双引号视为字符串文字的开头

JavaMan写道:

简而言之,2对/**/和“”将相互干扰

错误,不是。如果一个
/*
首先被“看到”,它将一直消耗到第一个
*/
。对于以下输入:

/*注释…“看起来像字符串文字的注释”…更多注释*/
这意味着双引号也会被使用。字符串文字也是如此:当首先看到双引号时,
/*
和/或
*/
将被使用,直到遇到下一个(未转义)

还是我误解了

请注意,您可以在
*
+
之前从语法中删除
选项{greedy=false;}:
,这些选项默认为取消冻结

这里有一个方法:

语法T;
作语法分析
:(t=。
{
如果($t.type!=其他){
System.out.printf(“\%-10s>\%s<
空间><
空间><
字符串>“foo\t/*bar*/baz”<
空间>
<
空间><
空间><
空间><
字符>“”<
空间><
SL_COMMENT>//COMMENT/*此处<
空间>
<
ML_COMMENT>/*多个“无字符串”
线*/<

基本上,您的问题是:在字符串文本中,注释(/*和//)必须忽略,反之亦然。在我看来,这只能通过顺序读取来解决。在逐个字符地遍历源文件时,您可以将其作为状态机处理,其中包含状态文本、BlockComment、LineComment和StringLiteral

这是一个很难用正则表达式甚至语法来解决的问题


请注意,任何C/C++/C#/Java lexer都需要处理完全相同的问题。我很确定它采用了类似于状态机的解决方案。因此,如果可以的话,我的建议是,以这种方式定制您的lexer。

谢谢,您是对的。我对lexer规则工作方式的误解。顺便说一句,SL|U注释中的~('\r'.\n')*等同于(~('\r'|'\n'))*?@JavaMan,是的,
~('\r'|'\n')*
(~('\r'|'\n'))*
是另一个lexer规则必须的吗?如果一个字符不能与任何lexer规则匹配,会发生什么情况?@JavaMan,lexer会发出“sees”的警告任何lexer规则都不匹配的字符。因此,是的,
其他
规则必须在其中。“这是一个很难用正则表达式甚至语法解决的问题。”,不,不是。它可以很容易地翻译成几个正则表达式:看我的答案。你答案的高度复杂性使我提供了这个答案作为替代。你的答案可能是这个特殊情况下的解决方案,但不值得羡慕。我不同意我的答案是复杂的:一个只有基本知识的人当然,ANTLR可以理解。此外,你所说的是不正确的:OP问题的解决方案是一对正则表达式(语法是正则的!)。即使在这种情况下,它也是正确的。但是你的解决方案很直接。尽管如此,我发现它是可以解释的。同意不同意。
/*  comment...."comment that looks */   /*like a string literal"...more comment */