写在前面
因为自己在学习使用flex&bison编写编译器时,困难很大,网上的资料很老很陈旧,很多示例代码都无法运行。幸而自己最终找到一份07年的博客,所以想对其整理一下。一来加深自己的理解,为学弟学妹提供一份参考资料,二来也能防止原博客丢失。
flex是lex的加强版,同样bison也是yacc的加强版,lex和yacc的语法适用于flex和bison,之后的博客内容将不区分flex
和lex
,bison
和yacc。
本文所有的代码都在kali2019
运行测试过,没有linux基础的读者可以安装Ubuntu
系列linux,推荐ubuntu16和ubuntu18。
示例
我们在以前的基础上,深入一步,设计一个简单的计算器,包含+,-,*,/四项操作,且支持()运算符,其中对值可以进行变量保存,并打印出内部的分析信息。
lex文件内容(lexya_b.l)
1 | %{ |
Yacc文件全内容(lexya_b.y)
1 | %{ |
待解释编译文本(input)全内容
ps:该input一定要在linux中编写或使用我写好的。Windows换行符和Linux不一致会导致无法完成词法分析。
1 | a=4+2*(3-2-1)+6 |
命令行依次输入下列命令
1 | bison -d lexya_b.y |
运行截图
文中成功了使用了变量,并且操作符运算优先级也没有问题。其实细看过flex&bison完成C-语言编译器前端(二)一文后,理解上面的例子就很轻松了。这里只是做了一些扩充变化:
1.增加了全局数组sMem来存放变量,不过变量名有限制,只支持单字符。
2.增加了全局数组sBuff存放分析过的语句
3.增加debuginfo打印堆栈信息
4.增加printinfo打印目前的分析语句
要进行内部分析,就需要剖析生成的c文件,对程序(parser)进行跟踪调试。(注:Lex编译时加上d参数,会在程序解释时输出详细的调试信息。如:lex -d lexya_b.l
)
通过本示例再加上实际对lexya_b.tab.c的分析理解,会对lex,yacc理论有更进一步的理解。
增加支持的变量字符数
上面的例子只支持单字符的变量,想支持多字符,需要定义一全局变量如:
1 | struct varIndex { |
同时打印信息加入对变量的显示,下面列出全部文件内容,比较简单,不再附加说明。
userdef.h
1 | typedef struct |
example2.l
1 | %{ |
example2.y
1 | %{ |
最后
这个系列打算就记载到这里了,剩余的内容读者可以访问原博客。