我在这个过程中学习了 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.
最佳答案
根据 Lex 手册:
The lexical analysis programs written with Lex accept ambiguous specifications and choose the longest match possible at each input point. If necessary, substantial lookahead is performed on the input, but the input stream will be backed up to the end of the current partition, so that the user has general freedom to manipulate it.
所以你不需要做任何特别的事情 - //
长于 /
所以当它看到两个时,它会更喜欢评论而不是除法运算符。但是,您没有发布您的评论规则 - 它在哪里?
编辑:没关系,我看到了。 [//]
是一个字符类。删除方括号。此外,您需要匹配到行尾 - 否则您将只允许空注释。所以你的正则表达式应该是这样的:
//[^\r\n]*\r\n
(根据需要为您支持的换行符进行调整 - 这个要求换行符正好是 \r\n
)。
编辑 2:@tur1ng 提出了一个很好的观点 - 您文件中的最后一行可能不会以换行符结尾。我查了一下,Lex 支持 <<EOF>>
也在其正则表达式中(参见 http://pltplp.net/lex-yacc/lex.html.en )。所以你可以改成:
//[^\r\n]*((\r\n)|<<EOF>>)
关于c - 无法识别 Lex 中的单行注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2249692/