下面是朝着正确方向的轻推。你所做的和我所做的主要区别在于我只做了两个正则表达式——一个用于空格,一个用于 ident(标识符)。我所说的标识符是指您想要注释掉的任何内容。这个正则表达式显然可以扩展为包含其他字符和符号。我还刚刚定义了开始和结束注释的三种模式,并将它们与我们可以传递给语法分析器的标记相关联(但这是一个全新的主题)。
我还更改了您向程序提供输入的方式。我发现将输入从文件重定向到程序并将输出重定向到另一个文件更干净 - 如果您需要的话。
以下是如何使用此程序的示例:
flex filename.l
g++ lex.yy.c -o lexer
./lexer < input.txt
如果需要,可以使用以下命令将输出重定向到另一个文件:
./lexer < input.txt > output.txt
而不是上面的最后一个命令。
注意:模式匹配末尾的 '.'(点)字符用作不匹配的字符、字符序列、符号等的全部内容。
使用正则表达式匹配注释行的模式匹配有很多细微差别。例如,即使注释行是字符串的一部分,它仍然会匹配。
前任。" //This is a comment in a string! "
你需要做更多的工作来克服这些细微差别——就像我说的,这是朝着正确方向的推动。
您可以执行类似的操作来实现您的目标:
%{
#include <stdio.h>
int sline = 0;
int mline = 0;
#define T_SLINE 0001
#define T_BEGIN_MLINE 0002
#define T_END_MLINE 0003
#define T_UNKNOWN 0004
%}
WSPACE [ \t\r]+
IDENT [a-zA-Z0-9]
%%
"//" {
printf("TOKEN: T_SLINE LEXEME: %s\n", yytext);
sline++;
return T_SLINE;
}
"/*" {
printf("TOKEN: T_BEGIN_MLINE LEXEME: %s\n", yytext);
return T_BEGIN_MLINE;
}
"*/" {
printf("TOKEN: T_END_MLINE LEXEME: %s\n", yytext);
mline++;
return T_END_MLINE;
}
{IDENT} {/*Do nothing*/}
{WSPACE} { /*Do Nothing*/}
. {
printf("TOKEN: UNKNOWN LEXEME: %s\n", yytext);
return T_UNKNOWN;
}
%%
int yywrap(void) { return 1; }
int main(void) {
while ( yylex() );
printf("Single-line comments = %d\n Multi-line comments = %d\n Total comments = %d\n", sline, mline, (sline + mline));
return 0;
}