按一定語(yǔ)法寫(xiě)好規(guī)則,bison則可以自動(dòng)識(shí)別語(yǔ)法屈溉,網(wǎng)上關(guān)于Yacc的資料很多,但是幾個(gè)關(guān)鍵點(diǎn)講的不夠清晰抬探,這里按自己的理解寫(xiě)下來(lái)子巾,加深記憶。
定義段寫(xiě)法:
定義段可以分為兩部分:
第一部分以符號(hào)%{和%}包裹,里面為以C語(yǔ)法寫(xiě)的一些定義和聲明:例如线梗,文件包含椰于,宏定義,全局變量定義仪搔,函數(shù)聲明等瘾婿。
第二部分主要是對(duì)文法的終結(jié)符和非終結(jié)符做一些相關(guān)聲明。這些聲明主要有如下一些:%token僻造,%left憋他,%right,%nonassoc髓削,%union,%type镀娶,%start立膛。下面分別說(shuō)明它們的用法。
%token定義文法中使用了哪些終結(jié)符梯码,定義形式為:
%token TOKEN1 TOKEN2 TOKEN3 …
%left宝泵,%right,%nonassoc也是定義文法中使用的終結(jié)符轩娶,定義形式與%token類(lèi)似儿奶,但是他們定義的終結(jié)符具有某種優(yōu)先級(jí)和結(jié)合性,%left表示左結(jié)合鳄抒,%right表示右結(jié)合闯捎,%nonassoc表示不可結(jié)合(即它定義的終結(jié)符不能連續(xù)出現(xiàn):例如<,如果文法中不允許出現(xiàn)形如a<b<c的句子许溅,則<就是不可結(jié)合的)瓤鼻。而優(yōu)先級(jí)關(guān)系則是以他們定義出現(xiàn)的順序決定的,先定義的優(yōu)先級(jí)低贤重,最后定義的優(yōu)先級(jí)最高茬祷,同時(shí)定義的優(yōu)先級(jí)相同。例如并蝗,如果有如下定義:
%left A B %nonassoc C %right D
則表示優(yōu)先級(jí)關(guān)系為: A=B < C < D祭犯,而結(jié)合性關(guān)系為:A,B左結(jié)合,C不可結(jié)合滚停,D右結(jié)合沃粗。
%union和%type用來(lái)處理文法中各符號(hào)所帶的屬性。在詞法分析的學(xué)習(xí)中铐刘,我們知道記號(hào)是由記號(hào)名和記號(hào)的屬性值兩部分組成的陪每,文法中的終結(jié)符就是記號(hào),他們有屬性值,同樣檩禾,非終結(jié)符也是可以有屬性值的挂签。
%union { int num; char * id; }
定義了類(lèi)型,再將類(lèi)型和具體的標(biāo)示符進(jìn)行關(guān)聯(lián)盼产,如果是
終結(jié)符:
%token <num> TOKEN1 %token <id> TOKEN2 TOKEN3
非終結(jié)符:
%type <id> sym1 sym2 %type <num> sym3
第二部分規(guī)則段的寫(xiě)法
第二部分好理解饵婆,不作回顧。
第三部分輔助函數(shù)段的寫(xiě)法
輔助函數(shù)段用C語(yǔ)言語(yǔ)法來(lái)寫(xiě)戏售,輔助函數(shù)一般指在規(guī)則段中用到或者在語(yǔ)法分析器的其他部分用到的函數(shù)侨核。這一部分一般會(huì)被直接拷貝到y(tǒng)acc編譯器產(chǎn)生的c源文件中。 一般來(lái)說(shuō)灌灾,除規(guī)則段用到的函數(shù)外搓译,輔助函數(shù)段一般包括如下一些例程:yylex(),yyerror()锋喜,main()些己。
int yylex()是詞法分析程序,它返回記號(hào)嘿般。語(yǔ)法分析驅(qū)動(dòng)程序yyparse()將會(huì)調(diào)用yylex()獲取記號(hào)段标。如果不使用lex生成這個(gè)函數(shù),則必須在輔助函數(shù)段用C語(yǔ)言寫(xiě)這個(gè)程序炉奴。記號(hào)由記號(hào)名和屬性值構(gòu)成逼庞,記號(hào)名一般作為yylex的返回值(注意,記號(hào)名是由%token等定義的終結(jié)符名瞻赶,這些終結(jié)符名在yacc內(nèi)部會(huì)被宏定義成一些常數(shù)赛糟。),而屬性值則由yacc內(nèi)部定義的變量yylval來(lái)傳遞例如共耍,若屬性值棧定義為
%union { int num; char * id; }
而yylex返回記號(hào)的屬性值為”myid”(類(lèi)型為char *)時(shí)虑灰,yylex在返回之前,應(yīng)使用如下語(yǔ)句將屬性值傳遞給語(yǔ)法分析器:
yylval.id = “myid”;