%{
#undef yywrap
#define yywrap() 1
#include<stdio.h>
int statements = 0;
int ids = 0;
int assign = 0;
int rel = 0;
int keywords = 0;
int integers = 0;
%}
DIGIT [0-9]
LETTER [A-Za-z]
TYPE int|char|bool|float|void|for|do|while|if|else|return|void
%option yylineno
%option noyywrap
%%
\n {statements++;}
{TYPE} {/*printf("%s\n",yytext);*/keywords++;}
(<|>|<=|>=|==) {rel++;}
'#'/[a-zA-Z0-9]* {;}
[a-zA-Z]+[a-zA-Z0-9]* {printf("%s\n",yytext);ids++;}
= {assign++;}
[0-9]+ {integers++;}
. {;}
%%
void main(int argc, char **argv)
{
FILE *fh;
if (argc == 2 && (fh = fopen(argv[1], "r"))) {
yyin = fh;
}
yylex();
printf("statements = %d ids = %d assign = %d rel = %d keywords = %d integers = %d \n",statements,ids,assign,rel,keywords,integers);
}
//输入file.c
#include<stdio.h>
void main(){
float a123;
char a;
char b123;
char c;
int ab[5];
int bc[2];
int ca[7];
int ds[4];
for( a = 0; a < 5 ;a++)
printf("%d ", a);
return 0;
}
输出:
include
stdio
h
main
a123
a
b123
c
ab
bc
ca
ds
a
a
a
printf
d
a
statements = 14 ids = 18 assign = 1 rel = 3 keywords = 11 integers = 7
我正在打印标识符。 #include<stdio.h>
被视为标识符。我该如何避免这种情况?
我尝试了'#'/[a-zA-Z0-9]* {;}
规则:动作对,但它仍被视为标识符。该文件如何被标记化?
%d
中的printf
字符串也被计为标识符。我已明确写过标识符应该只以字母开头,那么为什么%d
被推断为标识符?
答案 0 :(得分:2)
我尝试了
'#'/[a-zA-Z0-9]* {;}
规则:动作对,但[include
]仍被视为标识符。该文件如何被标记化?
一次识别一个代币。每个令牌都从前一个令牌结束的地方开始。
'#'/[a-zA-Z0-9]*
匹配&#39; # &#39; ,前提是[a-zA-Z0-9]*
。您可能意味着"#"/[a-zA-Z0-9]*
(带双引号)与#匹配,再次提供后跟字母或数字。请注意,只匹配#; /
之后的模式是&#34;尾随上下文&#34;,这基本上是一个先行断言。在这种情况下,前瞻是没有意义的,因为[a-zA-Z0-9]*
可以匹配空字符串,因此任何#都将匹配。无论如何,在#作为令牌匹配后,扫描将继续下一个字符。所以下一个标记是include
。
由于拼写错误,该模式不匹配。 (源代码中没有撇号。)所以实际匹配的是你的&#34;后备&#34; rule:规则为.
的规则。 (我们将此称为后备规则,因为它匹配任何内容。实际上,它应该是.|\n
,因为.
匹配除换行符之外的任何内容,但只要您有一些匹配换行符的规则,它就是& #39;可以使用.
。如果您没有提供备用规则,则会通过flex自动插入一个ECHO
动作。)
因此,#将被忽略(就像您按照预期编写规则一样)并再次使用令牌include
进行扫描。< / p>
如果您想忽略整个预处理器指令,可以执行类似
的操作^ [[:blank:]]#。* {; }
(来自评论)我得到
stdio
和h
作为关键字,这与我给出的定义有什么关系?中间的.
发生了什么?
在回退规则忽略&lt; 之后,stdio
匹配。由于[a-zA-Z]+[a-zA-Z0-9]*
不匹配字母和数字以外的任何内容,因此。不会被视为令牌的一部分。然后,。被回退规则匹配并忽略,然后匹配h
。
%d
中的printf
字符串也被计为标识符。
不是真的。回退规则明确忽略%(与&#34; 一样),然后d
作为标识符进行游行。如果要忽略字符串文字中的单词,则必须识别并忽略字符串文字。
答案 1 :(得分:0)
#include指令是一个预处理程序指令,因此由预处理程序进行预处理。预处理器包含头文件并删除#include指令因此在预处理后将程序作为输入提供给编译器时,它没有任何预处理器指令,如#include。 所以你不需要编写代码来检测#include,因为编译器都没有看到它,也没有设计为#include指令的标记。
答案 2 :(得分:0)
在规则部分添加以下行对我有用:
#.* ;
这里的规则是#.*,动作是;。 #.* 将捕获以 # 和 ; 开头的行什么都不做,所以基本上这将忽略以 # 开头的行。