win_flex下载以及基本使用 和实现tiny程序的词法分析(编译原理实验)

编译原理实验要用lex,找了好久找到win_flex。
百度云链接:链接:https://pan.baidu.com/s/1b4qovNdx8_gKdtYfeoijiQ
提取码:mipa
解压后如图,里面的test,out,a都是我做实验写的,没有删也打包进去了,所以如果有和我做同样实验的就很简单了。
解压后就是这样

正则表达式的规则:

符号解释,我的表述可能不太准确
ab代表ab连接串
a|b代表a串或者b串
a*代表a串的0次或多次重复
a+代表a串的1次或多次重复
a?代表a串的存在或不存在
.代表任意字符的匹配
[a-z]代表所有的小写字母中任意一个,[a-zA-Z]代表所有的字母中的任意一个。
[^a]代表所有不是a的字符中任意一个。

上面是正则表达式的写法,在lex中也是差不多的。

首先,要使用win_flex就要先编写.l文件,就是我图中的test1.l
lex文件(就是.l文件)的编写规则如下。
共可分为三个部分(我认为的)

1,在 %{ 和%}之间的为第一部分,这一部分的代码是和c的语法一样,他会被直接加在生成的test1.c文件的前面,主要是用来声明全局变量和包含头文件的。如下

%{
#include<stdio.h>
long long reserved_word_number=0;
long long special_symbol_number=0;
long long number_of_figures=0;
long long identifier_number=0;
long long space_number=0;
long long tab_number;
long long enter_number;
%}

最后一定记得是%}不是}%!
2.第二部分则是正则表达式的编写和 %% 和 %%之间的部分

reserved_word (if)|(then)|(else)|(end)|(repeat)|(until)|(read)|(write)
special_symbol ["+""\-""*""/""=""<""("")"";"]|(:=)
number [0-9]+
identifier [a-zA-Z]+
notes \{([^/}]|\n)*\}
space " "
tab "\t"
enter "\n"
%%
{reserved_word} {printf("reserved_word:%d %s\n",reserved_word_number++,yytext);fprintf(yyout,"reserved_word: %s\n",yytext);}
{special_symbol} {printf("special_symbol:%d %s\n",special_symbol_number++,yytext);fprintf(yyout,"special_symbol: %s\n",yytext);}
{number} {printf("number:%d %s\n",number_of_figures++,yytext);fprintf(yyout,"number: %s\n",yytext);}
{identifier} {printf("identifier:%d %s\n",identifier_number++,yytext);fprintf(yyout,"ID: %s\n",yytext);} 
{space} {printf("space:%d %s\n",space_number,yytext);/*fprintf(yyout,"reserved_word: %s",yytext);*/}
{tab} {printf("tab:%d %s\n",tab_number,yytext);}
{enter} {printf("enter:%d %s\n",enter_number,yytext);}
{notes} {/*printf("notes:%s\n",yytext);*/fprintf(yyout,"notes:%s\n",yytext);}
%%

正则表达式的编写部分,前面是名称,中间一个空格,然后是正则表达式,里面的元字符要匹配的话要用\进行转义。对连续多个元字符进行转义可以使用一对双引号,元字符有大中小括号,+,-,* 等等。

两个%%之间的部分就是在匹配到相应的表达式时要做的事
前面一对大括号之间是表达式名称,中间一个空格,后面一对括号里是匹配到后要做的事,语法为c,只要你在第一部分写了相应的头文件,那么c的函数都可以调用,yytext为匹配到的文本,
注意:若是有一段文本没有和写的任何正则表达式匹配,则会直接输出该段文本。

3.main函数以及yywarp函数

int main(){
yyin=fopen("C:/Users/qzz/Desktop/in.txt","r");
yyout=fopen("C:/Users/qzz/Desktop/out.txt","w");
yylex();
fclose(yyin);
fclose(yyout);
getchar();
return 0;
}
int yywrap(){
return 1;
}

会被直接加在源文件里,
yytext为匹配到的相应文本,yyout为输出,yyin为输入,
yywarp()函数为读到文件末尾时要做的事,返回1代表结束
yylex()为启动词法分析的函数,默认情况下输入为键盘,输出为屏幕,可通过在main函数里写,从这里可以看出,yyout和yyin就是文件指针 。

yyin=fopen(in_filepath,"r");
yyout=fopen(out_filepath,"w");

进行更改。
写好了lex文件之后了,就是利用win_flex生成.c文件了。
好像可以直接将lex文件拖到win_flex.exe上就会生成默认文件名的lex.yy.c的源文件,然后编译后就可以使用了。
也可以在flex目录栏里直接键入cmd打开控制台然后输入,test1和Test都是我自己的文件名,使用的时候记得相应的更改,注意,第一个是输出文件名,第二个是输入文件名。第一条是生成源文件,第二条是对生成的源文件进行编译
gcc所在目录一定要加在环境变量里,当然也可以直接用编译器打开源文件然后一键编译生成。

win_flex -o test1.c test1.l
gcc -o Test.exe test1.c

在这里插入图片描述

用IDE进行编译的话(比如VS),可能会出现提示少了 unistd.h头文件,这个只需要新建一个头文件,名字为unistd.h然后在里面写如下代码,同时记得把#include<unistd.h>的尖括号改为引号,以及改为 X64 模式,关闭sdl检查

/** This file is part of the Mingw32 package.
 *  unistd.h maps     (roughly) to io.h
 */
#ifndef _UNISTD_H
#define _UNISTD_H
#include <io.h>
#include <process.h>
#endif /* _UNISTD_H */


最后运行生成的exe文件,就可以进行词法分析啦,我是用的文件输入以及文件输出,结果如下
in.txt

{ Sample program
in TINY language -
computers factorial
}
read x;{input an integar}
if 0<x then { don't compute if x<=0}
fact :=1;
repeat
fact:=fact *x;
x:=x-1;
until x=0;
write fact{ output factorial of x}
end

out.txt

notes:{ Sample program
in TINY language -
computers factorial
}
reserved_word: read
ID: x
special_symbol: ;
notes:{input an integar}
reserved_word: if
number: 0
special_symbol: <
ID: x
reserved_word: then
notes:{ don't compute if x<=0}
ID: fact
special_symbol: :=
number: 1
special_symbol: ;
reserved_word: repeat
ID: fact
special_symbol: :=
ID: fact
special_symbol: *
ID: x
special_symbol: ;
ID: x
special_symbol: :=
ID: x
special_symbol: -
number: 1
special_symbol: ;
reserved_word: until
ID: x
special_symbol: =
number: 0
special_symbol: ;
reserved_word: write
ID: fact
notes:{ output factorial of x}
reserved_word: end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值