在这个过程中学习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个分区运算符时。我应该在哪里修改代码。任何建议。
编辑:
Lex Code:
%{
#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.
答案 0 :(得分:6)
根据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>>)