编译原理实战——使用Lex/Flex进行编写一个有一定词汇量的词法分
编译原理实战——使用Lex/Flex进行编写一个有一定词汇量的词法分析器by steve yu 2019.9.30 参考文档:1.https://blog.csdn.net/mist14/article/details/48641349 1.Flex工具的概述Flex工具是生成C语言的工具,我们在日常生活中,如果直接使用C语言进行编写词法分析器,会嵌套太多的if语句,或者switch语句,那么会使我们的代码出现混乱(可读性较差),于是,Flex工具,可以让我们直接使用正规式,进行词法分析。 2.Flex的安装与使用(CentOS 系统为例)yum intsall flex -y 3.“.l”文件的概述我们安装完flex工具,可以编写一个文件,这个文件可以通过flex编译成C程序,进行词法分析。 flex的语法被分为3个部分: {definitions} %% {rules} %% {user subroutines} defnitions 这部分由正则式组成,我们在正规式的编写中,有这样语法规则。 1. INT [1-9][0-9]*|[0] /*整数类型,0或不以0开头的由0-9组成的字符串*/ 2. FLOAT [0-9]*[.][0-9]+([eE][+-]?[0-9]*|[0])?f? /*浮点数格式*/ 3. LP ( /*一个左圆括号*/ rules rules规则部分语法如下: {LABEL1} | {LABLE2} | ... { /*TODO*/ } TODO部分是告诉编译器在匹配到字符串后需要做什么。 {INT} { printf("Pick up an integer,value is %d",atoi(yytext)); printf("Pick up an integer,value is %s",yytext); } user subroutines 此处主要是放置用户需要执行的c语言代码。他们会被原封不动地加入到lex.yy.c文件的末尾。 4.文档(这边以C程序的关键字为例)数据类型关键字(12个)
控制语句关键字(12个)
存储类型关键字(4个)
其他关键字
**非关键字其他*
由于中文是根据编码不同的二进制安全,所以等同非关键字即可处理。(应该全了,不全可以再提醒我补齐) 5.编写.l文件分析代码(这边手写l文件调试了一下午)/** analyse_c.l @author steve yu @date 2019/9/30 */ %{ #include "stdio.h" #include "stdlib.h" %} CHAR char DOUBLE double ENUM enum FLOAT float INT int LONG long SHORT short SIGNED signed STRUCT struct UNION union UNSIGNED unsigned VOID void FOR for DO do WHILE while BREAK break CONTINUE continue IF if ELSE else GOTO goto SWITCH switch CASE case DEFAULT default RETURN return AUTO auto EXTERN extern REGISTER register STATIC static CONST const SIZEOF sizeof TYPEDEF typedef VOLATILE volatile INT_DEX [1-9][0-9]*|[0] INT_HEX [0][Xx][1-9a-fA-F][0-9a-fA-F]*|[0] INT_OCT [0][1-7][0-7]*|[0] SEMI ; COMMA,QUO ' DOUQUO " EQ = PLUS + MIN - MULTI * DIV / AND && OR || SLAND & SLOR | LP ( RP ) LB [ RB ] LC { RC } SPACE [ nrt] ID [a-zA-Z][a-zA-Z0-9]* DOU {INT_DEX}[.][0-9]+ %% {CHAR} { printf("%s 1n",yytext); } {DOUBLE} { printf("%s 2n",yytext); } {ENUM} { printf("%s 3n",yytext); } {FLOAT} { printf("%s 4n",yytext); } {INT} { printf("%s 5n",yytext); } {LONG} { printf("%s 6n",yytext); } {SHORT} { printf("%s 7n",yytext); } {SIGNED} { printf("%s 8n",yytext); } {STRUCT} { printf("%s 9n",yytext); } {UNION} { printf("%s 10n",yytext); } {UNSIGNED} { printf("%s 11n",yytext); } {VOID} { printf("%s 12n",yytext); } {FOR} { printf("%s 13n",yytext); } {DO} { printf("%s 14n",yytext); } {WHILE} { printf("%s 15n",yytext); } {BREAK} { printf("%s 16n",yytext); } {CONTINUE} { printf("%s 17n",yytext); } {IF} { printf("%s 18n",yytext); } {ELSE} { printf("%s 19n",yytext); } {GOTO} { printf("%s 20n",yytext); } {SWITCH} { printf("%s 21n",yytext); } {CASE} { printf("%s 22n",yytext); } {DEFAULT} { printf("%s 23n",yytext); } {RETURN} { printf("%s 24n",yytext); } {AUTO} { printf("%s 25n",yytext); } {EXTERN} { printf("%s 26n",yytext); } {REGISTER} { printf("%s 27n",yytext); } {STATIC} { printf("%s 28n",yytext); } {CONST} { printf("%s 29n",yytext); } {SIZEOF} { printf("%s 30n",yytext); } {TYPEDEF} { printf("%s 31n",yytext); } {VOLATILE} { printf("%s 32n",yytext); } {INT_DEX} { printf("%s 33n",yytext); } {INT_HEX} { printf("%s 34n",yytext); } {INT_OCT} { printf("%s 35n",yytext); } {SEMI} { printf("%s 36n",yytext); } {COMMA} { printf("%s 37n",yytext); } {QUO} { printf("%s 38n",yytext); } {DOUQUO} { printf("%s 39n",yytext); } {EQ} { printf("%s 40n",yytext); } {PLUS} { printf("%s 41n",yytext); } {MIN} { printf("%s 42n",yytext); } {MULTI} { printf("%s 43n",yytext); } {DIV} { printf("%s 44n",yytext); } {AND} { printf("%s 45n",yytext); } {OR} { printf("%s 46n",yytext); } {SLAND} { printf("%s 47n",yytext); } {SLOR} { printf("%s 48n",yytext); } {LP} { printf("%s 49n",yytext); } {RP} { printf("%s 50n",yytext); } {LB} { printf("%s 51n",yytext); } {RB} { printf("%s 52n",yytext); } {LC} { printf("%s 53n",yytext); } {RC} { printf("%s 54n",yytext); } {SPACE} { } {ID} { printf("%s 56n",yytext); } {DOU} { printf("%s 57n",yytext); } %% /*necessary func*/ int yywrap(){ return 1; } /*main func*/ int main(int argc,char** argv){ if(argc>1){ if(!(yyin=fopen(argv[1],"r"))){ perror(argv[1]); return 1; } } while(yylex()); return 0; } 6.编译并测试flex analyse.l gcc lex.yy.c ./a.out test 在这个test文本文件代码如下 int main(){ int a=0; if(a==6) a=a+1; else return -1; return 0; } 分析结果如下 int 5 main 56 ( 49 ) 50 { 53 int 5 a 56 = 40 0 33 ; 36 if 18 ( 49 a 56 = 40 = 40 6 33 ) 50 a 56 = 40 a 56 + 41 1 33 ; 36 else 19 return 24 - 42 1 33 ; 36 return 24 0 33 ; 36 } 54 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |