• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Lex和Yacc從入門到精通(3) - 一個極其簡單的lex和yacc程序

            原文地址

            摘要

            在本章中,將會首先給出一個最基本的lex和yacc聯(lián)合使用的框架,這個基本框架最主要的特點就是能夠正確的被編譯。在我學習lex和yacc的過程中經歷了無數(shù)次的痛苦折磨,我發(fā)現(xiàn)一個一開始足夠簡單而且能夠被正確編譯的例子往往能夠使 學習者增加學習的興趣和信心。因此我的所有的文章都盡可能的采用這種方式進行描述。我寫這些文檔的最大的愿望就是希望能夠減少新手學習的痛苦。希望自 己能夠做到這一點!

            例 3.1. frame.l

             

            %{
            int yywrap( void );
            %}
            %%
            %%
            int yywrap( void )
            {
            return 1;
            }

            lex文件和yacc文件都是被%%分成了上中下三個部分,在這個程序中的yywrap函數(shù) 需要說明一下:

            yywrap
            lex源文件中的yywrap函數(shù)是必須的!具體的原因就是因為給了這個函數(shù)實 現(xiàn)之后就可以不需要依賴flex庫了。具體yywrap的作用會在后面的章節(jié)應 用的時候進行解釋。通常的做法就是直接返回1,表示輸入已經結束了。

            例 3.2. frame.y

             

            %{
            void yyerror( const char *s);
            %}
            %%
            program:
            ;
            %%
            void yyerror( const char *s)
            {
            }
            int main()
            {
            yyparse();
            return 0;
            }

            如前所述,yacc文件被%%分成了上中下三個部分,在這個程序中有幾個需要說明 的地方:

            program
            這是語法規(guī)則里面的第一個非終結符,注意上面的格式哦:“program”后面緊跟著一個冒號“:”,然后換行之后有一個分號“;”,這表明這個 program是由空串組成的。至于什么是非終結符以及什么是終結符,還有什么是語法規(guī)則都會在后面的章節(jié)中進行詳細介 紹。
            yyerror
            從字面上就可以看出是一個處理錯誤的函數(shù),在這里為空的原因是為了保 證代碼盡可能的簡潔! 實際上這個函數(shù)里面的代碼通常只有一句輸出語句 ,當然如果你喜歡還可以加入糾錯代碼,使你的解析器具備糾錯能力:)
            yyparse
            其實這個函數(shù)是yacc生成的,所以你在代碼里面可以直接使用。這個時候你可能會問:“yacc生成了yyparse函數(shù),那么lex是不是也生成了什么函數(shù)呢?”,是的,lex生成的函數(shù)為yylex函數(shù)。實際上yyparse還間接調用 了yylex函數(shù),可以在生成的C源文件中去核實。
            main
            每一個C/C++程序都必須的裝備啊,少了怎么能行呢:)所以這個main函數(shù)你 可以放到任何的地方,當然要保證能夠調用yyparse就可以了。但是通常的 做法就是將main函數(shù)放到y(tǒng)acc文件中。

            從上面的yacc文件中還可以看出被%%分割成為的三個部分,第一部分中要寫入 C/C++代碼必須用%{和%}括起來;但是第三個部分就可以直接寫入C/C++代碼了,不需要任何的修飾;中間的那一部分就是yacc語法規(guī)則了。為了能夠讓這個最最簡單的yacc源程序能夠通過bison的編譯必須要提供一個語法規(guī)則,這里給出了一個最簡單的規(guī)則:一個program就是由空字符串構成的。實際上等于什么也沒有做。呵呵,對啊,本章的目的就是為了能夠編譯通過lex和yacc源程序,并且也能夠被C/C++編譯器編譯通過啊。現(xiàn)在是不是已經真的編譯通過了呢 ,可以按照下面的編譯步驟一步一步的來編譯核實。

            提示

            對yacc的描述同樣也適用于lex。

            lex就是詞法掃描器,yacc就是語法分析器,這是通用的說法;具體的實現(xiàn)有所 不同GNU的lex就是flex,GNU的yacc就是bison。為了統(tǒng)一,所以在后面的文章 中就只會用lex來表達詞法掃描器,用yacc來表達語法分析器啦!

            下面是編譯全過程記錄,采用了我在第一章中所制作的lex和yacc轉換環(huán)境:

             

            D:\work\lex_yacc\chapter03>dir
            驅動器 D 中的卷是 工作區(qū)
            卷的序列號是 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 個文件 215 字節(jié)
            2 個目錄 7,785,578,496 可用字節(jié)

            D:\work\lex_yacc\chapter03>flex frame.l

            D:\work\lex_yacc\chapter03>dir
            驅動器 D 中的卷是 工作區(qū)
            卷的序列號是 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 個文件 37,212 字節(jié)
            2 個目錄 7,785,537,536 可用字節(jié)

            D:\work\lex_yacc\chapter03>bison -d frame.y

            D:\work\lex_yacc\chapter03>dir
            驅動器 D 中的卷是 工作區(qū)
            卷的序列號是 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 個文件 56,702 字節(jié)
            2 個目錄 7,785,517,056 可用字節(jié)

            D:\work\lex_yacc\chapter03>

            過程 3.1. 總的來說就是如下的幾個步驟:

            1. 將前面的例子frame.lframe.y保存成為相應的文件
            2. flex frame.l
            3. bison frame.y
            4. gcc frame.tab.c lex.yy.c

            提示

            實際上經過flex和bison的轉換之后的C/C++源程序是可以直接在VC里面使用的!

            上面的frame.tab.c是由bison編譯frame.y產生的,而lex.yy.c則是由flex編譯 frame.l產生的。

            好了,一個最簡單的lex和yacc程序已經完備了,因此這一章的目的也就已經達到了。在下一章里面將會對這里的框架例子進行擴充以適應自己特殊的需要,逐步逐步的實現(xiàn)一個分析C/C++源代碼的工具程序,但是每一章的結尾都會盡可能的給出一個可以編譯通過的lex和yacc源程序。本來也想給出一個計算器的源程序作為例子的,但是這樣的資料已經很多了。這些資料往往不能夠讓自己說清楚問題,在自己的開發(fā)中還是會遇到千奇百怪的問題,因此為了讓自己能夠有機會解決一個新手在開發(fā)新程序中可能出現(xiàn)的問題,我也就找了一個我沒有開發(fā)過的程序來讓自己一步一步的解決這些問題 。我想這種方式也許是比較好的學習方式吧:)


            posted on 2008-02-03 17:59 FongLuo 閱讀(356) 評論(0)  編輯 收藏 引用

            <2008年2月>
            272829303112
            3456789
            10111213141516
            17181920212223
            2425262728291
            2345678

            導航

            常用鏈接

            留言簿

            隨筆分類(11)

            隨筆檔案(79)

            文章檔案(1)

            收藏夾(38)

            學習網站

            一般網站

            最新隨筆

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            久久国产一片免费观看| 久久午夜无码鲁丝片秋霞| 国产A三级久久精品| 久久久精品久久久久久| 久久久91人妻无码精品蜜桃HD| 精品国产青草久久久久福利| 色综合久久久久网| 免费精品99久久国产综合精品| 69久久精品无码一区二区| 久久99国产精品99久久| 一本大道加勒比久久综合| 青青青国产精品国产精品久久久久| 国产精品岛国久久久久| 国产日韩欧美久久| 久久亚洲国产成人影院网站| 欧美午夜A∨大片久久| 一本一本久久a久久综合精品蜜桃| 久久WWW免费人成一看片| 国内精品久久久久影院优| 久久97久久97精品免视看| 欧美伊人久久大香线蕉综合69 | 久久久国产视频| 少妇无套内谢久久久久| 久久丫精品国产亚洲av| 久久香蕉一级毛片| 久久一区二区三区99| 综合网日日天干夜夜久久| 四虎国产精品免费久久久| 亚洲综合久久夜AV | 久久久久亚洲av无码专区导航| 狠狠狠色丁香婷婷综合久久俺| 久久精品综合一区二区三区| 久久夜色精品国产噜噜麻豆| 精品国产一区二区三区久久蜜臀| 最新久久免费视频| 色综合合久久天天综合绕视看 | 人妻精品久久无码区| 精品久久久久久国产牛牛app| 亚洲精品无码久久久影院相关影片| 成人精品一区二区久久| 99国产欧美精品久久久蜜芽|