Intoduction of YACC 電子四乙 B9942305 李昀融
YACC YACC 代表 Yet Another Compiler Compiler。 YACC 的 GNU 版叫做 Bison。 它是一種工具,將任何一種編譯程式語言的所有 語法翻譯成針對此種語言的 YACC 語法解析器。 它用巴科斯範式(BNF, Backus Naur Form)來書寫。 按照慣例,YACC 檔有 .y 尾碼。
YACC 圖中所表示的是使用lex及YACC的一般工作流程。 首先看到YACC會讀入一個.y檔案,這裡.y檔案的 內容就是我們使用類似BNF語法定義的語法規則, YACC會分析這些語法規則後,幫我們產生可以用 來解析這些規則的程式碼,一般名稱預設為y.tab.c 產生的程式碼中最重要的的函式叫作yyparse。 lex也會讀入一個.l的檔案,這個檔案裡面定義的是 如何從文字流裡解出token的規則,使用的方法是 常規表示式(regular expression) 。
YACC lex也會讀入一個.l的檔案,這個檔案裡面定義的是如何 從文字流裡解出token的規則,使用的方法是常規表示 式(regular expression) 。 在圖的左側中間我們還可以看到有一個叫作y.tab.h的檔 案從YACC產生出來並餵給lex作輸入,這個檔案是 YACC根據在讀入的.y檔裡面所定義的token代號所產生 出來的一個header,這樣YACC及lex產生出來的程式碼 裡面就可以使用共通定義的代碼而不必各寫個的。 lex分析過.l檔案後也會產生一個一般預設叫作lex.yy.c的 原始碼檔案,裡頭最重要的一個函式叫作yylex。
YACC 最後,我們把YACC產生出來的y.tab.c還有lex產生 出來的lex.yy.c,以及其它我們自己撰寫的原始碼 檔案一起拿來編譯再作連結,最後產生出來的就 是一個可以用來解析我們定義的語法的解析器工 具。以上是整個lex及YACC的使用流程概觀
YACC語法 YACC 語法檔包括這一語法規範。 這包含了序列匹配時你想要做的事。以英語為例。 這一套標記可能是:名詞, 動詞, 形容詞等等。 為了使用這些標記造一個語法正確的句子, 你的結構必須符合一定的規則。 一個簡單的句子可能是名詞+動詞或名詞+動詞+名 詞。
建立YACC編譯器 2.1編寫一個 .y 的語法檔 (同時說明 C 在這裡要進行的動作)。 2.說明語法: 2.1編寫一個 .y 的語法檔 (同時說明 C 在這裡要進行的動作)。 2.2編寫一個詞法分析器來處理輸入並將標記傳 遞給解析器。 這可以使用 Lex 來完成。 2.3編寫一個函數,通過調用yyparse()來開始解 析。 2.4編寫錯誤處理常式(如 yyerror())。 3.編譯 Yacc 生成的代碼以及其他相關的原始檔案。 4.將目標檔鏈結到適當的可執行解析器庫。
C與 YACC的聲明 C 聲明可能會定義動作中使用的類型和變數,以 及巨集。還可以包含頭檔。 每個 YACC聲明段聲明了終端符號和非終端符號 (標記)的名稱,還可能描述操作符優先順序和 針對不同符號的資料類型。lexer(Lex)一般返回這 些標記。所有這些標記都必須在YACC聲明中進行 說明。 在檔解析的例子中我們感興趣的是這些標記: name, equal sign, 和age。Name 是一個完全由字元 組成的值。Age 是數字。
C與 YACC的聲明 於是聲明段就會像這樣: % #typedef char* string; /* to specify token types as char* */ #define YYSTYPE string /* a Yacc variable which has the value of returned token */ %} %token NAME EQ AGE %%
實作 1.安裝 MinGW-5.1.6.exe 在 C:\MinGW 網址:http://www.mingw.org/ 2.安裝 flex-2.5.4a-1.exe 在 C:\GnuWin32 網址:http://gnuwin32.sourceforge.net/packages/flex.htm 3.安裝 bison-2.4.1-setup.exe 在 C:\GnuWin32 網址:http://gnuwin32.sourceforge.net/packages/bison.htm 4.複製C:\GnuWin32\lib裡的 (a) charset.alias (b) libfl.a (c) liby.a 到C:\MinGW\lib 5.設環境變數 Path C:\MinGW\bin; C:\GnuWin32\bin;
實作 開一個 “.txt”檔 將下列文字複製貼上後 改名為 “lex.as.l” %{ #include "y.tab.h" %} %% [0-9]+"."[0-9]+ { sscanf(yytext,"%lf",&yylval); return NUMBER; } [0-9]+ { sscanf(yytext,"%lf",&yylval); return NUMBER; } [ \t] ; [\n] { return '\n'; } . { return yytext[0]; } int yywrap() { return 1; }
實作 開一個 “.txt”檔 將下列文字複製貼上後 改名為 “yacc.as.y” %{ #define YYSTYPE double extern int yylex(); void yyerror(char*); %} %token NUMBER %% lines : | lines expression '\n' { printf(" = %lf\n", $2); } ;
實作 續上頁 expression : term { $$ = $1; } : factor { $$ = $1; } | term '*' factor { $$ = $1 * $3; } | term '/' factor { $$ = $1 / $3; }
實作 續上頁 factor : NUMBER { $$ = $1; } | group { $$ = $1; } ; group : '(' expression ')' { $$ = $2; } %% void yyerror(char* msg) { printf("error\n") ; exit(1) ; } int main(int argc, char** argv) yyparse(); return 0;
實作 1.執行 -> com ->cd c:\gnuwin32\bin 2. bison yacc.as.y -d 3.上述程式碼執行完 會在 c:\gnuwin32\bin 產生yacc.as.tab.c yacc.as.tab.h 4. flex lex.as.l 5.上述程式碼執行完 會在 c:\gnuwin32\bin 產生lex.yy.c 6.將c:\gnuwin32\bin 中的yacc.as.tab.h改名為 y.tab.h 7.cc lex.yy.c yacc.as.c 8.上述程式碼執行完 會在 c:\gnuwin32\bin 產生a.exe 即為本yacc產生的計算程式
實作 參考網頁 Lex與yacc學習實例 http://www.linuxsir.org/bbs/thread186941.html; ycaa與lex快速入門 http://www.ibm.com/developerworks/cn/linux/sdk/lex /index.html#resources 很讚的遊戲編譯器 http://good-ed.blogspot.tw/2010/04/lexyacc.html
實作圖