无法在Lex中识别单行注释

10

我正在学习词法分析器,并为C语言生成标记。我试图识别单行注释“//”,但是与除法运算符产生冲突。

[1-9][0-9]*|0x[0-9a-fA-F][0-9a-fA-F]*           return NUMBER;
[a-zA-Z][a-zA-Z0-9]*                            return IDENT;
/                                               {return DIVIDE;}

[ \t\r\n]
[//]

但是当我运行这个例子并输入 // 时,它把它们识别为2个除法运算符。我应该在哪里修改代码呢?有什么建议吗。

编辑:

词法分析器代码:

%{
#include "y.tab.h"
%}
%array
%%
if                                              {return IF;}
while                                           {return WHILE;}
else                                            {return ELSE;}
int                                             {return INT;}
return                                          {return RETURN;}
\/\/[^\r\n]*
[1-9][0-9]*|0x[0-9a-fA-F][0-9a-fA-F]*           return NUMBER;
[a-zA-Z][a-zA-Z0-9]*                            return IDENT;

[+]                                             {return ADD;}
[-]                                             {return SUB;}
[<]                                             {return LESS;}
[>]                                             {return GREAT;}
[*]                                             {return MULT;}
[/]                                             {return DIVIDE;}
[;]                                             {return SEMICOLON;}

\{                                              return LBRACE;
\}                                              return RBRACE;

[ \t\r\n]

\(                                              return LPAREN;

\)                                              return RPAREN;

.                                               return BADCHAR;
%%

以下是我使用的头文件。
typedef enum {END=0, WHILE, IF, ELSE,RETURN, IDENT, LPAREN, RPAREN,INT,LBRACE,RBRACE, SEMICOLON, EQUALITY, DIVIDE, MULT, LESS, GREAT,
 ADD, SUB, NUMBER,BADCHAR} Token;

以下是我正在运行的输入内容:
//
/
p
Token 16, text /
Token 16, text /
Token 16, text /
Token 5, text p

当我运行它时,注释被消耗掉,甚至除号也被忽略了。但是当我输入p时,请注意它对上述列出的运算符进行分类,这是不应该发生的。

Note: Am trying to ignore tabs, newline characters and single line comments. 

Note 2: \/\/[^\r\n]* I have understood where I committed the mistake and wanted to share this.

回答你的问题:https://dev59.com/kG_Xa4cB1Zd3GeqP364S - Nilesh Agrawal
1个回答

8
根据Lex手册:
使用Lex编写的词法分析程序接受模糊的规范,并在每个输入点选择最长的匹配。如果必要,会对输入进行大量的前瞻,但是输入流将被备份到当前分区的末尾,以便用户可以自由操纵它。
因此,您不需要做任何特殊处理 - ///更长,因此当它看到两个时,它将优先考虑注释而不是除法运算符。但是,您没有发布您的注释规则 - 它在哪里?
编辑:没关系,我看到了。 [//]是一个字符类。去掉方括号。此外,您将希望匹配到行尾 - 否则,您只允许空注释。因此,您的正则表达式应该是这样的: //[^\r\n]*\r\n(根据您支持的换行符进行必要的调整 - 这个需要一个换行符恰好为\r\n)。
编辑2:@tur1ng提出了一个很好的观点 - 您的文件中的最后一行可能没有以换行符结尾。我查了一下,Lex也支持在其正则表达式中使用<<EOF>>(请参见http://pltplp.net/lex-yacc/lex.html.en)。因此,您可以更改为: //[^\r\n]*((\r\n)|<<EOF>>)

我正在尝试忽略制表符、换行符和单行注释。 - user265867
你是对的。匹配的阴影不是问题,我已经删除了我的答案。 - John Knoeller
如果最后一行包含类似于“// ...”的内容,那么“//[^\r\n]*\r\n”会失败,“//[^\r\n]*”才是正确的方法。 - tur1ng
当我第一次运行这个例子时,// s Token 16,文本/ Token 16,文本/ Token 5,文本s第一次输入注释时,它被消耗掉了,但是下一次我输入一个s,它会识别两次除法,然后识别一个s。 - user265867
此外,请在您的问题中以适当的格式发布测试用例,这样我就可以清楚地看到您的输入和结果是什么。 - danben
//.*存在什么问题?无论如何,.*都不会识别换行符。 - Tejesh Raut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接