1. 程式人生 > >【原創】讓VS2015與Win Flex Bison共舞

【原創】讓VS2015與Win Flex Bison共舞

時光荏苒,歲月如梭!很久很久沒有更新部落格了,很多要寫的東西都只是開了個頭,或者只寫了一小部分因不完整而無法釋出,實在遺憾。無奈時間實在是太緊張,大量時間都用在了看書、學習和工作上,不能快意自在的筆耕以飼讀者,深感愧疚。

前一久加入了一個立志開發編譯器的網友團隊,哪不知還沒開始就又結束了(幹嘛說個“又”字,原因你懂的),但是這次經歷居然又勾起了我10多年對編譯原理的那份迷戀,從書架上翻出那些10多年前夠買的相關專輯,又是一頓狂啃,突然感覺年近不惑的我,現在居然能一口氣讀通讀懂,那種酣暢淋漓的感覺,如飲佳釀,想來是因為我前一久花了大量時間複習了數學,並坐了人類進步電梯的“古今數學思想”之緣故吧。

10多年前為了實現編譯器,蒐集了很多Lex和Yacc的工具,其中感覺讓我眼前一亮的是叫做Parser Generator的一款美國大黃蜂公司出品的Lex和Yacc的IDE工具,無奈該公司自2003年之後就再沒有更新過了,這個工具只能與當時的VC6和VS2003很好的整合,且只能支援Win32和老舊的Win16。此次複習編譯原理,只能先又祭出這款老刀,開砍正則表示式和EBNF。在反覆與VS2015整合編譯的過程中,感覺山窮水盡,實在是無法將二者簡單融合,老舊的工具與年輕的後生VS2015格格不入,各種警告,編譯錯誤,在折磨了我半天之後我只好先放棄了。

繼而我在近乎絕望的時候,突然想起要不直接下載Flex和Bison的最新版原始碼然後再搜尋下它們在Win平臺和VS工具下的編譯方法,自己搞定吧,實在不行不是還有個CygWin可以用來救場,於是說幹就幹。開啟百度一頓狂搜,有個關鍵詞“Win Bison”讓我眼前一亮,然後就直奔主題全英文開搜,於是就讓我找到了Win Flex Bison Tools,幸運的是居然還讓我搜到了一篇文章介紹如何將這個工具整合到VS2010中的文章,此時我的心情就是柳暗花明了。

偉大的毛主席教導我們:“你要知道梨子的滋味,你就得變革梨子,親口吃一吃。”,於是二話不說就開練,當然是用2015,礙於我蹩腳的英文,在耗費了我大約2個左右腦細胞和近2個小時的時間後,居然就成功了,於是我乾的第一件事情就是把這個過程寫成這篇博文。

當然要完成這個過程,第一步就是要下載到WinFlexBison工具,在這裡:

下載後解壓就OK了;

第二步就是啟動VS2015並新建一個空的C++專案,如下圖:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

該專案命名為SampleCALC。建好後的解決方案資源管理器如下圖所示:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

接下來就是新建一個SampleCALC.y的語法檔案,將下面這段Yacc程式碼複製貼上進去:

----------------------------------------------------割------------------------------------------------------------------

%{
#include <stdio.h>
#include <ctype.h>
#include <math.h>

#define YYSTYPE  double
void yyerror(char *text);
int yylex(void);
%}
/////////////////////////////////////////////////////////////////////////////
// declarations section
// place any declarations here
%token NUMBER
%left '+' '-'
%left '*' '/'
%right '^'
%%
/////////////////////////////////////////////////////////////////////////////
// rules section
// place your YACC rules here (there must be at least one)
command : exp {printf("%lf\n",$1);}
   ;
exp       : NUMBER          {$$ = $1;}
       | exp '+' exp     {$$ = $1 + $3;}
       | exp '-' exp     {$$ = $1 - $3;}
       | exp '*' exp     {$$ = $1 * $3;}
       | exp '/' exp     {
                            if(0 != $3)
                            {
                               $$ = $1 / $3;
                            }
                            else
                            {
                               $$=0;
                            }
                        }
       | exp '^' exp     {$$ = pow($1,$3);}
       | '(' exp ')'     {$$ = $2;}
       ;
%%
/////////////////////////////////////////////////////////////////////////////
// programs section
int yylex(void)
{
   // place your token retrieving code here
   int c = 0;
   while( (c = getchar()) == ' ');
   if( isdigit(c) )
   {
       ungetc(c,stdin);
       scanf_s("%lf",&yylval);
       return (NUMBER);
   }
   if( '\n' == c )
   {
       return 0;
   }
   return c;
}
int main(void)
{
   yyparse();
   system("PAUSE");
   return 0;
}
void yyerror(char *text)
{
   fprintf(stderr,"%s\n",text);
}

----------------------------------------------------割------------------------------------------------------------------

Ok,至此基本的準備工作就結束了,接下來的第四步就需要WinFlexBison登場了。在VS2015解決方案資源管理器的專案節點上右鍵單擊然後按下圖所示順序選中生成自定義選單:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

之後會彈出如下的對話方塊:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

按圖示點選其上的查詢現有的按鈕,然後找到你下載的WinFlexBison工具的解壓目錄中的custom_build_rules目錄下的win_flex_bison_custom_build.targets檔案點選開啟後VS2015會提示:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

點選是之後上面這個對話方塊變成下面的樣子:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

注意多出來的Win_flex_bison_custom_build選項,點選之前的方框使他成為選中狀態,然後點選確定按鈕關閉。

第五步需要做的就是將WinBison的exe檔案所在的目錄新增到專案的可執行檔案路徑中,如下圖操作:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

開啟屬性對話方塊後在選項樹中找到VC++目錄選項的可執行檔案目錄選項,如下圖:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

點選右側箭頭選擇編輯後在彈出的對話方塊中新增解壓的WinFlexBison目錄如下:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

然後點選確定按鈕關閉兩個對話方塊,準備開始下一步;

第六步直接生成專案,這時輸出視窗中會顯示下面的資訊:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

當然這只是說生成剛才新建的SampleCALC.y檔案成功了,這會生成兩個檔案:SampleCALC.tab.h和SampleCALC.tab.cpp,然後將這兩個檔案新增現有項到當前專案中如下:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

至此算大功告成了,當然最後一步就是生成並執行程式了,本文給的例子是個簡單的命令列計算器,實現了+、-、*、/、^(乘方)運算。生成成功後,點選除錯執行按鈕就可以輸入你想要的的表示式計算下看看了。下面給幾個我除錯執行的例子大家過過眼癮:

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

讓VS2015與Win Flex Bison共舞 - Gamebaby Rock Sun - Gamebaby Rock Sun的部落格

至此所有的工作都做完了,以後要開發編譯器使用WinFlexBison工具都照此執行即可,當然我沒有介紹Lex檔案怎麼弄,其實和Yacc的檔案一個道理,我想剩下的東西聰明的你應該不需要我教了。最後提醒一下,在新增WinFlexBison工具的EXE檔案目錄那一步,主要我們選擇了預設配置,通常你需要選擇所有配置新增一下,這樣無論是Win32、Win64還是Debug或Release都可以使用WinFlexBison工具進行編譯了。

    其他的深入的關於工具的使用內容,我將繼續結合複習編譯原理的過程進行摸索,如果有什麼重大的發現,我將考慮繼續寫成文章釋出出來,供大家參考。

最後平心而論,現代化的Bison工具比當年的那個Parser Generator先進了不止一點半點,而且也方便了很多,不需要額外的include、lib引用,直接編譯就可以生成想要的編譯器工具,先進、方便集於一身。常言道:工欲善其事必先利其器,有了WinFlexBison工具在手,各位觀眾實現自己的編譯器再不是一件極度複雜的事情了,你可以直接無視那些還在寫巢狀下降遞迴呼叫實現編譯器的入門者了,真正是居家旅行裝13必備之神器!

最後提醒各位一下,因為*.y檔案的顯示和編輯在VS2015中都是當作普通的文字檔案處理的,所以是一個黑白的世界,如果你想要帶語法高亮的顯示,那麼還是先得下載Parser Generator工具並安裝,然後在這個工具中編輯*.l和*.y檔案,然後在VS2015中按照本文提示的方法編譯執行。最蛋疼的莫過於這個Parser Generator工具居然不支援滑鼠滾輪,只能祈禱你的Lex和Yacc檔案不要太大,不然想要瀏覽的時候你就知道這個工具該是有多老舊。當然如果你找到了能夠整合到VS2015中的Lex和Yacc語法高亮外掛的話,請你不要忘記把下載連結回覆給我,萬分感謝!