版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、編譯原理課程設(shè)計報告課題名稱: C-詞法掃描器及語法分析器實現(xiàn) 提交文檔學(xué)生姓名: XXX 提交文檔學(xué)生學(xué)號: XXX 同組 成 員 名 單: 無 指導(dǎo) 教 師 姓 名: 張 兵 指導(dǎo)教師評閱成績: 指導(dǎo)教師評閱意見: . . 提交報告時間:2012年 6月 2日目錄1 課程設(shè)計目標32 分析與設(shè)計42.1 程序結(jié)構(gòu)42.2 程序流程53 詞法分析63.1 代碼結(jié)構(gòu)分析63.2 Token定義73.2.1 Token的定義和類型73.2.2 Token的種別碼73.3 DAF分析83.3.1 刪除注釋DFA83.3.2 詞法分析DFA104 語法分析144.1 代碼結(jié)構(gòu)分析144.2 節(jié)點定義
2、154.2.1 節(jié)點定義和類型154.2.2 各類型節(jié)點的描述164.3 遞歸向下語法分析164.3.1 C-文法164.3.2 遞歸向下分析過程175 測試結(jié)果345.1 流程345.2 詞法分析結(jié)果345.3 詞法分析出錯385.4 語法分析結(jié)果395.5 語法分析出錯416 總結(jié)426.1 詞法分析編寫過程426.2 語法分析編寫過程436.3 成果和收獲437 附錄447.1 scanner.h源文件447.2 scanner.cpp源文件457.3 parser.h源文件557.4 parser.cpp源文件56 1 課程設(shè)計目標學(xué)生在學(xué)習(xí)編譯原理課程過程中,結(jié)合各章節(jié)的構(gòu)造編譯程序
3、的基本理論,要求用C或C+語言描述及上機調(diào)試,實現(xiàn)一個 C-Minus 小編譯程序(包括詞法分析,語法分析等重要子程序),使學(xué)生將理論與實際應(yīng)用結(jié)合起來,受到軟件設(shè)計等開發(fā)過程的全面訓(xùn)練,從而提高學(xué)生軟件開發(fā)的能力。 要求:(1)設(shè)計詞法分析器設(shè)計各單詞的狀態(tài)轉(zhuǎn)換圖,并為不同的單詞設(shè)計種別碼。將詞法分析器設(shè)計成供語法分析器調(diào)用的子程序。功能包括:a. 具備預(yù)處理功能。將不翻譯的注釋等符號先濾掉,只保留要翻譯的符號串,即要求設(shè)計一個供詞法分析調(diào)用的預(yù)處理子程序;b. 能夠拼出語言中的各個單詞;c. 返回(種別碼, 屬性值)。(2)語法分析要求用學(xué)習(xí)過的自底向上或自頂向下的分析方法等,實現(xiàn)對表達式
4、、各種說明語句、控制語句進行語法分析。若語法正確,則用語法制導(dǎo)翻譯法進行語義翻譯;生成并打印出語法樹;若語法錯誤,要求指出出錯性質(zhì)和出錯位置(行號)。2 分析與設(shè)計2.1 程序結(jié)構(gòu)本節(jié)主要分析程序的代碼結(jié)構(gòu)和代碼工程文件的劃分。(程序由兩個類組成: Scanner類和Parser類,分別為詞法分析和語法分析類。工程分為四個文件:scanner.h、scanner.cpp、parser.h、parser.cpp,分別對應(yīng)Scanner類和Parser類的聲明和實現(xiàn)文件)。本程序采用C+語言以面向?qū)ο蟮乃枷刖帉?,程序分為兩部分:詞法分析(Scanner)和語法分析(Parser),分別將兩個處理階
5、段封裝成Scanner類和Parser類,兩個類各司其職,分別完成詞法分析和語法分析的任務(wù)。Scanner類主要的工作是過濾注釋、詞法分析獲取Token。Parser類的主要工作是根據(jù)Scanner類詞法分析之后的Token進行語法分析,生成語法樹,最后并輸出語法樹。在處理過程中,Scanner類的對象作為Parser類的一個成員變量,配合Parser類進行語法分析。工程文件總體上是按照兩個類的格局分為四個文件,分別是兩個類的聲明文件和實現(xiàn)文件。四個文件分別為scanner.h和scanner.cpp以及parser.h和parser.cpp,他們分別是Scanner類聲明文件、Scanner
6、類實現(xiàn)文件、Parser類聲明文件、Parser類實現(xiàn)文件。詞法分析scanner.h:與詞法分析相關(guān)的類(Scanner類)的聲明scanner.cpp:詞法分析階段類(Scanner類)的實現(xiàn)語法分析parser.h:與語法分析相關(guān)的類(Parser類)的聲明parser.cpp:語法分析階段類(Parser類)的實現(xiàn)2.2 程序流程在程序中,Scanner類的對象(scanner)作為Parser類中的一個成員變量,配合Parser類進行語法分析。它們的關(guān)系是這樣的:Parser類的一個成員變量scanner首先對源程序刪除注釋,然后進行詞法分析獲取所有Token,并將獲取的Token存
7、儲在scanner對象的tokenList(vector類型)中。然后Parser類的語法分析程序就根據(jù)tokenList中的Token進行語法分析,生成語法樹,最后打印語法樹。同時,這也是程序的流程。整體程序流程圖開始刪除注釋出錯詞法分析TF結(jié)束語法分析出錯出錯輸出出錯信息TFFT從文件獲取源代碼3 詞法分析3.1 代碼結(jié)構(gòu)分析詞法分析階段的代碼被封裝成一個類Scanner,scanner.h中主要是Scanner類的聲明代碼,scanner.cpp中主要是Scanner類的實現(xiàn)代碼。Scanner類對外提供的函數(shù)主要有:getSourseStringFromFile(string s)(從
8、文件中獲取待分析的源代碼)、deleteComments()(過濾注釋)、scan()(詞法分析主程序)。詞法分析的過程主要是:l Scanner調(diào)用getSourseStringFromFile(string s),從文件中獲取待分析的源代碼l Scanner調(diào)用deleteComments(),將注釋過濾掉,如果注釋出錯,則不進行詞法分析l Scanner調(diào)用scan(),進行詞法分析,將分析得到的所有Token保存在Scanner類的成員變量tokenList中,以備語法階段調(diào)用,并將Token輸出到文件Token.txt中以上三個函數(shù)構(gòu)成了詞法分析的骨架,在Scanner類中還有其他成
9、員變量和函數(shù),主要作為這三個函數(shù)處理過程的中間步驟,為這三個函數(shù)服務(wù)。Scanner類的代碼結(jié)構(gòu)和主要的成員變量和函數(shù)如下圖所示:其他函數(shù)和成員變量的作用和含義:l void backToLastChar():在詞法分析過程中,回退一個字符l DFAState charType(char):返回字符的類型(按狀態(tài)分),如white space返回START,0-9返回NUMl char getNextChar():獲取到下一個字符l Token getTokenAt(int):根據(jù)下標從tokenList數(shù)組中獲取詞法分析后所保存的Token(供語法分析階段調(diào)用)l void printTok
10、en():將詞法分析好的Token輸出到文件Token.txt中l(wèi) TokenType returnTokenType(string s):根據(jù)字符串返回對應(yīng)的31種Token類型,如字符串int將返回INT, var將返回IDl int charIndex:配合getNextChar()和backToLastChar()使用(分別自增和自減1),用以指示當前待分析的char在源代碼中的位置l bool commentFlag:標注注釋開始的標志,為true時表示正在注釋體內(nèi),即源代碼進入/*之后且*/之前的狀態(tài)l int lineCount:對行號計數(shù),表示當前詞法分析在源代碼的行位置(每次
11、獲取到的char為/n就自增1)l bool scanSuccess:詞法分析是否成功的標志l string sourseString:獲取源代碼的字符串l string str:在分析過程中保存Token對應(yīng)的串l vector tokenList:保存Token序列3.2 Token定義3.2.1 Token的定義和類型Token定義:/定義的Token結(jié)構(gòu)體,包括類型、對應(yīng)的串、所在代碼的行號struct TokenTokenType tokenType;string tokenString;int lineNo;Token類型(TokenType):程序中,將Token的類型分為31種
12、,分別對應(yīng)于else、if、int、return、void、while、+、-、*、/、=、=、!=、=、;、,、(、)、/*、*/、num、id、錯誤、文件結(jié)束,TokenType的定義和種別碼分別如下所示:/定義的Token的類型(31種),分別對應(yīng)于else、if、int、return、void、while、+、-、*、/、=、=、!=、=、;、,、(、)、/*、*/、num、id、錯誤、結(jié)束typedef enumELSE = 1,IF,INT,RETURN,VOID,WHILE,PLUS,MINUS,TIMES,OVER,LT,LEQ,GT,GEQ,EQ,NEQ,ASSIGN,SEM
13、I,COMMA,LPAREN,RPAREN,LMBRACKET, RMBRACKET,LBBRACKET,RBBRACKET,LCOMMENT,RCOMMENT,NUM,ID,ERROR,ENDFILE TokenType;3.2.2 Token的種別碼TokenType的種別碼如下表所示,共31種單詞符號種別碼Value單詞符號種別碼ValueelseELSE1=ASSIGN17ifIF2;SEMI18intINT3,COMMA19returnRETURN4(LPAREN20voidVOID5)RPAREN21whileWHILE6LMBRACKET22+PLUS7RMBRACKET23-M
14、INUS8LBBRACKET24*TIMES9RBBRACKET25/OVER10/*LCOMMENT26LT11*/RCOMMENT27GT13idID29=GEQ14錯誤ERROR30=EQ15結(jié)束ENDFILE31!=NEQ163.3 DAF分析由于詞法分析程序分為兩個步驟處理:刪除注釋和詞法分析獲取Token。所以對應(yīng)有兩個DFA,程序分別根據(jù)這兩個DFA進行編寫,現(xiàn)根據(jù)DFA分析兩程序deleteComments()和scan()如下:3.3.1 刪除注釋DFA刪除注釋的DFA描述:刪除注釋的DFA如下所示,一共分為5個狀態(tài),在開始狀態(tài)1時,如果輸入的字符為/,則進入狀態(tài)2,此時有可
15、能進入注釋狀態(tài),如果在狀態(tài)2時,輸入的字符為*,則進入注釋狀態(tài),狀態(tài)將轉(zhuǎn)到3,如果在狀態(tài)3時,輸入的字符為*,則有可能結(jié)束注釋狀態(tài),此時狀態(tài)將轉(zhuǎn)到狀態(tài)4,如果在狀態(tài)4時輸入的字符為/,則注釋狀態(tài)結(jié)束,狀態(tài)轉(zhuǎn)移到結(jié)束狀態(tài)。對應(yīng)的DFA的代碼分析:刪除注釋的功能通過Scanner 類的成員函數(shù)deleteComments()實現(xiàn),功能是將源代碼中的注釋過濾掉,將其余代碼輸出到sourceFile.txt文件中。deleteComments()函數(shù)按照上面的DFA編寫,在函數(shù)中,state變量表示狀態(tài),共分為5個狀態(tài):l 在狀態(tài)1時,如果輸入的字符為/,則進入狀態(tài)2,否則仍處在狀態(tài)1,且輸出輸入的字
16、符l 在狀態(tài)2時,(此時可能進入注釋狀態(tài)),如果輸入的字符為*,則進入注釋狀態(tài),狀態(tài)將轉(zhuǎn)到3,否則跳轉(zhuǎn)到狀態(tài)1,并輸出/和輸入的字符l 在狀態(tài)3時,(此時可能結(jié)束注釋狀態(tài)),如果輸入的字符為*,此時狀態(tài)將轉(zhuǎn)到狀態(tài)4,否則繼續(xù)在狀態(tài)3l 在狀態(tài)4時,如果輸入的字符為/,則注釋狀態(tài)結(jié)束,狀態(tài)轉(zhuǎn)移到結(jié)束狀態(tài)相應(yīng)的DFA代碼:代碼如下所示:void Scanner : deleteComments()ofstream fout_Sourse(sourseFile.txt);int state = 1;char ch;while(state6)ch = getNextChar();if(0=ch)/文件
17、結(jié)束break;if(1=state)/DFA中的狀態(tài)if(/=ch)state = 2;elsestate = 1;fout_Soursech;else if(2=state)/DFA中的狀態(tài)if(*=ch)state = 3;commentFlag = false; elsestate = 1;fout_Sourse/ch;else if(3=state)/DFA中的狀態(tài)if(*=ch)state = 4;elsestate = 3;else if(4=state)/DFA中的狀態(tài)if(*=ch)state = 4;else if(/=ch)state = 5;elsestate = 3;
18、if(5=state)/結(jié)束狀態(tài),處理commentFlag = true;state = 1;if(!commentFlag)cout注釋錯誤,沒有結(jié)束符!endl;scanSuccess = false;3.3.2 詞法分析DFA詞法分析的DFA描述:詞法分析的DFA如下所示,一共分為5個狀態(tài):START、INNUM、INID、INDBSYM、DONE。狀態(tài)START表示開始狀態(tài),狀態(tài)INNUM表示數(shù)字類型(NUM)Token的狀態(tài),狀態(tài)INID表示字符串類型Token的狀態(tài)(如關(guān)鍵字和一般的標示符),狀態(tài)INDBSYM表示雙目運算符型Token的狀態(tài)(如=、!=、=),狀態(tài)DONE表示接
19、收狀態(tài)。l 在開始狀態(tài)START時 如果輸入的字符為空白符,如空格換行等,則仍在START狀態(tài) 如果輸入的字符為digit,則進入狀態(tài)INNUM,即可能是數(shù)字類型(NUM)Token的狀態(tài) 如果輸入的字符為letter,則進入狀態(tài)INID,即可能是字符串類型Token的狀態(tài) 如果輸入的字符為、!、=,則進入狀態(tài)INDBSYM,即可能是雙目運算符型Token的狀態(tài),同時將ch添加到str中去(str += ch) 如果輸入的字符為是除以上之外的,則進入狀態(tài)DONE,同時將ch添加到str中去(str += ch),這次輸入的字符可能是單目運算符、錯誤等l 在狀態(tài)INNUM時 如果輸入的字符為di
20、git,則仍停留在INNUM狀態(tài),同時將ch添加到str中去(str += ch) 如果輸入的為其他的字符,則轉(zhuǎn)到DONE狀態(tài)l 在狀態(tài)INID時 如果輸入的字符為letter,則仍停留在INID狀態(tài),同時將ch添加到str中去(str += ch) 如果輸入的為其他的字符,則轉(zhuǎn)到DONE狀態(tài)l 在狀態(tài)INDBSYM時 如果輸入的字符為=,將雙目運算標志賦值為true后轉(zhuǎn)到DONE狀態(tài),同時將ch添加到str中去(str += ch),并將doubleSym 賦值為true(doubleSym = true),表示ch為= 如果輸入的為其他的字符,則直接轉(zhuǎn)到DONE狀態(tài)l 在狀態(tài)DONE時接受
21、狀態(tài),根據(jù)分析過程中獲取的字符串確定Token的類型,并生成和保存相應(yīng)的Token,同時將str設(shè)為空,(以便分析下一個Token)。在DFA中,other表示ch沒有被添加到str中后的轉(zhuǎn)移,所以當狀態(tài)是通過條件other跳轉(zhuǎn)到DONE狀態(tài)的情況時,則需將分析的字符回退回去(backToLastChar())。相應(yīng)的DFA代碼:代碼如下:void Scanner : scan()bool doubleSym = false;getSourseStringFromFile(sourseFile.txt);int state = START;lineCount = 0;char ch;/每一次循
22、環(huán)都執(zhí)行一次DFA,并獲取到一個Tokenwhile(state6)ch = getNextChar();if(0=ch)/到達文件末尾,文件結(jié)束Token t;t.lineNo = lineCount;t.tokenString = ;t.tokenType = ENDFILE;tokenList.push_back(t);break;if(START=state)/初始狀態(tài)和空格state = charType(ch);if(state!=START)str += ch;else if(INNUM=state)/digitstate = charType(ch);if(state!=INN
23、UM)state = DONE;elsestr += ch;else if(INID=state)/letterstate = charType(ch);if(state!=INID)state = DONE;elsestr += ch;else if(INDBSYM=state)/除了=!之外的各種符號if(=ch)str += ch;doubleSym = true;elsedoubleSym = false;state = DONE;if(DONE=state)/接收狀態(tài)int tp = 0;if(n=ch)tp = 1;/根據(jù)str生成TokenToken t;t.lineNo = l
24、ineCount-tp;t.tokenString = str;t.tokenType = returnTokenType(str);tokenList.push_back(t);if(ERROR=t.tokenType)scanSuccess = false;/針對other的情形,回退一個字符int lastState = charType(strstr.length()-1);if(lastState=INNUM | lastState=INID | (lastState=INDBSYM & doubleSym=false)backToLastChar();str = ;state =
25、START;if(doubleSym=true)doubleSym = false; printToken();/輸出Token到文件Token.txt中4 語法分析4.1 代碼結(jié)構(gòu)分析語法分析階段的代碼被封裝成一個類Parser,parser.h中主要是Parser類的聲明代碼,parser.cpp中主要是Parser類的實現(xiàn)代碼。語法分析的過程主要是:在語法分析之前進行詞法分析,然后通過遞歸向下分析法根據(jù)C-語言的文法進行語法分析,并生成語法樹,最后打印語法樹。Parser類在其構(gòu)造函數(shù)中完成語法分析,在構(gòu)造函數(shù)Parser()中,首先通過Parser類的scanner成員變量進行詞法分析
26、(刪除注釋、詞法分析獲取Token),然后通過parse()函數(shù)開始遞歸向下分析,并返回語法樹的根節(jié)點,最后通過printTree()打印語法樹,輸出到文件tokenTree.txt中。Parser類的代碼結(jié)構(gòu)和主要的成員變量和函數(shù)如下圖所示: 成員函數(shù)和變量的作用和含義:l Token getToken():獲取保存在scanner中TokenList數(shù)組中的Token,每次獲取完之后數(shù)組下標指向下一個l void printSpace(int n):打印n個空格l void syntaxError(string s):報錯的函數(shù),報告出錯位置(行號)、出錯位置附近的Tokenl void
27、match(TokenType ex):與目標Token類型ex匹配,如果匹配成功則獲取下一個Token(為currentToken賦值),否則報錯l void printTree(TreeNode * t):打印生成的語法樹l TreeNode * newNode(Nodekind k):根據(jù)節(jié)點類型新建節(jié)點l 以下為遞歸向下分析文法過程中各階段的分析函數(shù):TreeNode * declaration_list(void);TreeNode * declaration(void);TreeNode * params(void);TreeNode * param_list(TreeNode *
28、 k);TreeNode * param(TreeNode * k);TreeNode * compound_stmt(void);TreeNode * local_declaration(void);TreeNode * statement_list(void);TreeNode * statement(void);TreeNode * expression_stmt(void);TreeNode * selection_stmt(void);TreeNode * iteration_stmt(void);TreeNode * return_stmt(void);TreeNode * exp
29、ression(void);TreeNode * var(void);TreeNode * simple_expression(TreeNode * k);TreeNode * additive_expression(TreeNode * k);TreeNode * term(TreeNode * k);TreeNode * factor(TreeNode * k);TreeNode * call(TreeNode * k);TreeNode * args(void);l Scanner scanner:詞法分析的Scanner類對象,用于語法分析前進行詞法分析處理l Token curren
30、tToken:當前獲取的Tokenl Token lastToken:前一個Tokenl int tokenIndex:配合getToken使用,每獲取一次,tokenIndex自增1l bool Error:語法分析是否出錯l int step:用于printTree()函數(shù)節(jié)點輸出時表征節(jié)點的先行空格4.2 節(jié)點定義4.2.1 節(jié)點定義和類型節(jié)點定義:/treeNode定義 包括子節(jié)點、兄弟節(jié)點、所處行號、節(jié)點類型、屬性、表達式返回類型typedef struct treeNodestruct treeNode * childMAXCHILDREN;struct treeNode * si
31、bling;int lineno; Nodekind nodekind;union TokenType op; int val; const char * name; attr; ExpType type; TreeNode;節(jié)點類型:在程序處理過程中,主要對語法樹定義了19種節(jié)點,分別為IntK, IdK, VoidK, ConstK, Var_DeclK, Arry_DeclK, FunK, ParamsK, ParamK, CompK, Selection_StmtK, Iteration_StmtK, Return_StmtK, AssignK, OpK, Arry_ElemK, Ca
32、llK, ArgsK, UnkownK,分別表示int、id、void、數(shù)值、變量聲明、數(shù)組聲明、函數(shù)聲明、函數(shù)聲明參數(shù)列表、函數(shù)聲明參數(shù)、復(fù)合語句體、if、while、return、賦值、運算、數(shù)組元素、函數(shù)調(diào)用、函數(shù)調(diào)用參數(shù)列表、未知節(jié)點。/19種節(jié)點類型,分別表示int、id、void、數(shù)值、變量聲明、數(shù)組聲明、函數(shù)聲明、函數(shù)聲明參數(shù)列表、函數(shù)聲明參數(shù)、復(fù)合語句體、if、while、return、賦值、運算、數(shù)組元素、函數(shù)調(diào)用、函數(shù)調(diào)用參數(shù)列表、未知節(jié)點typedef enum IntK, IdK, VoidK, ConstK, Var_DeclK, Arry_DeclK, FunK,
33、ParamsK, ParamK, CompK, Selection_StmtK, Iteration_StmtK, Return_StmtK, AssignK, OpK, Arry_ElemK, CallK, ArgsK, UnkownK Nodekind;4.2.2 各類型節(jié)點的描述節(jié)點類型描述子節(jié)點組成IntK變量或返回值類型(int)無VoidK變量或返回值類型(void)無IdK標示符(id)無ConstK數(shù)值無Var_DeclK變量聲明變量類型+變量名Var_DeclK數(shù)組聲明數(shù)組名+數(shù)組大小FunK函數(shù)聲明返回類型+函數(shù)名+參數(shù)列表+函數(shù)體ParamsKFunK的參數(shù)列表參數(shù)(如果
34、有多個參數(shù),則之間為兄弟節(jié)點)ParamKFunK的參數(shù)參數(shù)類型+參數(shù)名CompK復(fù)合語句體變量聲明列表+語句列表Selection_StmtKif條件表達式+IF體+ELSE體Iteration_StmtKwhile條件表達式+循環(huán)體Return_StmtKreturn表達式AssignK賦值被賦值變量+賦值變量OpK運算運算符左值+運算符右值A(chǔ)rry_ElemK數(shù)組元素數(shù)組名+下標CallK函數(shù)調(diào)用函數(shù)名+參數(shù)列表ArgsKCallK的參數(shù)列表表達式(如果有多個表達式,則之間為兄弟節(jié)點)UnkownK未知節(jié)點無4.3 遞歸向下語法分析4.3.1 C-文法已通過使用EBNF的方式消除左遞歸:
35、programdeclaration-listdeclaration_list declaration declaration declarationvar-declaration|fun-declarationvar_declaration type-specifier ID; | type-specifier ID NUM;type - specifier int | voidfun-declatationtype-specifier ID (params) | compound-stmtparamsparam_list | voidparam_listparam, paramparam
36、type-specifier ID compound-stmt local-declaration statement-listlocal-declarations empty var- declarationstatement-liststatementstatementexpression-stmt | compound-stmt | selection-stmt | iteration-stmt | return-stmtexpression-stmt expression;selection-stmtif (expression) statement else statementite
37、ration-stmtwhile (expression)statementreturn-stmtreturn expression;expression var = expression | simple-expressionrelop = | | = | = = | ! =varID | ID expressionsimple-expressionadditive-expression relop additive-expression additive-expressiontermaddop term addop + | -termfactormulop factor mulop * |
38、 /factor(expression) | var | call | NUMcallID( args )argsarg-list | emptyarg-list expression, expression4.3.2 遞歸向下分析過程以下表格列出了根據(jù)上文中的C-文法使用遞歸向下分析方法分析程序的過程,待分析文法中列出的是將要分析的若干文法,分析函數(shù)是程序針對該文法編寫的分析函數(shù),用以分析該文法,分析是對該文法的分析過程以及分析函數(shù)的編寫思想,代碼是分析函數(shù)用C+語言的實現(xiàn),各文法分析過程如下:待分析文法programdeclaration-list分析函數(shù)TreeNode * parse(
39、void)分析說明C-語言編寫的程序由一組聲名序列組成。parse(void)函數(shù)使用遞歸向下分析方法直接調(diào)用declaration_list()函數(shù),并返回樹節(jié)點代碼TreeNode * Parser : parse(void)TreeNode * t;currentToken = getToken();lastToken = currentToken;t = declaration_list();if(currentToken.tokenType!=ENDFILE) syntaxError(結(jié)束錯誤);return t;待分析文法declaration_list declaration d
40、eclaration 分析函數(shù)TreeNode * declaration_list(void)分析說明C-語言編寫的程序由一組聲名序列組成。declaration_list(void)函數(shù)使用遞歸向下分析方法直接調(diào)用declaration()函數(shù),并返回樹節(jié)點代碼TreeNode * Parser : declaration_list() TreeNode * t = declaration();TreeNode * p = t;/在開始語法分析出錯的情況下找到int和void型,過濾掉int和void之前的所有Token,防止在開始時出錯后面一錯百錯while(currentToken.t
41、okenType!=INT)&(currentToken.tokenType!=VOID)&(currentToken.tokenType!=ENDFILE) syntaxError();getToken();if(currentToken.tokenType=ENDFILE)break;/尋找語法分析的入口,即找到int和voidwhile(currentToken.tokenType=INT)|(currentToken.tokenType=VOID) TreeNode * q;q = declaration();if(q!=NULL)if(t=NULL) t = p = q;else p
42、-sibling = q;p = q;match(ENDFILE);return t;待分析文法declarationvar-declaration|fun-declarationvar_declaration type-specifier ID; | type-specifier ID NUM;fun-declatationtype-specifier ID (params) | compound-stmttype - specifier int | void分析函數(shù)TreeNode * declaration(void)分析說明C-語言的聲明分為變量聲明和函數(shù)聲明。declaration(
43、void)函數(shù)并不是直接調(diào)用var-declaration或fun-declaration文法所對應(yīng)的函數(shù),令其返回節(jié)點,實際上程序并沒有為var-declaration和fun-declaration文法定義函數(shù),而是在declaration(void)函數(shù)中,通過求First集合的方式先確定是變量定義還是函數(shù)定義,然后分別根據(jù)探測的結(jié)果生成變量聲明節(jié)點(Var_DeclK)或函數(shù)聲明節(jié)點(FunK)。所以var-declaration和fun-declaration文法在declarationvar-declaration|fun-declaration文法中就都已經(jīng)分析了代碼TreeNo
44、de * Parser : declaration(void)TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;TreeNode * s = NULL;if(currentToken.tokenType=INT) p = newNode(IntK);match(INT);else if(currentToken.tokenType=VOID) p = newNode(VoidK);match(VOID);elsesyntaxError(類型匹配錯誤);if(p!=NULL)&(currentToken.tokenType=I
45、D) q = newNode(IdK); = currentToken.tokenString.c_str();match(ID);if(currentToken.tokenType=LPAREN)/(:函數(shù)情況 t = newNode(FunK);t-child0 = p;t-child1 = q;match(LPAREN);t-child2 = params();match(RPAREN);t-child3 = compound_stmt();else if(currentToken.tokenType=LMBRACKET)/:數(shù)組聲明 t = newNode(Va
46、r_DeclK);TreeNode * m = newNode(Arry_DeclK);match(LMBRACKET);match(NUM);s = newNode(ConstK);s-attr.val = atoi(lastToken.tokenString.c_str();m-child0 = q;m-child1 = s;t-child0 = p;t-child1 = m;match(RMBRACKET);match(SEMI);else if(currentToken.tokenType=SEMI)/;結(jié)尾:普通變量聲明t = newNode(Var_DeclK);t-child0
47、= p;t-child1 = q;match(SEMI);else syntaxError(); else syntaxError();return t;待分析文法paramsparam_list | void分析函數(shù)TreeNode * params(void)分析說明函數(shù)參數(shù)列表要么是void,要么是多個參數(shù)組成。params(void)函數(shù)先判斷第一個是void還是int,如果是int說明是由param_list組成,則調(diào)用param_list(TreeNode * k)函數(shù)遞歸向下分析;如果是void說明可能是void型的參數(shù),也可能參數(shù)就是void,所以再求其Follow集合,如果集合求出來是右括號,則說明參數(shù)就是void,于
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 某著名企業(yè)全面診斷咨詢項目文件規(guī)范0613
- 某著名企業(yè)績效管理咨詢中期匯報0718
- 《GBT 9738-2008化學(xué)試劑 水不溶物測定通 用方法》專題研究報告
- 《GBT 21458-2008流動式起重機 額定起重量圖表》專題研究報告
- 《GBT 14270-2008毛絨纖維類型含量試驗方法》專題研究報告
- 道路養(yǎng)護員實操培訓(xùn)課件
- 2026年廣東省惠州市高職單招數(shù)學(xué)考試題庫(含答案)
- 《美國胸外科協(xié)會磨玻璃結(jié)節(jié)管理專家共識2023》解讀
- 車險續(xù)保知識
- 內(nèi)蒙古對口招生語文模擬試題(一)帶答案
- 床-輪椅轉(zhuǎn)移操作質(zhì)量及評分標準
- DL-T976-2017帶電作業(yè)工具、裝置和設(shè)備預(yù)防性試驗規(guī)程
- DB32T3916-2020建筑地基基礎(chǔ)檢測規(guī)程
- 2024年青海海南州消防救援支隊消防文員招聘筆試參考題庫附帶答案詳解
- 2022版《義務(wù)教育教學(xué)新課程標準》解讀課件
- 期末水平綜合練習(xí)(試題)新思維小學(xué)英語一年級上冊
- 初中語文 送別詩練習(xí)題(含答案)
- 人教A版高中數(shù)學(xué)選擇性必修第二冊全冊各章節(jié)課時練習(xí)題含答案解析(第四章數(shù)列、第五章一元函數(shù)的導(dǎo)數(shù)及其應(yīng)用)
- 六年級下冊小升初全復(fù)習(xí)-第12講 工程問題-北師大 (含答案)
- 烹飪原料知識 水產(chǎn)品蝦蟹類
- 考勤抽查記錄表
評論
0/150
提交評論