




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第四部分:GCC語(yǔ)法與語(yǔ)義分析程序琚 小 明浙江大學(xué)信息與通信工程學(xué)系 2002年8月 一、語(yǔ)法與語(yǔ)義分析程序的主要功能語(yǔ)法分析是編譯過程的第二個(gè)階段。語(yǔ)法分析的任務(wù)是在詞法分析的基礎(chǔ)上將單詞序列分解成各類語(yǔ)法短語(yǔ),如“程序”,“語(yǔ)句”,“表達(dá)式”等等。一般這種語(yǔ)法短語(yǔ)也稱為語(yǔ)法單位,可表示成語(yǔ)法樹。(一)語(yǔ)法分析程序的主要功能語(yǔ)法分析所依據(jù)的是語(yǔ)言的語(yǔ)法規(guī)則,即描述程序結(jié)構(gòu)的規(guī)則。通過語(yǔ)法分析確定整個(gè)輸入串是否構(gòu)成一個(gè)語(yǔ)法上正確的程序。在GCC中采用自底向上(bottom-up)最右規(guī)約的語(yǔ)法分析方法進(jìn)行分析的,因?yàn)镚CC的語(yǔ)法分析程序是由語(yǔ)法分析程序自動(dòng)產(chǎn)生器(Yacc或bison)生成,
2、LR方法是YACC設(shè)定的語(yǔ)法分析方法。語(yǔ)義分析是審查源程序有無語(yǔ)義錯(cuò)誤,為代碼生成階段收集類型信息。例如語(yǔ)義分析的一個(gè)工作是進(jìn)行類型審查,審查每個(gè)算符是否具有語(yǔ)言規(guī)范允許的運(yùn)算對(duì)象,當(dāng)不符合語(yǔ)言規(guī)范時(shí),編譯程序應(yīng)報(bào)告錯(cuò)誤。詞法分析和語(yǔ)法分析本質(zhì)上都是對(duì)源程序的結(jié)構(gòu)進(jìn)行分析。但詞法分析的任務(wù)僅對(duì)源程序進(jìn)行線性掃描即可完成,例如識(shí)別標(biāo)識(shí)符,因?yàn)闃?biāo)識(shí)符的結(jié)構(gòu)是字母打頭的字母和數(shù)字串,這只要順序掃描輸入流,遇到既不是字母又不是數(shù)字字符時(shí),將前面所發(fā)現(xiàn)的所有字母可數(shù)字組合在一起而構(gòu)成單詞標(biāo)識(shí)符。但這種線性掃描不能用于識(shí)別的遞歸定義的語(yǔ)法成分,比如不能用此辦法去匹配表達(dá)式中的括號(hào)。(二)語(yǔ)法分析程序自動(dòng)產(chǎn)
3、生器(YACC)簡(jiǎn)介由于GCC中的語(yǔ)法分析程序是由YACC產(chǎn)生的,故在此對(duì)YACC的工作原來作一簡(jiǎn)要的介紹。YACC的工作示意圖如圖1:(有關(guān)YACC的詳細(xì)資料見YACC的說明文檔)YACC源程序YACC單詞符號(hào)串(終結(jié)符)語(yǔ)法分析的輸出語(yǔ)法分析程序 yyparse輸入串詞法分析程序 yylex圖1 YACC工作示意圖。YACC源程序是用戶按要求對(duì)要處理語(yǔ)言的語(yǔ)法描述,經(jīng)YACC產(chǎn)生語(yǔ)法分析程序yyparse。圖中的詞法分析程序是GCC提供的,它的輸出作為語(yǔ)法分析程序的輸入。在圖中YACC源程序是用戶用YACC提供的一種類似BNF的語(yǔ)言寫的要處理的語(yǔ)言的語(yǔ)法描述。YACC會(huì)自動(dòng)的將這個(gè)源程序轉(zhuǎn)
4、換成用LR方法進(jìn)行語(yǔ)法分析的語(yǔ)法分析程序yyparse,YACC的宿主語(yǔ)言是c,因此yyparse是一個(gè)c語(yǔ)言的程序,用戶在主程序中通過調(diào)用yyparse進(jìn)行語(yǔ)法分析。語(yǔ)法分析必須建立在詞法分析的基礎(chǔ)之上,所以生成的語(yǔ)法分析程序還要有一個(gè)詞法分析程序與它配合工作。yyparse要求這個(gè)詞法分析程序的名字為yylex。用戶寫yylex時(shí)可以借助于LEX,也可以人工編寫。在YACC源程序中除了語(yǔ)法規(guī)則外,還要包括當(dāng)這些語(yǔ)法規(guī)則被識(shí)別出來時(shí),即用它們進(jìn)行歸約時(shí)要完成的語(yǔ)義動(dòng)作,語(yǔ)義動(dòng)作是用c語(yǔ)言寫的程序段。語(yǔ)法分析的輸出可能是一顆語(yǔ)法樹,或生成的目標(biāo)代碼,或者就是關(guān)于輸入串是否符合語(yǔ)法的信息。需要什
5、么樣的輸出都是由語(yǔ)義動(dòng)作和程序部分的程序段來實(shí)現(xiàn)的。(三)語(yǔ)法分析程序的文件構(gòu)成語(yǔ)法分析程序盡管是由YACC自動(dòng)產(chǎn)生的,但其語(yǔ)義動(dòng)作是由用戶自己編寫的c代碼,構(gòu)成語(yǔ)法分析程序的文件有:c-parse.y,tree.h,tree.def, c-tree.h,tree.c,c-decl.c,c-typeck.c, stmt.c等。其中c-parse.y是根據(jù)YACC的規(guī)范要求對(duì)c語(yǔ)言文法進(jìn)行的語(yǔ)法描述文件,即YACC源程序,經(jīng)YACC可產(chǎn)生相應(yīng)的c文件c-parse.c。相關(guān)的文件有c-lex.h,input.h,c-iterate.c,varasm.c,c-common.c,c-lex.c, m
6、achmode.h, machmode.def, obstack.h, real.h, rtl.h。等二、語(yǔ)法與語(yǔ)義分析程序的流程圖及其說明(一)語(yǔ)法分析程序的主要工作原理由YACC產(chǎn)生的語(yǔ)法分析程序是由放在棧中的有限狀態(tài)機(jī)構(gòu)成的,它同時(shí)能夠讀取并記住下一個(gè)輸入的單詞(token),有時(shí)也叫這樣的單詞為向前看字符(lookahead token)。有限狀態(tài)機(jī)的狀態(tài)是用一個(gè)整數(shù)表示的,這與詞法、語(yǔ)法分析程序中的單詞是相似的。在初始時(shí),機(jī)器處在0狀態(tài),此時(shí)僅僅棧中包含了狀態(tài)0,而沒有向前看字符被讀入。有限自動(dòng)機(jī)在語(yǔ)法分析程序中可執(zhí)行相應(yīng)的動(dòng)作,以決定下一步的動(dòng)作。語(yǔ)法分析可執(zhí)行的動(dòng)作(action
7、)共有4個(gè),它們分別是:移進(jìn)(shift)、歸約(reduce)、接受(accept)和錯(cuò)誤(error)。語(yǔ)法分析程序的運(yùn)行如下:1根據(jù)當(dāng)前狀態(tài),語(yǔ)法分析程序決定是否需要一個(gè)向前看字符以決定將要執(zhí)行什么動(dòng)作。如果需要一個(gè)單詞但還沒有讀入時(shí),語(yǔ)法分析程序?qū)⒄{(diào)用yylex獲得下一個(gè)單詞。2用當(dāng)前狀態(tài)和向前看字符(如果需要的話),語(yǔ)法分析程序決定它的下一個(gè)動(dòng)作(action),并且執(zhí)行這個(gè)動(dòng)作。這樣將導(dǎo)致狀態(tài)被壓入或被彈出棧,以及向前看字符是被處理了還是放在一邊待用的不同變化。以下分別說明4種語(yǔ)法動(dòng)作:移進(jìn)動(dòng)作(shift action)是語(yǔ)法分析程序采用的最平常的動(dòng)作。根據(jù)當(dāng)前棧的狀態(tài)和向前看字
8、符,語(yǔ)法分析程序查動(dòng)作表(action表),以決定將采取什么動(dòng)作。對(duì)于移進(jìn)動(dòng)作,不論何時(shí)采用移進(jìn)動(dòng)作,都有一個(gè)向前看字符,不然移進(jìn)動(dòng)作將無法執(zhí)行對(duì)單詞的清除處理。而對(duì)應(yīng)的狀態(tài)卻被壓入了狀態(tài)棧,從而造成錯(cuò)誤。歸約(reduce action)是用語(yǔ)法規(guī)則的左邊代替其右邊的過程。當(dāng)語(yǔ)法分析程序已經(jīng)看到某語(yǔ)法規(guī)則的右邊,并且確定右邊是語(yǔ)法規(guī)則的一個(gè)實(shí)例時(shí),歸約動(dòng)作將被采用。通常語(yǔ)法分析程序在采用歸約動(dòng)作時(shí)是不需要查看向前看字符的。歸約動(dòng)作能防止棧無限增大,因?yàn)榇蠖鄶?shù)情況下歸約動(dòng)作是將狀態(tài)彈出棧,減少占用的??臻g。歸約動(dòng)作取決于語(yǔ)法規(guī)則左邊的符號(hào)(非終結(jié)符)和右邊的符號(hào)(終結(jié)符和非終結(jié)符)數(shù)。歸約動(dòng)作
9、首先根據(jù)語(yǔ)法規(guī)則右邊的符號(hào)數(shù)決定將被彈出棧的狀態(tài)數(shù),然后將狀態(tài)從棧中彈出,使棧中的其它的狀態(tài)被顯露出來。事實(shí)上,被彈出的狀態(tài)就是在識(shí)別此規(guī)則右邊單詞時(shí)壓入棧的狀態(tài),規(guī)則一旦被識(shí)別,這些狀態(tài)將不再有用。將這些狀態(tài)彈出之后,在狀態(tài)棧中處在棧頂?shù)臓顟B(tài)是語(yǔ)法分析程序開始處理此規(guī)則之前的狀態(tài)。使用彈出之后的狀態(tài)和規(guī)則左邊的符號(hào),將獲得一個(gè)新狀態(tài)(查狀態(tài)轉(zhuǎn)換表即goto表得到)。將此新狀態(tài)壓入棧,語(yǔ)法分析繼續(xù)。處理左邊符號(hào)和普通的單詞移進(jìn)是有明顯的不同的。把對(duì)左邊符號(hào)的移進(jìn)動(dòng)作叫做狀態(tài)轉(zhuǎn)換動(dòng)作(goto action),尤其不同的是,當(dāng)執(zhí)行移進(jìn)時(shí),向前看字符是被清除的,但在執(zhí)行狀態(tài)轉(zhuǎn)換動(dòng)作時(shí),向前看字符是
10、不受影響的。(事實(shí)上,歸約動(dòng)作在語(yǔ)法分析過程中好像是時(shí)間倒轉(zhuǎn),將狀態(tài)從棧中彈出回到規(guī)則右邊剛開始看到時(shí)的狀態(tài)。當(dāng)一條規(guī)則被識(shí)別時(shí),語(yǔ)法分析程序好似在那時(shí)看到了規(guī)則的左邊。)如果規(guī)則的右邊是空的,沒有狀態(tài)被彈出棧,也就是棧中被顯露出來的狀態(tài)就是棧中的當(dāng)前狀態(tài)。歸約在處理用戶提供的動(dòng)作和值時(shí)也是重要的。當(dāng)一條規(guī)則被識(shí)別并被歸約時(shí),在棧被調(diào)整以前,由規(guī)則提供的代碼(code)將被執(zhí)行。語(yǔ)法分析程序使用兩個(gè)棧:一個(gè)是擁有狀態(tài)的棧,即上文提到的棧;另一個(gè)是與之并行運(yùn)行的值棧(value stack),這個(gè)棧擁有從詞法分析程序和動(dòng)作返回的值。當(dāng)移進(jìn)時(shí),外部變量yylavl被拷貝到值棧。從用戶碼(user
11、code)返回后,歸約被執(zhí)行。當(dāng)狀態(tài)轉(zhuǎn)換動(dòng)作被執(zhí)行后,外部變量yylval被拷貝到值棧。在YACC中,用偽變量$1,$2等來代表值棧的值,而$代表左邊非終結(jié)符的值。另外兩個(gè)語(yǔ)法動(dòng)作相對(duì)來說比較簡(jiǎn)單。接受動(dòng)作(accept action)表明整個(gè)輸入都已經(jīng)看到并且匹配語(yǔ)法規(guī)則,這個(gè)動(dòng)作只有當(dāng)向前看單詞是endmarker(文件結(jié)束符,在GCC中是以EOF為文件結(jié)束符的)才被采用,表明語(yǔ)法分析程序已經(jīng)成功地完成語(yǔ)法分析工作。報(bào)錯(cuò)動(dòng)作(error action)說明根據(jù)規(guī)則在某處語(yǔ)法分析程序不能再繼續(xù)語(yǔ)法分析了。當(dāng)輸入的單詞已經(jīng)被看到,同時(shí)還有向前看字符,但后面不能跟隨可導(dǎo)致合法輸入的任何東西,此時(shí)
12、語(yǔ)法分析程序報(bào)告一個(gè)錯(cuò)誤,并且試圖恢復(fù)狀況(situation),試圖接著進(jìn)行語(yǔ)法分析。(二)語(yǔ)法分析程序yyparse的主要流程說明在語(yǔ)法分析過程中,YACC語(yǔ)法分析器主要使用兩個(gè)棧:一個(gè)是狀態(tài)棧,一個(gè)是語(yǔ)義值棧。兩套指針:short *yyss, yyssa;YYSTYPE *yyvs, yyvsa。1 初始化狀態(tài)棧的狀態(tài)和值棧的單詞值。yystate=0;yyerrstatus=0;yynerrs=0;yychar=YYEMPTY; 初始化棧指針:yyssp=yyss-1; yyvsp=yyvs;對(duì)于其中主要變量的說明:yychar 是lookahead symbol;yychar1是y
13、ychar的語(yǔ)法分析的內(nèi)部形式;yylval 是lookahead symbol 的語(yǔ)義值; yyval 是用于從執(zhí)行程序中返回語(yǔ)義值;yystate 是從執(zhí)行程序中返回的狀態(tài)。2yynewstate:將返回的狀態(tài)yystate壓入狀態(tài)棧,成為新狀態(tài)。*+yyssp=yystate;3取出產(chǎn)生式號(hào)yyn=yypactyystate;如果產(chǎn)生式號(hào)yyn為YYFLAG,則轉(zhuǎn)到4(yydefault)。如果yychar為YYEMPTY,則調(diào)用詞法分析函數(shù)得到一個(gè)單詞(token),即 yychar=YYLEX。索引表是用單詞(token)的內(nèi)部形式索引的,故將單詞轉(zhuǎn)換為內(nèi)部形式。 當(dāng)yychar&l
14、t;=0 時(shí):yychar1=0; yychar=YYEOF;當(dāng)yychar>0時(shí):yychar1=YYTRANSLATE(yychar);計(jì)算yychar1的產(chǎn)生式號(hào):yyn+=yychar1;根據(jù)計(jì)算的產(chǎn)生式號(hào)到表中取出相應(yīng)的產(chǎn)生式號(hào): 初始化狀態(tài)和棧指針yynewstate讀取向前看單詞,并將其轉(zhuǎn)換成語(yǔ)法分析的內(nèi)部形式;置新狀態(tài)。計(jì)算產(chǎn)生式號(hào),并由此查yytable表得到產(chǎn)生式號(hào)yyn移進(jìn)NYYyyn > 0Nyyn < 0或yyn=0Y成功NY歸約Y出錯(cuò)yyn < 0Nyyn是終態(tài)?圖2 語(yǔ)法分析程序的流程圖。語(yǔ)法分析有兩個(gè)棧:一個(gè)是狀態(tài)棧;一個(gè)是值棧。這兩個(gè)棧
15、在進(jìn)行語(yǔ)法分析時(shí),它們的棧指針是同步移動(dòng)的。對(duì)于出錯(cuò)情況的處理有兩種:一種是處理后繼續(xù)執(zhí)行語(yǔ)法分析;一種是中斷返回。圖中用虛線表示是編譯器多數(shù)情況下的處理結(jié)果。yyn=yytableyyn。yyn是這個(gè)token類型在此狀態(tài)下要做的動(dòng)作:如果yyn是正數(shù),則移進(jìn),而yyn是新狀態(tài)。如果yychar不是YYEOF,則放棄被移進(jìn)的token,置yychar=YYEMPTY; *+yyvsp=yylval; yystate=yyn;轉(zhuǎn)到2(yynewstate);如果新狀態(tài)是終態(tài),則返回成功而不必移進(jìn)。4yydefault:執(zhí)行當(dāng)前狀態(tài)的默認(rèn)產(chǎn)生式。 yyn=yydefactyystate; 5yy
16、reduce:如果yyn是負(fù)數(shù),則規(guī)約,而-yyn是語(yǔ)法規(guī)則號(hào),yyn=-yyn;yylen=yyr2yyn; 如果yylen>0, 則yyval=yyvsp1-yylen;由此實(shí)現(xiàn)執(zhí)行的默認(rèn)值。6如果yyn是0或者大多數(shù)的負(fù)數(shù)時(shí),則出錯(cuò)。7根據(jù)yyn的值確定產(chǎn)生式,并執(zhí)行相應(yīng)的動(dòng)作。8規(guī)約后,yyvsp-=yylen;yyssp-=yylen;將單詞(token)的語(yǔ)義值賦給語(yǔ)義棧,*+yyvsp=yyval;yychar!=YYEOFyyn>0NY放棄被移進(jìn)的單詞yychar=YYEMPTYY將單詞的值壓入值棧*+yyvsp=yylval將新狀態(tài)壓入狀態(tài)棧yystate=yyn
17、yynewstate圖3 移進(jìn)動(dòng)作的流程圖。移進(jìn)動(dòng)作較簡(jiǎn)單,只需將單詞放棄,即將yychar置為YYEMPTY。然后將單詞的值和新狀態(tài)分別壓入值棧和狀態(tài)棧。返回到語(yǔ)法分析的開始處。9根據(jù)彈出后的狀態(tài)和被規(guī)約的產(chǎn)生式號(hào)決定轉(zhuǎn)換到什么狀態(tài)。yyn=yyr1yyn; yystate=yypgotoyyn-YYNTBASE+*yyssp;當(dāng)yystate不在yytable表中時(shí),yystate=yytableyystate;否則yystate=yydefgotoyyn-YYNTBASE;轉(zhuǎn)到2(yynewstate)。10yyerrhandle:出錯(cuò)處理。yystate=yyn;轉(zhuǎn)到2(yynewst
18、ate)?;蚍祷?。11yyacceptlab:接受狀態(tài),釋放棧空間:free(yyss);free(yyvs); 并返回0。 對(duì)于語(yǔ)法分析時(shí)進(jìn)行歸約所要執(zhí)行的動(dòng)作在此不作介紹,相關(guān)的說明見第四部分的函數(shù)功能介紹和語(yǔ)法樹結(jié)構(gòu)等內(nèi)容。歸約動(dòng)作的主要內(nèi)容是建立語(yǔ)法樹,并進(jìn)行相應(yīng)的語(yǔ)法和語(yǔ)義分析。yyn<0Y將產(chǎn)生式號(hào)取反yyn=-yynyyval=yyvsp1-yylenyylen>0查yyr2表得到歸約的長(zhǎng)度yylen=yyr2yynN根據(jù)yyn的不同完成各種歸約動(dòng)作(詳見源代碼)根據(jù)歸約的長(zhǎng)度yylen,彈出狀態(tài)棧和值棧中相應(yīng)數(shù)量的狀態(tài)和值。yyvsp-=yylen;yyssp-=
19、yylen;將返回的語(yǔ)義值置入值棧*+yyvsp=yyval移進(jìn)歸約的結(jié)果yyn=yyr1yyn;根據(jù)當(dāng)前的狀態(tài)和歸約的產(chǎn)生式號(hào),決定轉(zhuǎn)換的狀態(tài)yystate=yypgotoyyn-YYNTBASE+*yysspyystate>=0&&yystate<=YYLAST&&yycheckyystate=*yyssp查yytable表得到新狀態(tài)yystate=yytableyystateYN查yydefgoto表得到新狀態(tài)yystate=yydefgotoyyn-YYNTBASEyynewstate圖4 歸約動(dòng)作的流程圖。根據(jù)產(chǎn)生式號(hào)進(jìn)行相應(yīng)的歸約動(dòng)作,用
20、產(chǎn)生式的左邊代替右邊,并將相應(yīng)的狀態(tài)和值彈出棧。根據(jù)當(dāng)前狀態(tài)和產(chǎn)生式號(hào),從轉(zhuǎn)換表(yypgoto)中得到新狀態(tài)。三、語(yǔ)法與語(yǔ)義分析程序的數(shù)據(jù)結(jié)構(gòu)及其說明GCC語(yǔ)法分析程序的一個(gè)主要任務(wù)是建立合理和有效的語(yǔ)法樹。為此,GCC定義了由12個(gè)數(shù)據(jù)結(jié)構(gòu)組成的一個(gè)聯(lián)合,這個(gè)聯(lián)合能夠描述不同樹節(jié)點(diǎn)的全部?jī)?nèi)容。這些不同的樹節(jié)點(diǎn)是由TREE_CODE來說明的,而TREE_CODE是在文件tree.def中定義的。一個(gè)樹節(jié)點(diǎn)能描述一個(gè)數(shù)據(jù)類型、一個(gè)變量、一個(gè)表達(dá)式或一個(gè)語(yǔ)句。每個(gè)節(jié)點(diǎn)都有一個(gè)TREE_CODE用來說明所描述的內(nèi)容是哪類的。例如常用的codes:INTEGER_TYPE描述的是整型類型;ARRAY
21、_TYPE描述的是指針類型;VAR_DECL描述的是已聲明了的變量;INTEGER_CST描述的是整型常量值;PLUS_EXPR描述的是一個(gè)和(一個(gè)表達(dá)式)等。(一) 樹節(jié)點(diǎn)的類型TREE_CODE的有關(guān)說明對(duì)TREE_CODE的定義采用如下方法:#define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM, enum tree_code #include “tree.def”LAST_AND_UNUSED_TREE_CODE;#undef DEFTREECODE文件tree.def是用來定義TREE_CODE的,其形式如下:DEFTREECODE(IDE
22、NTIFIER_NODE, “identifier_node”, “x”, -1)其中的第一個(gè)參數(shù)是用來定義TREE_CODE的;第二個(gè)參數(shù)是輸出時(shí)用的;第三個(gè)參數(shù)可以是下列參數(shù)之一:“x” 用于表示特別的TREE_CODE,它不屬于任何一類?!皌” 用于表示類型?!癰” 用于表示詞法的塊?!癱” 用于表示常量?!癲” 用于表示聲明?!皉” 用于表示訪問存儲(chǔ)器?!?lt;” 用于表示比較表達(dá)式?!?” 用于表示一元算術(shù)表達(dá)式?!?” 用于表示二元算術(shù)表達(dá)式。“s” 用于表示固有副作用(side effects)的表達(dá)式。“e” 用于表示其他種類的表達(dá)式。對(duì)應(yīng) “r”、“e”、“<”、“1
23、”、“2”、“s”和“x”所表示的節(jié)點(diǎn),第四個(gè)元素是表示要分配參數(shù)槽的數(shù)量,這決定了樹節(jié)點(diǎn)的大小。TREE_CODE共有11種類別(數(shù)字表示可再分類的個(gè)數(shù)),總計(jì)有125種不同的TREE_CODE用來表示不同的節(jié)點(diǎn),下面所列的是關(guān)于對(duì)文件tree.def的一個(gè)統(tǒng)計(jì),詳細(xì)的內(nèi)容見源代碼。1. error_mark: 12. identifier: 23. tree_list: 14. tree_vec: 15. block:: 16. datatype: 20 (5 for pascal)7. constant: 58. declaration: 89. reference: 610. cons
24、tructor:111. expression: 79 (4 for pascal)(二) 樹節(jié)點(diǎn)的有關(guān)結(jié)構(gòu)說明對(duì)于一個(gè)樹節(jié)點(diǎn)的內(nèi)容,有些結(jié)構(gòu)成員或字段(fields)是所有節(jié)點(diǎn)共享的,同樣有些有各自不同特殊用途的字段。在GCC中,為了一致樹節(jié)點(diǎn)的結(jié)構(gòu),定義了一個(gè)聯(lián)合(union)tree_node,所有的樹節(jié)點(diǎn)均可以用此聯(lián)合來表示。在這個(gè)聯(lián)合中,總共包含了12個(gè)結(jié)構(gòu),其中結(jié)構(gòu)tree_common是一個(gè)通用的結(jié)構(gòu),可以認(rèn)為是其他11個(gè)結(jié)構(gòu)的共有部分。另外11結(jié)構(gòu)是為各種不同的樹結(jié)構(gòu)而定義的,但它們?cè)诮Y(jié)構(gòu)定義中都為tree_common結(jié)構(gòu)保留了空間,因此,tree_common結(jié)構(gòu)在聯(lián)合中始
25、終是存在的,成為所有結(jié)構(gòu)的共享部分。這個(gè)聯(lián)合的定義如下:union tree_node struct tree_common common; /通用結(jié)構(gòu),是其他11個(gè)結(jié)構(gòu)在聯(lián)合中的共有部分。 struct tree_int_cst int_cst; /整型常量結(jié)構(gòu) struct tree_real_cst real_cst; /實(shí)型常量結(jié)構(gòu) struct tree_string string; /字符串常量結(jié)構(gòu) struct tree_complex complex; /復(fù)數(shù)類型結(jié)構(gòu) struct tree_identifier identifier; /標(biāo)識(shí)符結(jié)構(gòu) struct tree_d
26、ecl decl; /聲明與定義結(jié)構(gòu) struct tree_type type; /類型說明結(jié)構(gòu) struct tree_list list; /列表節(jié)點(diǎn),用于數(shù)據(jù)結(jié)構(gòu)的描述等 struct tree_vec vec; /矢量結(jié)構(gòu) struct tree_exp exp; /表達(dá)式結(jié)構(gòu) struct tree_block block; /塊結(jié)構(gòu),用于描述函數(shù)體等以及一個(gè)重要的結(jié)構(gòu)指針的定義:typedef union tree_node * tree;在GCC中,對(duì)節(jié)點(diǎn)的結(jié)構(gòu)成員或字段(fields)是不直接存取的,都是通過定義宏的方式來實(shí)現(xiàn)這一目的的。例如:#define TREE_COD
27、E(NODE) (enum tree_code)(NODE)->common.code)這些宏的定義都是在文件tree.h中。下面將對(duì)聯(lián)合中的每個(gè)結(jié)構(gòu)的主要結(jié)構(gòu)成員作一簡(jiǎn)要的說明,關(guān)于聯(lián)合中的12個(gè)結(jié)構(gòu)的定義詳見附錄。(1) 結(jié)構(gòu)tree_common主要成員的說明:code:code即指TREE_CODE,說明的是什么類型的節(jié)點(diǎn)。Code是在文件tree.def中定義的。type:在所有是表達(dá)式的節(jié)點(diǎn)中,這是表達(dá)式的數(shù)據(jù)類型;在POINTER_TYPE節(jié)點(diǎn)中,這是指針?biāo)赶虻念愋?;在ARRAY_TYPE節(jié)點(diǎn)中,這是元素的類型。chain:很多情況下節(jié)點(diǎn)是通過chain鏈接起來的,這些節(jié)
28、點(diǎn)被鏈接在一起有很多用途。如:a、類型節(jié)點(diǎn)被鏈接在一起是為輸出到debugger調(diào)試程序而記錄這些類型的; b、在同一范圍(scope)的聲明節(jié)點(diǎn)將被鏈接在一起以記錄此范圍的內(nèi)容;c、連續(xù)語(yǔ)句的語(yǔ)句節(jié)點(diǎn)通常被鏈接在一起;d、通常列表(lists)是由被鏈接在一起的TREE_LIST節(jié)點(diǎn)來描述的。(2) 結(jié)構(gòu)tree_int_cst主要成員的說明:在INTEGER_CST節(jié)點(diǎn)中,int_cst_low和int_cst_high一起組成一個(gè)2字節(jié)整數(shù)。如果是有符號(hào)的數(shù)據(jù)類型,則整數(shù)的值是擴(kuò)展符號(hào)位的2字節(jié)數(shù),即使原來的2字節(jié)并不是所有位都被使用。如果是無符號(hào)的整數(shù)常量,則額外的符號(hào)位是0。在FAC
29、T_CST節(jié)點(diǎn)中,2個(gè)長(zhǎng)整型用來得到64位數(shù),用于描述分?jǐn)?shù)。(3) 結(jié)構(gòu)tree_real_cst主要成員的說明:在REAL_CST節(jié)點(diǎn)中,可以將一個(gè)實(shí)數(shù)值描述成“double”或是字符串。(4) 結(jié)構(gòu)tree_string主要成員的說明length:是字符串的長(zhǎng)度,整型。pointer:是指向字符串的字符指針。(5) 結(jié)構(gòu)tree_complex主要成員的說明:real:在COMPLEX_CST節(jié)點(diǎn)中real是復(fù)數(shù)的實(shí)部。imag:在COMPLEX_CST節(jié)點(diǎn)中imag是復(fù)數(shù)的虛部。(6) 結(jié)構(gòu)tree_identifier主要成員的說明:這是為某些特殊用途的樹節(jié)點(diǎn)定義的。length:是標(biāo)
30、識(shí)符的長(zhǎng)度。pointer:是指向標(biāo)識(shí)符的字符指針。(7) 結(jié)構(gòu)tree_list主要成員的說明:這些list節(jié)點(diǎn)通過TREE_CHAIN鏈接成列表。purpose:指向參數(shù)鏈的指針。value:(8) 結(jié)構(gòu)tree_vec主要成員的說明:length:是數(shù)組元素的個(gè)數(shù)。a1:是指向數(shù)組元素的結(jié)構(gòu)指針。(9) 結(jié)構(gòu)tree_exp主要成員的說明:complexity:operands1:是指向操作數(shù)的結(jié)構(gòu)指針。在SAVE_EXPR節(jié)點(diǎn)中,用的是operands1, operands2。在RTL_EXPR節(jié)點(diǎn)中,用的是operands0, operands1。在CALL_EXPR節(jié)點(diǎn)中,用的是o
31、perands2。在CONSTRCTOR節(jié)點(diǎn)中,用的是operands1。在通常的表達(dá)式節(jié)點(diǎn)中,任意一個(gè)操作數(shù)operandsI都有可能被使用, 同時(shí)還有成員complexity。(10) 結(jié)構(gòu)tree_block主要成員的說明:subblocks:包含了一個(gè)由BLOCK_CHAIN 鏈接起來的子塊的鏈。 supercontext: 指向父塊(parent block)。 對(duì)于一個(gè)描述函數(shù)最外層范圍的塊,它指向函數(shù)聲明節(jié)點(diǎn)(FUNCTION_DECL)。 vars: 指向聲明節(jié)點(diǎn)的鏈。 type_tags:指向有自己名字的類型的鏈。 chain: 指向下一個(gè)同一級(jí)(level)的塊,即指前面提
32、到的BLOCK_CHAIN。abstract_origin: 指向起始(original)樹節(jié)點(diǎn),當(dāng)前塊是起始數(shù)節(jié)點(diǎn)的一個(gè)實(shí)例(instance),或者它為NULL,表明當(dāng)前塊不是其他任何節(jié)點(diǎn)的實(shí)例。當(dāng)它為非空(non-NULL)時(shí),它可指向另一個(gè)塊節(jié)點(diǎn),或者指向一個(gè)函數(shù)聲明節(jié)點(diǎn)。abstract_flag: 如果當(dāng)前塊描述的是一個(gè)塊的起始實(shí)例,則它是非0的。(11) 結(jié)構(gòu)tree_type主要成員的說明:size:包含一顆樹,這顆樹是一個(gè)按位計(jì)算大小的表達(dá)式。 mode:包含這種類型的機(jī)器模式的值。 pointer_to:包含了一個(gè)類型,用一個(gè)指針指向這種類型。如果pointer_to為0,
33、則這種類型的節(jié)點(diǎn)還未建立。 next_variant:是用于鏈接由類型限定修飾詞"const" 和 "volatile"修飾的變量的類型。 main_variant:指向上述由TYPE_NEXT_VARIANT鏈接的鏈的頭指針。 noncopied_parts:是一個(gè) list節(jié)點(diǎn),用于說明這個(gè)類型的對(duì)象哪一部分是不能通過賦值拷貝的。 每個(gè)節(jié)點(diǎn)的TREE_PURPOSE 是這部分的偏移量。TREE_VALUE 是這部分以位計(jì)的大小。 name:包含為這種類型在程序中使用的名字的信息(為GDB符號(hào)表的輸出)。它是一個(gè)類型定義(typedef)的 TYPE_
34、DECL節(jié)點(diǎn);或者是一個(gè)IDENTIFIER_NODE 節(jié)點(diǎn)在結(jié)構(gòu)、聯(lián)合、枚舉已知是有標(biāo)簽(tag)的;或者是0,當(dāng)類型還沒有特殊的名字。 context:對(duì)類型有一個(gè)名字或者已經(jīng)命名的成員(member)中的任意一種情況,它指向描述給定類型的范圍的節(jié)點(diǎn),或者如果此類型具有文件范圍(file scope),則它是NULL_TREE。對(duì)大多數(shù)的類型來說,它將指向一個(gè)塊(block)節(jié)點(diǎn)或是函數(shù)聲明節(jié)點(diǎn)(FUNCTION_DECL),但是它也能夠指向函數(shù)類型節(jié)點(diǎn)(FUNCTION_TYPE),或者是結(jié)構(gòu)類型節(jié)點(diǎn)(RECORD_TYPE)和 聯(lián)合類型節(jié)點(diǎn)(UNION_TYPE)。chain:是用于枚
35、舉類型(ENUMERAL_TYPE),結(jié)構(gòu)類型(RECORD_TYPE) 和 聯(lián)合類型(UNION_TYPE)節(jié)點(diǎn)的。(12) 結(jié)構(gòu)tree_decl主要成員的說明:所有與名字有關(guān)的都描述為._DECL節(jié)點(diǎn),這些在一個(gè)綁定上下文(binding context)的節(jié)點(diǎn)通過TREE_CHAIN鏈接起來。name:包含一個(gè)IDENTIFIER_NODE的節(jié)點(diǎn),此節(jié)點(diǎn)是給定實(shí)體的名字。對(duì)labels來說,DECL_NAME為0。context:指向描述此聲明作用范圍的上下文的節(jié)點(diǎn)。對(duì)FIELD_DECLs而言,這是定義它的RECORD_TYPE 或是 UNION_TYPE 節(jié)點(diǎn)。對(duì)VAR_DECL,
36、 PARM_DECL, FUNCTION_DECL, LABEL_DECL, 及CONST_DECL 節(jié)點(diǎn)來說,它指向包含它們的FUNCTION_DECL節(jié)點(diǎn)。如果給定的聲明是文件范圍,則它是 NULL_TREE。 abstract_origin:如果非0,它指向起始(original)聲明節(jié)點(diǎn),而當(dāng)前聲明節(jié)點(diǎn)是它的一個(gè)實(shí)例(instance)。當(dāng)相關(guān)的時(shí)候,TREE_TYPE 擁有對(duì)象的數(shù)據(jù)類型。而LABEL_DECLs 沒有數(shù)據(jù)類型。對(duì)TYPE_DECL來說, TREE_TYPE 的內(nèi)容是一個(gè)類型,它的類型名正在被聲明,也可以說TREE_TYPE是已聲明實(shí)體的類型。frame_size,
37、size, 和mode: 存在于聲明節(jié)點(diǎn)和類型節(jié)點(diǎn),它們?cè)贚ABEL_DECL, TYPE_DECL 和 CONST_DECL 節(jié)點(diǎn)中是沒有用的。以下三個(gè)字段僅與 FIELD_DECLs 和PARM_DECLs有關(guān):DECL_OFFSET :擁有相對(duì)位偏移的整數(shù)值。DECL_VOFFSET: 擁有可變偏移的表達(dá)式,它與DECL_VOFFSET_UNIT (一個(gè)整數(shù))相乘可得偏移量。initial:擁有對(duì)一個(gè)變量的初始化的值,或是初始化一個(gè)常量的值。對(duì)一個(gè)函數(shù)而言,它指向一個(gè)塊(block),用一個(gè)塊來說明函數(shù)的binding contour并且包含了函數(shù)的語(yǔ)句。對(duì)于C 中的 LABEL_DEC
38、L, 它是一個(gè)標(biāo)志(flag),當(dāng)label的定義已被看見時(shí),此標(biāo)志為非0。 PARM_DECLs 使用特殊的字段: initial:是參數(shù)實(shí)際上通過類型檢查的類型,此類型可能與它原來在函數(shù)中的類型有所不同。FUNCTION_DECLs 使用以下四個(gè)特殊的字段: arguments: 擁有一條參數(shù)聲明PARM_DECL節(jié)點(diǎn)的鏈。 result:擁有一個(gè)函數(shù)返回值聲明的 RESULT_DECL 節(jié)點(diǎn)。或者當(dāng)函數(shù)無返回值時(shí),它為0。(在c中,函數(shù)返回void即為無返回值) DECL_RESULT_TYPE :擁有函數(shù)實(shí)際返回值的類型。這通常與DECL_RESULT的類型是相同的,但這可能是一個(gè)寬整
39、型類型;同時(shí)為了內(nèi)聯(lián),甚至對(duì)函數(shù)的編譯已經(jīng)結(jié)束,這仍然有效。這是兩者的不同之處。frame_size:是一個(gè)代碼數(shù)字(code number),非0時(shí)表示是內(nèi)建函數(shù)(built-in function)。它的值是一個(gè)枚舉類型值,指明了是哪一個(gè)內(nèi)建函數(shù)。filename: 擁有一個(gè)文件名字符串。linenum:擁有一個(gè)行數(shù)。abstract_flag:非0時(shí),此聲明說明一個(gè)聲明的抽象實(shí)例(abstract instance)。 (三) 建立樹節(jié)點(diǎn)時(shí)的有關(guān)棧與數(shù)據(jù)結(jié)構(gòu)的說明Gcc在處理語(yǔ)法樹節(jié)點(diǎn)時(shí)使用棧存放節(jié)點(diǎn)的內(nèi)容,有關(guān)各個(gè)棧的詳細(xì)內(nèi)容見源代碼,下面僅對(duì)各棧作一簡(jiǎn)要的說明:1. permanen
40、t_obstack 存放永久的樹節(jié)點(diǎn),如標(biāo)識(shí)符,全局的有關(guān)東西,函數(shù)定義的參數(shù)等。2. maybepermanent_obstack 存放在函數(shù)內(nèi)的初始的RTL和_TYPE節(jié)點(diǎn),通常它們?cè)诤瘮?shù)結(jié)束時(shí)被釋放。3. temporay_obstack是用來讀全局變量的初始化值的。4. momentary_obstack 存放表達(dá)式的樹節(jié)點(diǎn),它們?cè)诒磉_(dá)式結(jié)束時(shí)都被釋放。5. temp_decl_obstack 存放的樹節(jié)點(diǎn),當(dāng)聲明通過語(yǔ)法檢查時(shí)被釋放。6. momentary_level 暫時(shí)存放momentary_obstack,以便恢復(fù)。7. obstack_stack 時(shí)用來選擇推進(jìn)還是彈出ob
41、stack。標(biāo)識(shí)符節(jié)點(diǎn)、體外所有的東西和函數(shù)定義的參數(shù)分配在permanent_obstack中。RTL的初始化,所有在一個(gè)函數(shù)內(nèi)的_TYPE節(jié)點(diǎn)分配在function_maybepermanent_obstack中,通常它們?cè)诤瘮?shù)結(jié)束時(shí)被釋放,但如果函數(shù)是內(nèi)聯(lián)函數(shù)時(shí)將被儲(chǔ)存,嵌套的函數(shù)存放在各自分開的棧中。當(dāng)前函數(shù)定義的內(nèi)容分配在function_obstack中,在函數(shù)結(jié)束時(shí)全部被釋放,嵌套的函數(shù)存放在各自分開的棧中。表達(dá)式節(jié)點(diǎn)分配在temp_decl_obstack中,當(dāng)聲明體通過語(yǔ)法時(shí)全部被釋放。Struct obstack *saveable_obstack 指向permanent_
42、obstack 或者當(dāng)前的function_maybepermanent_obstack.Struct obstack *current_obstack 指向permanent_obstack或者當(dāng)前的function_obstack.在語(yǔ)法和展開期間,Struct obstack *rtl_obstack 與saveable_obstack一樣;在優(yōu)化時(shí)它指向當(dāng)前函數(shù)的棧;這是用來產(chǎn)生rtl 對(duì)象的棧。Struct obstack *current_obstack指向permanent_obstack 或者當(dāng)前的function_obstack或者momentary_obstack.對(duì)每個(gè)b
43、inding contour 分配一個(gè)binding _level structure,這個(gè)結(jié)構(gòu)記錄了定義在那個(gè)contour中的names。Contour 包括:全局的contour;每個(gè)有參數(shù)的內(nèi)部聲明出現(xiàn)的函數(shù)定義;復(fù)合語(yǔ)句,記錄它的聲明。struct binding_leveltree names;tree tags;tree shadowed;tree blocks;tree this_block;struct binding_level *level_chain; char parm_flag;char tag_transparent;char subblocks_tag_tran
44、sparent;char keep;char keep_if_subblocks;int n_incomplete;tree parm_order;names:指向所有變量,常量,函數(shù)和typedef 類型的_DECL節(jié)點(diǎn)的鏈。這個(gè)鏈?zhǔn)且韵喾吹捻樞蛱峁┑?。tags:指向一個(gè)結(jié)構(gòu),聯(lián)合和枚舉定義的list, 這是一個(gè)TREE_LIST 節(jié)點(diǎn)的鏈,每個(gè)節(jié)點(diǎn)的TREE_PURPOSE 時(shí)一個(gè)name或者NULL_TREE; 節(jié)點(diǎn)的TREE_VALUE時(shí)一個(gè)RECORD_TYPE,UNION_TYPE,或者是ENUBERAL_TYPE節(jié)點(diǎn)。對(duì)每一層,當(dāng)這一層被彈出時(shí),被屏蔽的外層局部定義的list 將
45、被存儲(chǔ)。每個(gè)link 是一個(gè)TREE_LIST, 它的TREE_PURPOSE時(shí)一個(gè)標(biāo)識(shí)符,它的TREE_VALUE是它原來的定義(-DECL節(jié)點(diǎn))。blocks:對(duì)于每一個(gè)level,都有一條由塊(block)節(jié)點(diǎn)組成的鏈,blocks指向此鏈。shadowed:對(duì)于每一個(gè)level,當(dāng)這個(gè)level被彈出時(shí),被屏蔽(shadowed)的外層level的局部定義的list節(jié)點(diǎn)將被儲(chǔ)存起來。每個(gè)list鏈節(jié)點(diǎn)的TREE_PURPOSE是一個(gè)標(biāo)識(shí)符,而TREE_VALUESHI 是它老的定義(是_DECL節(jié)點(diǎn))。this_block:這層level的block節(jié)點(diǎn)由this_block指向。le
46、vel_chain:binding_level是由level_chain鏈接在一起的。parm_flag:非0表示此level擁有函數(shù)的參數(shù)。tag_transparent:非0表示這層level沒有tags。parm_order:聲明的列表是以相反的參數(shù)順序說明的。定義了三個(gè)主要的結(jié)構(gòu)指針,其中current_binding_level是當(dāng)前有效的操作level;free_binding_level是binding_level的鏈,用來把釋放的binding_level鏈起來以備重復(fù)使用。目的是減少內(nèi)存堆中的碎塊;global_binding_level是最外層的binding_level,
47、它是在編譯器開始編譯的時(shí)候建立的,并在整個(gè)運(yùn)行過程中存在。它們分別定義如下:struct binding_level * current_binding_level;struct binding_level * free_binding_level;struct binding_level * global_binding_level;(四)語(yǔ)法分析時(shí)建立的語(yǔ)法樹結(jié)構(gòu)對(duì)于每個(gè)binding contour都將分配一個(gè)binding_level節(jié)點(diǎn),用來記錄在這個(gè)contour這定義的names。Contour包含以下三個(gè)方面:1 全局的contour。2 每個(gè)函數(shù)定義都有一個(gè)對(duì)應(yīng)的contou
48、r,參數(shù)的內(nèi)部聲明出現(xiàn)在那里。3 每個(gè)復(fù)合語(yǔ)句對(duì)應(yīng)一個(gè)contour,用來記錄它的聲明。結(jié)構(gòu)指針free_binding_level的用處:當(dāng)一個(gè)binding_level節(jié)點(diǎn)被彈出時(shí),并不實(shí)際釋放內(nèi)存空間,而是將此節(jié)點(diǎn)鏈入到free_binding_level指向的鏈中。當(dāng)需要一個(gè)binding_level節(jié)點(diǎn)時(shí),首先查看free_binding_level鏈釋放為空。若有就重復(fù)使用原來已經(jīng)存在的節(jié)點(diǎn),否則新建一個(gè)節(jié)點(diǎn)。supercontextblockcurrent_function_decldecl nodeinitial resultinitial resultinitial resu
49、ltbinding_levelcurrent_binding_levelglobal_binding_levelnames tags blocksnames tags blocksnames tags blockslist nodevalue purposevalue purposevalue purposetype nodecontextcontextcontextblock nodeblock/ current_function_declinitialdecl nodeblock nodetype nodelist nodebinding level node圖5 頂層的語(yǔ)法樹結(jié)構(gòu)bind
50、ing_level。GCC在進(jìn)行語(yǔ)法分析時(shí),是以current_binding_level為中心,所有的聲明、參數(shù)定義和塊等都是掛在binding_level上的。圖中的虛線箭頭表示省略了節(jié)點(diǎn),對(duì)與其他圖相連的連線和箭頭采用不同的顏色加以區(qū)別。存儲(chǔ)當(dāng)前l(fā)evel的狀態(tài):每當(dāng)當(dāng)前l(fā)evel被彈出時(shí),level中的狀態(tài)將被保存到一個(gè)塊(block)中。將當(dāng)前l(fā)evel的names(decls)鏈入block的vars;將當(dāng)前l(fā)evel的tags鏈入block的type_tags;將當(dāng)前l(fā)evel的blocks鏈入block的subblocks。然后將當(dāng)前l(fā)evel節(jié)點(diǎn)彈出,同時(shí)鏈入到free_bi
51、nding_level鏈中,并使下一個(gè)level節(jié)點(diǎn)成為當(dāng)前l(fā)evel。parm decl nodeinitial resultinitial resultinitial resultblock nodesupercontextsupercontextcurrent_function_declnamesinitial result type argumentsdecl nodecontexttype valuestype nodetype nodevalue purposevalue purposelist nodevalue purposearg types圖6 當(dāng)前函數(shù)聲明current_
52、function_decl的語(yǔ)法樹結(jié)構(gòu)。initial 指向的block節(jié)點(diǎn)包含了函數(shù)體的語(yǔ)句;result指向的decl節(jié)點(diǎn)是函數(shù)的返回值;arguments指向的是參數(shù)聲明節(jié)點(diǎn)的鏈。TYPE_VALUES是list鏈,它的 TREE_PURPOSE是名字,TREE_VALUE是值 ( INTEGER_CST節(jié)點(diǎn))。block nodeblockvars type_tags subblocks supercontextcurrent_function_declblockstagsnamesblock nodelist nodevalue purposevalue purposevalue p
53、urposedecl nodeinitial resultinitial resultinitial result圖7 塊節(jié)點(diǎn)block的語(yǔ)法樹結(jié)構(gòu)。一個(gè)塊包含聲明、參數(shù)、子塊等,這些都是掛在同一個(gè)塊的節(jié)點(diǎn)上的。以個(gè)塊也可能是一個(gè)函數(shù)體,在圖5中,函數(shù)聲明initial指向的塊block就是一個(gè)函數(shù)體。四、語(yǔ)法與語(yǔ)義分析程序主要函數(shù)的功能:void push_obstacks (curren, saveable)struct abstack* current, *saveable;將當(dāng)前各棧的指針放到obstack_stack 中,然后將current,saveable設(shè)置為當(dāng)前棧。void
54、push_obstacks_nochange ()將當(dāng)前各棧中的指針存放到obstack_stack中,并使棧指針指向它。void push_momentary ()分配臨時(shí)存儲(chǔ)空間(struct momentary_level) (在c 中,每個(gè)復(fù)合語(yǔ)句有自己的層次,這個(gè)層次在每個(gè)語(yǔ)句結(jié)束時(shí)被釋放。所有表達(dá)式節(jié)點(diǎn)也是分配momentary_stack)。void pop_momentary ()釋放momentary_stack。tree make_node (code)enum tree_code code;根據(jù)code指向不同的obstack, 在obstack 中創(chuàng)建對(duì)應(yīng)code 的節(jié)點(diǎn),并返回這個(gè)節(jié)點(diǎn)的指針。Identifier 節(jié)點(diǎn)始終是永久的,因?yàn)樗鼈冊(cè)诰幾g器運(yùn)行中是唯一的,初始化它的id和它的TREE_PERMANENT flag。對(duì)decl和type節(jié)點(diǎn),一些其它fields要初始化(如decl_source_line; decl_source_file; decl_source_file 等)。其余的都初始化為0。tree copy_node (node)tree n
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 服裝店裝修發(fā)包合同
- 2025年度養(yǎng)豬場(chǎng)生物安全防控體系建設(shè)合同
- 2025年度勞動(dòng)合同到期解除協(xié)議書及離職員工離職證明及離職手續(xù)辦理指南
- 2025年度建筑勞務(wù)施工節(jié)能減排合作協(xié)議
- 2025年度分紅股收益分配與權(quán)益變更協(xié)議
- 2025年度數(shù)據(jù)保密審計(jì)與保密合同
- 2025年度公司免責(zé)的旅游服務(wù)合作協(xié)議
- 2025年度創(chuàng)業(yè)公司股權(quán)激勵(lì)及轉(zhuǎn)讓協(xié)議
- 2025年網(wǎng)絡(luò)游戲行業(yè)發(fā)展現(xiàn)狀分析:網(wǎng)絡(luò)游戲國(guó)內(nèi)用戶規(guī)模不斷擴(kuò)大
- 崗位晉升申請(qǐng)書
- 物業(yè)公司客戶服務(wù)課件
- 腦卒中患者的康復(fù)護(hù)理查房
- 酶工程技術(shù)在茶葉深加工中的應(yīng)用
- 大模型在教育科技中的應(yīng)用
- 人教版英語(yǔ)八年級(jí)下冊(cè)全冊(cè)教案教學(xué)設(shè)計(jì)及教學(xué)反思
- 02J401 鋼梯【含03年修改】圖集
- 烹飪概論教學(xué)大綱
- Android移動(dòng)應(yīng)用開發(fā)基礎(chǔ)教程-教案
- 腦梗合并心衰護(hù)理查房
- JGT472-2015 鋼纖維混凝土
- 第九屆鵬程杯五年級(jí)數(shù)學(xué)競(jìng)賽初試真題
評(píng)論
0/150
提交評(píng)論