主题:[原创]c语言词法分析器
雨中石桥
[专家分:0] 发布于 2011-02-13 22:45:00
我所编写的是吉林大学一年级上学期的课程设计——词法分析器,这是我和同学努力的结果,希望对大家有用,源码运行环境win7,用codeblocks编译
最后更新于:2011-02-16 11:47:00
回复列表 (共8个回复)
沙发
3751002 [专家分:160] 发布于 2011-02-14 23:11:00
不错的啊 mark下
板凳
eastcowboy [专家分:25370] 发布于 2011-02-15 20:31:00
如果文件里面出现了“/*”却没有出现“*/”,似乎会进入死循环。(我没有实际运行,只是随便说说)
词法分析器一般要求正则文法。而对于正则文法,理论上可以不必倒退,一次性解析完毕。也就是说,像fseek这样的函数其实是没有必要使用的,制作一个有穷自动机,挨个的fgetc即可。当然更好的做法是一次读取大量数据放到一个数组中,然后一点一点的解析,这样可以减少函数调用次数,速度更快。
3 楼
雨中石桥 [专家分:0] 发布于 2011-02-16 11:39:00
谢谢评论,不过我们说编写的这个程序的思想是逐个逐个的“词”来读入,既需要判断不同的“词”,这样一来就会多读入一个用来判断,所以在某些地方有必要加入fseek函数来调整文件指针,对于你所讲到的/*我想您是看错了,不过我又更新了附件,您可以在看看,请您多指正批评
4 楼
windy0will [专家分:2300] 发布于 2011-02-16 15:35:00
楼主的研究精神 值得我们高度学习。
[quote]
词法分析器一般要求正则文法。而对于正则文法,理论上可以不必倒退,一次性解析完毕。也就是说,像fseek这样的函数其实是没有必要使用的,制作一个有穷自动机,挨个的fgetc即可。当然更好的做法是一次读取大量数据放到一个数组中,然后一点一点的解析,这样可以减少函数调用次数,速度更快。[/quote]
表示赞同。可以定义这样的全局变量char buffer[2][BUF_SIZE]或char buffer[BUF_SIZE]这样的全局变量。然后定义PUTS() ,GETC(),UNGETC(c)这几个宏来分别实现把数据缓存到buffer,从buffer获取1个字符,把字符c压回buffer(有时候需要超前搜索).
楼主的代码还有很多方面莫有实现,如 L'a' , L"abc", 0x123efw(16进制数), *(乘号和指针取对象), 01248(8进制), += -=等(这些复合赋值符), != == &&(等等,很多符号) 。。。
感觉有很多方面还要改善,就简单的说说整数和浮点数.0开头的8进制只允许0-7这几个字符, 0x开头的16进制只允许0-9a-fA-F这些字符。整数后面可以跟U,L这样的后缀,如124L,123U,123LLU等。像这样的浮点数都是合法的:1.0,1.,1.0F,.4f,1.E-4.
在词法分析器发现上面的错误时,应该停止工作,给出错误信息。
5 楼
windy0will [专家分:2300] 发布于 2011-02-16 16:32:00
楼主,再给您一些建议:
现在,一般的词法分析器都是用 有限自动机(FA) 来自动分析的。
比如说分析 整数(不考虑整数后面的后缀UL等)。
最开始什么都没输入的时候 我们成为 状态0(STAT_START)
如果输入字符0, 进入 状态1
如果输入字符1-9,进入 状态2
在状态1的时候, 如果输入1-7, 进入 状态3
如果输入x|X, 进入 状态4
在状态2的时候, 如果输入 0-9, 进入 状态2(循环接受字符0-9)
如果输入 空白字符, 进入 状态5(终态) <<<-
在状态3的时候, 如果输入 0-7, 进入 状态3(循环接受字符0-7)
如果输入 空白字符, 进入 状态6(终态) <<<-
在状态4的时候, 如果输入 0-9a-fA-F, 进入状态4(循环)
如果输入 空白字符, 进入 状态7(终态) <<<-
如果不是上面的输入情况,应该停止工作,给出错误信息。
不同的终态表示不同的情况,如 运算符, 括号, 标识, 8进制数, 10进制数等。
这样,我们首先把所有字符分类,映射成像下面的几类;
digit_8:[0-7] digit_10:[0-9] digit_16:[a-fA-F] eE:[eE] xX:[xX] zero:[0]
fF:[Ff] lL:[Ll] letter:[_a-zA-Z] 等等。一般像+-!%*()这样的符号都单独分类。
然后把 语言里面的各种词汇用正则式表达出来,保存到某个文件如in.txt
integer_base_8 0{digit_8}*
integer_base_16 0[xX]{digit_16}+
identifier {letter}{letter | digit_10}*
。。。。
然后用脚本语言或者c语言写一个程序,把in.txt里面的类容转换成 非确定性有限自动机(NFA), 然后把NFA转换成DFA,在把DFA优化。运行程序然后输出 某个语言的词汇的 状态表。这就说所谓的 词法分析器自动生成器 的原理。
有了上面的 状态表,我们可以把它 复制粘贴 到我们真正的 C语言源代码中。后面的工作非常简单了。这样做是有好处的。如果哪天,您还想写个Python的词法分析器,只要把in.txt里面的内容改变一下,就很容易得到Python 的词法分析状态表。
还有,保留字的识别问题,可以把它们全部定义为某个状态,那么最终得到的状态表非常大,那么至少有200个状态,如果 我们把字符分为20类,那么这个表将有200*20,很大吧??也可以把保留字和标识同等对待,然后再识别。上次在哪里看到过一句话,好像有人证明有可能可以设计一个 完美的哈希函数,把所有关键字映射到某个表中。如果您能设计出一个好的哈希函数,分析速度应该会提速不少。
当然,状态表也可以有人工来填写,不过那可是一个巨大的工程哦。。
6 楼
雨中石桥 [专家分:0] 发布于 2011-02-16 17:46:00
实话说我只是一个刚刚接触编程的大一的菜鸟,不过在+=,-=等地方我们做了处理啊,我有很多东东都不会,非常感谢您给的建议,可我还是不明白您的评论,您能给出具体代码么,非常感谢
7 楼
雨中石桥 [专家分:0] 发布于 2011-02-16 17:50:00
我们的这个词法分析器是在比较短的时间完成的,并没有做报错的功能,只是在思想上和其他编程爱好者的词法分析器不同
[em2]
8 楼
Jig [专家分:1180] 发布于 2011-02-23 22:05:00
http://bbs.pfan.cn/post-361794.html
一个比较完整的C编译器
我来回复