日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

自制编译器学习3:Flex和Bison简介

發(fā)布時(shí)間:2024/3/26 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自制编译器学习3:Flex和Bison简介 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Flex和Bison安裝

Ubuntu環(huán)境下直接安裝即可:

apt-get install flex bison

第一個(gè)Flex程序

首先給出代碼(fb1-1.l)

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-1.l,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* fb1-1 just like unix wc */ %{ int chars = 0; int words = 0; int lines = 0; %}%%[a-zA-Z]+ { words++; chars += strlen(yytext); } \n { chars++; lines++; } . { chars++; }%%main() {yylex();printf("%8d%8d%8d\n", lines, words, chars); }

flex程序分為3部分,每一部分通過(guò)符號(hào)%%來(lái)分割,第一部分包含聲明和選項(xiàng)設(shè)置,第二部分是一系列的模式和動(dòng)作,第三部分是會(huì)被拷貝到詞法生成器里面的C代碼。

第一部分,%{%}之間的代碼會(huì)被照抄到生成C文件的頭部,可以看到在這個(gè)實(shí)例中只是定義了3個(gè)整型變量。

第二部分,每一個(gè)模式匹配位于一行的開始,接著是匹配時(shí)要執(zhí)行的的C代碼,C代碼為{}之間的一行或者多行代碼。[a-zA-Z]+用來(lái)匹配一個(gè)單詞,大括號(hào)內(nèi)表示可以匹配任意大小寫字母,+表示匹配一個(gè)或多個(gè)前面的字符,即一串字母或者一個(gè)單詞,flex中,yytext總是被指定為本次匹配的輸入文本,.表示匹配任意一個(gè)字符。

第三部分,主程序,調(diào)用flex的詞法分析例程,并輸出結(jié)果。

執(zhí)行flex

flex -o fb1-1.c fb1-1.l

詞法生成器翻譯成c程序,c文件為:fb1-1.c

使用gcc編譯生成可執(zhí)行文件:

gcc fb1-1.c -lfl -o fb1-1

注意編譯時(shí)需要鏈接庫(kù)(-lfl),執(zhí)行該程序,輸入3個(gè)字符串后按ctrl+d退出,輸出結(jié)果如下:

?flex和bison協(xié)同工作

來(lái)看第二段代碼:

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-3.l,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* recognize tokens for the calculator and print them out */%% "+" { printf("PLUS\n"); } "-" { printf("MINUS\n"); } "*" { printf("TIMES\n"); } "/" { printf("DIVIDE\n"); } "|" { printf("ABS\n"); } [0-9]+ { printf("NUMBER %s\n", yytext); } \n { printf("NEWLINE\n"); } [ \t] { } . { printf("Mystery character %s\n", yytext); } %%

這里只給出了模式匹配,flex的lfl庫(kù)提供了極小的主程序來(lái)調(diào)用詞法分析器,這里已經(jīng)足夠,詞法分析器的生成和編譯與之前相同,生成可執(zhí)行詞法分析程序,執(zhí)行后輸入12+34和13/34做詞法分析,執(zhí)行結(jié)果如下:

考慮一個(gè)更完成的計(jì)算器詞分析器:

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-4.l,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* recognize tokens for the calculator and print them out */%{enum yytokentype {NUMBER = 258,ADD = 259,SUB = 260,MUL = 261,DIV = 262,ABS = 263,EOL = 264 /* end of line */};int yylval;%}%% "+" { return ADD; } "-" { return SUB; } "*" { return MUL; } "/" { return DIV; } "|" { return ABS; } [0-9]+ { yylval = atoi(yytext); return NUMBER; } \n { return EOL; } [ \t] { /* ignore white space */ } . { printf("Mystery character %c\n", *yytext); } %% main() {int tok;while(tok = yylex()) {printf("%d", tok);if(tok == NUMBER) printf(" = %d\n", yylval);else printf("\n");} }

輸出結(jié)果如下:

?我們來(lái)分析下代碼,flex做詞分析返回記號(hào)流時(shí),每個(gè)記號(hào)記號(hào)編號(hào)(token number)和記號(hào)值(token's value)組成,其中記號(hào)編號(hào)為一個(gè)小的整數(shù),bison自動(dòng)從258開始編號(hào),并且創(chuàng)建一個(gè)編號(hào)定義的.h文件,這里為了方便理解通過(guò)enum進(jìn)行了手工定義。主程序調(diào)用yylex()返回記號(hào)值,對(duì)于NUMBER轉(zhuǎn)換為int。

語(yǔ)法分析器

下面基于flex和bison來(lái)設(shè)計(jì)一個(gè)基本的語(yǔ)法分析器,bison遵循BNF(BackusNaur Form)語(yǔ)法,

在BNF里,::=(:)是被定義為的意思,|表示其左右兩邊任選一項(xiàng), 左邊的名稱是語(yǔ)法符號(hào)(symbol),有效的BNF是具有遞歸性的,例如處理 1×5+2×3這種簡(jiǎn)單的算術(shù)表達(dá)式:

<exp> ::= <factor>| <exp> + <factor> <factor> ::= NUMBER| <factor> * NUMBER

exp被定義為一個(gè)factor 或者 factor + exp,而facotr被定義為NUMBER或者factor×NUMBER,每個(gè)規(guī)則最左邊是非終結(jié)符,冒號(hào)右邊是非終結(jié)符的推導(dǎo)規(guī)則,如果推導(dǎo)規(guī)則是多個(gè)那么通過(guò)|隔開。

我們給出bison代碼的示例(fb1-5.y):

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-5.y,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* simplest version of calculator */%{ # include <stdio.h> %}/* declare tokens */ %token NUMBER %token ADD SUB MUL DIV ABS %token OP CP %token EOL%%calclist: /* nothing 空規(guī)則 從輸入開頭開始匹配*/ | calclist exp EOL { printf("= %d\n> ", $2); } /*EOL代表一個(gè)表達(dá)式的結(jié)束*/| calclist EOL { printf("> "); } /* blank line or a comment */;exp: factor| exp ADD exp { $$ = $1 + $3; }| exp SUB factor { $$ = $1 - $3; }| exp ABS factor { $$ = $1 | $3; };factor: term| factor MUL term { $$ = $1 * $3; }| factor DIV term { $$ = $1 / $3; };term: NUMBER| ABS term { $$ = $2 >= 0? $2 : - $2; }| OP exp CP { $$ = $2; }; %% main() {printf("> "); yyparse(); }yyerror(char *s) {fprintf(stderr, "error: %s\n", s); }

bison程序同樣包含三部分:聲明部分,規(guī)則匹配部分和C代碼部分。

聲明部分同樣是用%{%}包括且要原樣拷貝到C代碼,隨后%token記號(hào)聲明,便于告訴bison在語(yǔ)法分析程序中記號(hào)的名稱,記號(hào)通常總是大寫,未聲明為記號(hào)的語(yǔ)法符號(hào)必須出現(xiàn)在至少一條規(guī)則的左邊。

規(guī)則部分通過(guò)簡(jiǎn)單的BNF定義規(guī)則,bison使用單一的冒號(hào)而不是::=,同時(shí)由于行間隔并不明顯,用分號(hào)來(lái)表示規(guī)則的結(jié)束,C的動(dòng)作代碼在每條規(guī)則之后用花括號(hào)括起來(lái)。

我們來(lái)詳細(xì)看下匹配規(guī)則,第一個(gè)語(yǔ)法符號(hào)calclist,第一個(gè)匹配是空值,第二個(gè)是表達(dá)式(exp)+結(jié)束符(EOL),第三個(gè)是只有結(jié)束符的情況。

接下來(lái)的語(yǔ)法符號(hào)是term->factor->exp,匹配規(guī)則:

term: NUMBER 或者 絕對(duì)值的 term或者 加括號(hào)的 exp;

factor: term 或者 factor和term的乘法(左遞歸) 或者factor和term(左遞歸)的除法 或者 絕對(duì)值;

exp: factor 或者 exp和exp的加法 或者 exp和factor的乘法(左遞歸) 或者 exp和factor(左遞歸)的除法。

顯然是由小到大組成的(并不是絕對(duì)的,term也會(huì)匹配exp),并且優(yōu)先級(jí)越高的越靠前,由于BNF語(yǔ)法具有遞歸性,這樣的順序可以保證運(yùn)算優(yōu)先級(jí)的正確性。

目標(biāo)符號(hào)(冒號(hào)左邊的語(yǔ)法符號(hào))的值在動(dòng)作代碼中用$$代替,右邊語(yǔ)法符號(hào)的語(yǔ)義值依次為$1 $2 $3 ......。當(dāng)詞法分析器返回記號(hào)時(shí),記號(hào)值總是存儲(chǔ)在yyval中。

聯(lián)合編譯flex和bison程序

flex代碼(fb1-5.l)如下:

/* Companion source code for "flex & bison", published by O'Reilly* Media, ISBN 978-0-596-15597-1* Copyright (c) 2009, Taughannock Networks. All rights reserved.* See the README file for license conditions and contact info.* $Header: /home/johnl/flnb/code/RCS/fb1-5.l,v 2.1 2009/11/08 02:53:18 johnl Exp $*//* recognize tokens for the calculator and print them out */%{ # include "fb1-5.tab.h" %}%% "+" { return ADD; } "-" { return SUB; } "*" { return MUL; } "/" { return DIV; } "|" { return ABS; } "(" { return OP; } ")" { return CP; } [0-9]+ { yylval = atoi(yytext); return NUMBER; }\n { return EOL; } "//".* [ \t] { /* ignore white space */ } . { yyerror("Mystery character %c\n", *yytext); } %%

我們專門寫一個(gè)Makefile文件:

fb1-5: fb1-5.l fb1-5.ybison -d fb1-5.yflex -o fb1-5.c fb1-5.lgcc -o $@ fb1-5.tab.c fb1-5.c -lflclean:rm -f fb1-5 \fb1-5.c fb1-5.tab.c fb1-5.tab.h

執(zhí)行

bison -d fb1-5.y

會(huì)生成文件:fb1-5.tab.h 和 fb1-5.tab.c,在flex文件中調(diào)用該頭文件即可以實(shí)現(xiàn)聯(lián)合編譯,最后生成可執(zhí)行程序fb1-5,測(cè)試結(jié)果如下:

可以看到,由于缺少對(duì)負(fù)數(shù)的支持,所以輸入負(fù)數(shù)會(huì)報(bào)錯(cuò)。先講到這里,本節(jié)介紹了如何設(shè)計(jì)最基本的詞法分析器和語(yǔ)法分析器,后面會(huì)對(duì)flex和bison做更詳細(xì)介紹。

end

總結(jié)

以上是生活随笔為你收集整理的自制编译器学习3:Flex和Bison简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。