10

在这个过程中学习 lex,我正在为 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.
4

1 回答 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>>)

于 2010-02-12T04:40:05.780 回答