本文版權(quán)歸熊春雷所有 ,我的郵箱:<pandaxcl@163.com>
,歡迎大家和我討論計(jì)算機(jī)方面 的問(wèn)題,在我的博客上 面還寫了很多其他的文檔,有空來(lái)看看哦。如果轉(zhuǎn)載,請(qǐng)保留此版權(quán)信息,并注 明出處。謝謝:)
摘要
在本章中,將會(huì)首先給出一個(gè)最基本的lex和yacc聯(lián)合使用的框架,這個(gè)基本框架 最主要的特點(diǎn)就是能夠正確的被編譯。在我學(xué)習(xí)lex和yacc的過(guò)程中經(jīng)歷了無(wú)數(shù)次 的痛苦折磨,我發(fā)現(xiàn)一個(gè)一開(kāi)始足夠簡(jiǎn)單而且能夠被正確編譯的例子往往能夠使 學(xué)習(xí)者增加學(xué)習(xí)的興趣和信心。因此我的所有的文章都盡可能的采用這種方式進(jìn) 行描述。我寫這些文檔的最大的愿望就是希望能夠減少新手學(xué)習(xí)的痛苦。希望自 己能夠做到這一點(diǎn)!
%{
int yywrap(void);
%}
%%
%%
int yywrap(void)
{
return 1;
}
lex文件和yacc文件都是被%%分成了上中下三個(gè)部分,在這個(gè)程序中的yywrap函數(shù) 需要說(shuō)明一下:
lex源文件中的yywrap函數(shù)是必須的!具體的原因就是因?yàn)榻o了這個(gè)函數(shù)實(shí) 現(xiàn)之后就可以不需要依賴flex庫(kù)了。具體yywrap的作用會(huì)在后面的章節(jié)應(yīng) 用的時(shí)候進(jìn)行解釋。通常的做法就是直接返回1,表示輸入已經(jīng)結(jié)束了。
%{
void yyerror(const char *s);
%}
%%
program:
;
%%
void yyerror(const char *s)
{
}
int main()
{
yyparse();
return 0;
}
如前所述,yacc文件被%%分成了上中下三個(gè)部分,在這個(gè)程序中有幾個(gè)需要說(shuō)明 的地方:
這是語(yǔ)法規(guī)則里面的第一個(gè)非終結(jié)符,注意上面的格式哦:“program”后 面緊跟著一個(gè)冒號(hào)“:”,然后換行之后有一個(gè)分號(hào)“;”,這表明這個(gè) program是由空串組成的。至于什么是非終結(jié)符以及什么是終結(jié)符,還有什 么是語(yǔ)法規(guī)則都會(huì)在后面的章節(jié)中進(jìn)行詳細(xì)介 紹。
從字面上就可以看出是一個(gè)處理錯(cuò)誤的函數(shù),在這里為空的原因是為了保 證代碼盡可能的簡(jiǎn)潔! 實(shí)際上這個(gè)函數(shù)里面的代碼通常只有一句輸出語(yǔ)句 ,當(dāng)然如果你喜歡還可以加入糾錯(cuò)代碼,使你的解析器具備糾錯(cuò)能力:)
其實(shí)這個(gè)函數(shù)是yacc生成的,所以你在代碼里面可以直接使用。這個(gè)時(shí)候 你可能會(huì)問(wèn):“yacc生成了yyparse函數(shù),那么lex是不是也生成了什么函 數(shù)呢?”,是的,lex生成的函數(shù)為yylex函數(shù)。實(shí)際上yyparse還間接調(diào)用 了yylex函數(shù),可以在生成的C源文件中去核實(shí)。
每一個(gè)C/C++程序都必須的裝備啊,少了怎么能行呢:)所以這個(gè)main函數(shù)你 可以放到任何的地方,當(dāng)然要保證能夠調(diào)用yyparse就可以了。但是通常的 做法就是將main函數(shù)放到y(tǒng)acc文件中。
從上面的yacc文件中還可以看出被%%分割成為的三個(gè)部分,第一部分中要寫入 C/C++代碼必須用%{和%}括起來(lái);但是第三個(gè)部分就可以直接寫入C/C++代碼了 ,不需要任何的修飾;中間的那一部分就是yacc語(yǔ)法規(guī)則了。為了能夠讓這個(gè) 最最簡(jiǎn)單的yacc源程序能夠通過(guò)bison的編譯必須要提供一個(gè)語(yǔ)法規(guī)則,這 里給出了一個(gè)最簡(jiǎn)單的規(guī)則:一個(gè)program就是由空字符串構(gòu)成的。實(shí)際上等于 什么也沒(méi)有做。呵呵,對(duì)啊,本章的目的就是為了能夠編譯通過(guò)lex和yacc源程 序,并且也能夠被C/C++編譯器編譯通過(guò)啊?,F(xiàn)在是不是已經(jīng)真的編譯通過(guò)了呢 ,可以按照下面的編譯步驟一步一步的來(lái)編譯核實(shí)。
對(duì)yacc的描述同樣也適用于lex。
lex就是詞法掃描器,yacc就是語(yǔ)法分析器,這是通用的說(shuō)法;具體的實(shí)現(xiàn)有所 不同GNU的lex就是flex,GNU的yacc就是bison。為了統(tǒng)一,所以在后面的文章 中就只會(huì)用lex來(lái)表達(dá)詞法掃描器,用yacc來(lái)表達(dá)語(yǔ)法分析器啦!
下面是編譯全過(guò)程記錄,采用了我在第一章中所制作的lex和yacc轉(zhuǎn)換環(huán)境:
D:/work/lex_yacc/chapter03>dir
驅(qū)動(dòng)器 D 中的卷是 工作區(qū)
卷的序列號(hào)是 54D0-5FC0
D:/work/lex_yacc/chapter03 的目錄
2006-09-25 20:27 <DIR> .
2006-09-25 20:27 <DIR> ..
2006-09-25 20:07 71 frame.l
2006-09-25 20:20 144 frame.y
2 個(gè)文件 215 字節(jié)
2 個(gè)目錄 7,785,578,496 可用字節(jié)
D:/work/lex_yacc/chapter03>flex frame.l
D:/work/lex_yacc/chapter03>dir
驅(qū)動(dòng)器 D 中的卷是 工作區(qū)
卷的序列號(hào)是 54D0-5FC0
D:/work/lex_yacc/chapter03 的目錄
2006-09-25 20:28 <DIR> .
2006-09-25 20:28 <DIR> ..
2006-09-25 20:07 71 frame.l
2006-09-25 20:20 144 frame.y
2006-09-25 20:28 36,997 lex.yy.c
3 個(gè)文件 37,212 字節(jié)
2 個(gè)目錄 7,785,537,536 可用字節(jié)
D:/work/lex_yacc/chapter03>bison -d frame.y
D:/work/lex_yacc/chapter03>dir
驅(qū)動(dòng)器 D 中的卷是 工作區(qū)
卷的序列號(hào)是 54D0-5FC0
D:/work/lex_yacc/chapter03 的目錄
2006-09-25 20:28 <DIR> .
2006-09-25 20:28 <DIR> ..
2006-09-25 20:07 71 frame.l
2006-09-25 20:28 19,416 frame.tab.c
2006-09-25 20:28 74 frame.tab.h
2006-09-25 20:20 144 frame.y
2006-09-25 20:28 36,997 lex.yy.c
5 個(gè)文件 56,702 字節(jié)
2 個(gè)目錄 7,785,517,056 可用字節(jié)
D:/work/lex_yacc/chapter03>
實(shí)際上經(jīng)過(guò)flex和bison的轉(zhuǎn)換之后的C/C++源程序是可以直接在VC里面使用的!
上面的frame.tab.c是由bison編譯frame.y產(chǎn)生的,而lex.yy.c則是由flex編譯 frame.l產(chǎn)生的。
好了,一個(gè)最簡(jiǎn)單的lex和yacc程序已經(jīng)完備了,因此這一章的目的也就已經(jīng)達(dá)到了。 在下一章里面將會(huì)對(duì)這里的框架例子進(jìn)行擴(kuò)充以適應(yīng)自己特殊的需要,逐步逐步的實(shí) 現(xiàn)一個(gè)分析C/C++源代碼的工具程序,但是每一章的結(jié)尾都會(huì)盡可能的給出一個(gè)可以編 譯通過(guò)的lex和yacc源程序。本來(lái)也想給出一個(gè)計(jì)算器的源程序作為例子的,但是這樣 的資料已經(jīng)很多了。這些資料往往不能夠讓自己說(shuō)清楚問(wèn)題,在自己的開(kāi)發(fā)中還是會(huì) 遇到千奇百怪的問(wèn)題,因此為了讓自己能夠有機(jī)會(huì)解決一個(gè)新手在開(kāi)發(fā)新程序中可能 出現(xiàn)的問(wèn)題,我也就找了一個(gè)我沒(méi)有開(kāi)發(fā)過(guò)的程序來(lái)讓自己一步一步的解決這些問(wèn)題 。我想這種方式也許是比較好的學(xué)習(xí)方式吧:)
本章完!
聯(lián)系客服