我是靠谱客的博主 悦耳白开水,这篇文章主要介绍flex和bison实例分析,现在分享给大家,希望可以做个参考。

        最近在学习编译原理,利用flex和bison编写一个基于文本识别的简单计算器程序,参考《flex于bison》中内容,对程序进行一些简单的修改,加入Makefile。该计算器程序主要实现识别文本中的整数和运算符,进行加减乘除四则运算,暂不考虑括号对运算顺序的影响。
        flex用于词法分析器的构建,bison用于语法分析器构建,两者可以结合使用,利用bison生成源程序可以直接调用flex生成源程序中yylex()函数,提取标准输入文本中的目标字符,虽然main函数可以放到flex或bison的源码文件的用户自定义部分,但是不便于阅读和理解。因此将main函数单独放到一个cpp文件中,调用bison源码文件中的yyparse()函数对输入内容进行解析和处理。将计算器的运算实现放到bison源码的规则部分。
       创建test.l文件,编写词法分析规则(数字和符号识别)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
%{     #include <stdio.h>     #include "test_yacc.h"      //因为使用了bison在test_yacc.h中自动生成的token枚举     extern int yylval;      //yylval定义在bison库中 %} number [0-9] %% {number}+ {     yylval = atoi(yytext);     printf("number: %d  ", yylval);     return INT; } "+" {     printf("operator: +  ");     return ADD;  } "-" {     printf("operator: -  ");     return SUB; } "*" {     printf("operator: *  ");     return MUL; } "/" {     printf("operator: /  ");     return DIV; } n { return EOL; } [ t] {} . { //该条规则匹配除以上字符外的剩余字符,并且报错     printf("error: input illegal character '%s'.n", yytext); } %% void yyerror(const char *msg)  //该函数的重写可以放在任意位置,bison的yyparse()会调用该函数,需在.y文件中声明此函数 //传参必须为const,不然编译会报warning {     fprintf(stderr, "error: %s.n", msg); }

        创建test.y文件,编写语法分析规则(计算器的运算处理),cal为创建的空规则,专门用于判断是否有换行,如果有换行,完成一次cal的规约,exp属性栈弹出,即exp清零。根据BNF表示方法,将首处理符号INT放在最底层规则,其次优先匹配乘除法,在处理乘除法之后再匹配加减法。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
%{     #include <stdio.h>     extern int yylex();     extern void yyerror(const char *); %} %token INT %token ADD SUB MUL DIV %token EOL %% cal :      | cal exp EOL { printf("n<archerfoo> caculation result: %dn", $2); }     ; exp : factor     | exp ADD factor { $$ = $1 + $3; }      | exp SUB factor { $$ = $1 - $3; }      ; factor : term     | factor MUL term { $$ = $1 * $3; }      | factor DIV term { $$ = $1 / $3; }      ; term : INT     ; %%

        创建testMain.cpp,编写main函数内容:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h> //extern int yylex(); extern int yyparse(); int main(int argc, char ** args)  {     //yylex();      yyparse(); //调用bison的yyparse()函数     return 0; }

        编写编译Makefile脚本

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
ECHO = echo CXX  = g++ TARGET = ./testDemo LIBS   = -lfl CFLAGS = -Wall CFLAGS += -std=c++11 OBJECTS =  testMain.o  OBJECTS += test_yacc.o OBJECTS += test_lex.o $(TARGET) : $(OBJECTS)     $(CXX) -o $(TARGET) $(OBJECTS) $(LIBS) $(CFLAGS)  .cpp.o :     $(CXX) -o $@ -c $< #生成test_yacc.cpp、test_yacc.h #test_yacc.h会生成token的相关枚举 test_yacc.cpp : test.y     bison -d $< -b test_yacc     mv test_yacc.tab.c test_yacc.cpp     mv test_yacc.tab.h test_yacc.h #生成test_lex.cpp test_lex.cpp : test.l     flex -o $@ $< .PHONY : clean clean:     rm $(OBJECTS) $(TARGET) test_yacc.h test_yacc.cpp test_lex.cpp

        编译:

     yylex()返回记号token标志,标志0-255被保留作为字符值,可以自己定义token标志的值,一般由bison产生的token标志默认从258开始。本例中,由bison生成的test_yacc.h文件,其中token枚举定义:

       调试结果:

最后

以上就是悦耳白开水最近收集整理的关于flex和bison实例分析的全部内容,更多相关flex和bison实例分析内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(85)

评论列表共有 0 条评论

立即
投稿
返回
顶部