lex创建词法分析程序

词法分析程序作用




lex是构建此法分析程序的工具,流程如下

  1. 编写模式和该模式对应的c处理程序
  2. lex生成lex.yy.c,然后可以通过调用yylex()来使用这个lex.yy.c

编写模式

  • . 任意字符,除了\n
  • * 前面表达式重复0-n次
  • [] 括号内的任意字符,如[0-9]表示0到9的任一个数字
  • ^ 行的开头,也作为[]内部第一个字符表示否定
  • $ 行的末尾,可参考vim快捷键
  • {} 括号内的数字表示重复的次数的范围,\d{2}表示两位的数字,包含名称,则用该名称替换
  • \ 转移元字符
  • + 前面表达式重复1-n次
  • ? 前面表达式重复0-1次
  • | 任选一种,比如a|b可匹配的为a,b
  • " " 引号内的字符解释为字面意义
  • / 匹配需要前后的条件都满足,但是只截取/的前半部分
  • () 一个正则表达式的组合

格式



%{


%}
被称为定义段,为c代码编写,将被拷贝到lex.yy.c中去

%%
标记第一部分结束

第二部分是规则段,也就是许多条模式和对应动作

%%
标记规则段结束

第三部分是代码段,c语言编写,也是直接复制到lex.yy.c


实例,筛选小数

float.l
%{

%}
%%

-?(([0-9]+)|([0-9]*\.[0-9]+))	{ printf("%s is a number\n",yytext); }
.	;
%%

main(){
	yylex();
}

nosourcesmatoMacBook-Pro:lex nosources$ lex float.l
nosourcesmatoMacBook-Pro:lex nosources$ cc lex.yy.c -o float -ll
运行编译好的词法分析器,就可以筛选输入流里面的小数了
nosourcesmatoMacBook-Pro:lex nosources$ ./float
1.2 333 s.d  3.4
1.2 is a number
333 is a number
3.4 is a number


实例,单词计数器

wc.l
%{
unsigned int charCount = 0, wordCount = 0, lineCount = 0;
%}

%%

[0-9a-zA-Z]* 	                {
					wordCount++;
					charCount += yyleng;
				}
\n 				{ 
					charCount++; 
					lineCount++;
				}
.				{
					charCount++;
				}
%%

int main(argc, argv)
int argc;
char** argv;
{
	if (argc > 1){
		FILE *file;
		file = fopen(argv[1], "r");
		if (!file){
			fprintf(stderr, "could not open %s\n", argv[1]);
			exit(1);
		}
		yyin = file;
	}
	yylex();
	printf("word:%d, char:%d, line:%d\n", wordCount, charCount, lineCount);
	return 0;
}

test
sdf adsfa asdf d


编译并且运行
mini2:wc nosources$ lex wc.l && cc lex.yy.c -o wc -ll
mini2:wc nosources$ ./wc test
word:4, char:17, line:1

因为yylex()没有遇到文件结尾不会返回,所以需要写成读文件的形势,不然,可以写成下面这样
wc2.l
%{
unsigned int charCount = 0, wordCount = 0, lineCount = 0;
%}

%%

[0-9a-zA-Z]* 	{
					wordCount++;
					charCount += yyleng;
				}
\n 				{ 
					charCount++; 
					lineCount++;
				}
.				{
					charCount++;
				}
%%

int main(argc, argv)
int argc;
char** argv;
{
	yylex();
	printf("word:%d, char:%d, line:%d\n", wordCount, charCount, lineCount);
	return 0;
}

mini2:wc nosources$ lex wc2.l && cc lex.yy.c -o wc2 -ll

mini2:wc nosources$ ./wc2 < test
word:4, char:17, line:1

起始位置

遇到某一个匹配的时候,可以进入到一种特殊的匹配模式,这种模式下的匹配都以起始位置为开头,比如下面的程序可以知道一个函数有多少行
%{
	
%}

%s MAGIC
%%

<MAGIC>\}		{
					BEGIN 0; printf("\nEnd MAGIC:");
				}
\{				{
					BEGIN MAGIC; printf("\nBegin MAGIC\n");
				}
\w				{
					ECHO;
				}
%%

main(){
	yylex();
}

mini2:startPosition nosources$ lex startPosition.l && cc lex.yy.c -o sp -ll
mini2:startPosition nosources$ ./sp
ad { int a = 1;}
ad 
Begin MAGIC
 int a = 1;
End MAGIC:



































  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验二 词法分析器 一、实验目的 掌握词法分析器的构造原理,掌握手工编程或LEX编程方法之一。 二、实验内容 编写一个LEX程序,使之生成一个词法分析器,能够输入的源程序转换为单词序列输出。 三、实验环境 Flex+VC6.0 四、实验注意 1.Id正则表达式:{letter}({letter}|{digit})* 2.Num正则表达式:{digit}+(\.{digit}+)?(E[+-]?{digit}+)? 3.注释:(\/\*(.)*\*\/) 4.关键字再加上其他字符就又能编程id,所以在词法分析时,id的判断应该放在关键字前面,这样才不会误判 5.由于本程序知识简单的打印数字,因此没有考虑数字的转换 6.">="比">"多一个字符,它应该放在前面判断,其他类似的也应该如此安排 五、实验代码 ******************************************************************************* 实验文件lex.l、lex.yy.c 实验结果:lex.exe 运行方式:打开lex.exe,弹出input.txt,在其中输入所要测试的程序,保存并关闭,即可在output.txt中看到所得结果 ******************************************************************************* %{ void Install(char *type); %} %option noyywrap delim [ \t] newline [\n] digit [0-9] num {digit}+(\.{digit}+)?(E[+-]?{digit}+)? letter [A-Za-z] id {letter}({letter}|{digit})* key ("if"|"while"|"do"|"break"|"true") basic ("int"|"float"|"bool"|"char") op (">="|""|"<"|"="|"!="|"+"|"-"|"*"|"/") comment (\/\*(.)*\*\/) %% delim {;} newline {printf("\n");} {num} {Install("Num");} {key} {Install("Key");} {basic} {Install("Basic");} {op} {Install("Op");} ";" {Install("Comma");} {id} {Install("ID");} {comment} {Install("Comment");} "(" | "[" | "{" {Install("lbracket");} ")" | "]" | "}" {Install("rbracket");} %% void Install(char *s) { fprintf(yyout, "%s:%s ", s, yytext); } int main() { printf("please input the test program in input.txt\n"); system("input.txt"); yyin = fopen("input.txt", "r"); yyout = fopen("output.txt", "w" ); yylex(); fclose(yyout); fclose(yyin); printf("analysis result in output.txt\n"); system("output.txt"); return 0; } 六、实验小结 本次的实验由于使用了flex,所以代码较短,麻烦的事flex的正则式表达,由于该使用规则只有简单介绍,而网上找的教程难免有比重就轻之嫌,所以得到上述表达式着实费力,且有的没有成功,例如bracket的(\ ((.)*\ ))或者("("(.)*")")使用时都没有成功,所以便单独写出,有点不伦不类。至于其他的,都较为简单,完。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值