C語言詞法分析器和C語言語法分析器編譯原理課程設(shè)計(jì)_第1頁
C語言詞法分析器和C語言語法分析器編譯原理課程設(shè)計(jì)_第2頁
C語言詞法分析器和C語言語法分析器編譯原理課程設(shè)計(jì)_第3頁
C語言詞法分析器和C語言語法分析器編譯原理課程設(shè)計(jì)_第4頁
C語言詞法分析器和C語言語法分析器編譯原理課程設(shè)計(jì)_第5頁
已閱讀5頁,還剩56頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、精選優(yōu)質(zhì)文檔-傾情為你奉上編譯原理課程設(shè)計(jì)課程報(bào)告題目 C語言詞法分析器和C-語言語法分析器 學(xué)生姓名 學(xué)生學(xué)號(hào) 指導(dǎo)教師 提交報(bào)告時(shí)間 2019 年 6 月 8 日C語言詞法分析器1 實(shí)驗(yàn)?zāi)康募耙饬x1. 熟悉C語言詞法2. 掌握構(gòu)造DFA的過程3. 掌握利用DFA實(shí)現(xiàn)C語言的詞法分析器4. 理解編譯器詞法分析的工作原理2 詞法特點(diǎn)及正則表達(dá)式2.1詞法特點(diǎn)2.1.1 保留字AUTO, BREAK , CASE , CHAR , CONST , CONTINUE , DEFAULT , DO , DOUBLE , ELSE, ENUM , EXTERN , FLOAT , FOR , GOTO

2、, IF , INT , LONG , REGISTER , RETURN, SHORT , SIGNED , SIZEOF , STATIC , STRUCT , SWITCH , TYPEDEF , UNION , UNSIGNED , VOID, VOLATILE , WHILE,2.1.2 符號(hào) + - * / + - += -= *= < <= > >= = != = ; , ( ) /* */ : 2.2 正則表達(dá)式 whitespace = (newline|blank|tab|comment)+ digit=0|.|9 nat=digit+ signed

3、Nat=(+|-)?nat NUM=signedNat(“.”nat)? letter = a|.|z|A|.|Z ID = letter(letter|digit|“_”)+ CHAR = 'other+' STRING = “other+”3 Token定義3.1 token類型保留字auto break case char const continue default do double elseenum extern float for gotoif int long redisterreturnshort signed sizeof static struct swi

4、tch typedef union unsignedvoid volatile while特殊符號(hào)+ - * / + - += -= *= < <= > >= = != = ; , ( ) /* */ :文件結(jié)束、錯(cuò)誤EOF ERROR其它tokenNUM ID CHARACTER STRINGtypedef enum /錯(cuò)誤、結(jié)束 ENDFILE,ERROR, /保留字 AUTO,BREAK,CASE,CHAR,CONST,CONTINUE ,DEFAULT , DO ,DOUBLE, ELSE, ENUM, EXTERN , FLOAT ,FOR , GOTO,IF

5、, INT, LONG,REGISTER , RETURN, SHORT, SIGNED ,SIZEOF ,STATIC, STRUCT ,SWITCH, TYPEDEF ,UNION, UNSIGNED , VOID,VOLATILE , WHILE, /其他token ID,NUM,CHARACTER,STRING,/特殊符號(hào) /+、-、*、/、+、-、+=、-=、*=、<、<=、>、>=、=、!=、=、;、,、(、)、/、/*、*/、:PLUS,MINUS,TIMES,OVER,SELFPLUS,SELFMINUS,PLUSASSIGN,MINUSASSIGN,T

6、IMESASSIGN,LT,LEQ,GT,GEQ,EQ,NEQ,ASSIGN,SEMI,COMMA,LPAREN, MINUSASSIGN,TIMESASSIGN,LT,LEQ,GT,GEQ,EQ,NEQ,ASSIGN,SEMI,COMMA,LPAREN, RPAREN,LBRACKET,RBRACKET, LCBRACKET,RCBRACKET,LCOMMENT,RCOMMENT,COLON TokenType;3.2 tokenType類型代碼4 DFA設(shè)計(jì)4.1 注釋的DFA設(shè)計(jì)注釋的DFA如下所示,一共分為5個(gè)狀態(tài),在開始狀態(tài)1時(shí),如果輸入的字符為/,則進(jìn)入狀態(tài)2,此時(shí)有可能進(jìn)入注釋狀

7、態(tài),如果在狀態(tài)2時(shí),輸入的字符為*,則進(jìn)入注釋狀態(tài),狀態(tài)將轉(zhuǎn)到3,如果在狀態(tài)3時(shí),輸入的字符為*,則有可能結(jié)束注釋狀態(tài),此時(shí)狀態(tài)將轉(zhuǎn)到狀態(tài)4,如果在狀態(tài)4時(shí)輸入的字符為/,則注釋狀態(tài)結(jié)束,狀態(tài)轉(zhuǎn)移到結(jié)束狀態(tài)。4.2 詞法分析的DFA設(shè)計(jì)詞法分析的DFA如下所示,一共分為10個(gè)狀態(tài):START、INNUM、INNUM1、INNUM2、INID、INCOMPARE、INOPERATE、INSTRING、INCHAR、DONE。狀態(tài)START表示開始狀態(tài),狀態(tài)INNUM,INNUM1,INNUM2表示數(shù)字類型(NUM)Token的狀態(tài),狀態(tài)INID表示標(biāo)示符(ID)類型Token的狀態(tài),狀態(tài)INOP

8、ERATE表示算數(shù)運(yùn)算符型Token的狀態(tài),狀態(tài)INOCOMPARE表示比較運(yùn)算符型Token的狀態(tài),INSTRING表示字符串(STRING)類型Token的狀態(tài),INCHAR表示字符(CHARACTER)類型Token的狀態(tài),狀態(tài)DONE表示接收狀態(tài)。l 在開始狀態(tài)START時(shí)Ø 如果輸入的字符為空白符,如空格換行等,則仍在START狀態(tài)Ø 如果輸入的字符為digit,則進(jìn)入狀態(tài)INNUM,即可能是數(shù)字類型(NUM)Token的狀態(tài)Ø 如果輸入的字符為letter,則進(jìn)入狀態(tài)INID,即可能是標(biāo)識(shí)符類型Token的狀態(tài)Ø 如果輸入的字符為>、&

9、lt;、!、=,則進(jìn)入狀態(tài)INCOMPARE,即可能是比較運(yùn)算符型Token的狀態(tài)Ø 如果輸入的字符為+、*、/,則進(jìn)入狀態(tài)INOPERATE,即可能是算數(shù)運(yùn)算符類型Token的狀態(tài)Ø 如果輸入的字符為,則進(jìn)入狀態(tài)INCHAR,即可能是字符類型Token的狀態(tài)Ø 如果輸入的字符為“,則進(jìn)入狀態(tài)INSTRING,即可能是字符串類型Token的狀態(tài)Ø 如果輸入的字符為是除以上之外的,則進(jìn)入狀態(tài)DONE,這次輸入的字符可能是單目運(yùn)算符、錯(cuò)誤等l 在狀態(tài)INNUM時(shí)Ø 如果輸入的字符為digit,則仍停留在INNUM狀態(tài)Ø 如果輸入的字符為”

10、.”,則轉(zhuǎn)到INNUM1狀態(tài)l 在狀態(tài)INNUM1時(shí)Ø 如果輸入的字符為digit,則進(jìn)入INNUM2狀態(tài)l 在狀態(tài)INNUM2時(shí)l 如果輸入的為其他的字符,則轉(zhuǎn)到DONE狀態(tài)Ø 如果輸入字符為digit,則停留在INNUM2狀態(tài)Ø 如果輸入的為其他字符,則轉(zhuǎn)到DONE狀態(tài)l 在狀態(tài)INID時(shí)Ø 如果輸入的字符為letter或“_”或digit,則仍停留在INID狀態(tài)Ø 如果輸入的為其他的字符,則轉(zhuǎn)到DONE狀態(tài)l 在狀態(tài)INCOMPARE時(shí)Ø 如果輸入的字符為=,則轉(zhuǎn)到DONE狀態(tài)Ø 如果輸入的為其他的字符,則直接轉(zhuǎn)到DO

11、NE狀態(tài)l 在狀態(tài)INOPERATE時(shí)Ø 如果輸入的字符為=,轉(zhuǎn)到DONE狀態(tài)Ø 如果輸入的為其他的字符,則直接轉(zhuǎn)到DONE狀態(tài)l 在狀態(tài)INCOMPARE時(shí)Ø 如果輸入的字符為=,則轉(zhuǎn)到DONE狀態(tài)Ø 如果輸入的為其他的字符,則直接轉(zhuǎn)到DONE狀態(tài)l 在狀態(tài)INCHAR時(shí)Ø 如果輸入為單引號(hào),則轉(zhuǎn)到DONE狀態(tài)Ø 如果輸入的為其他字符,則停留在INCHAR狀態(tài)l 在狀態(tài)INSTRING時(shí)Ø 如果輸入為雙引號(hào),則轉(zhuǎn)到DONE狀態(tài)Ø 如果輸入的為其他字符,則停留在INSTRING狀態(tài)l 在狀態(tài)DONE時(shí)接受狀態(tài),根據(jù)

12、分析過程中獲取的字符串確定Token的類型,并生成和保存相應(yīng)的Token5 代碼結(jié)構(gòu)分析5.1主要結(jié)構(gòu)詞法分析部分的代碼在scan.c和scan.h文件中,全局變量以及公共函數(shù)代碼在global.h以及util.h和util.c文件中。主函數(shù)中進(jìn)行文件打開和關(guān)閉,并調(diào)用scan.c中的getToken()函數(shù)對(duì)源文件進(jìn)行詞法分析。5.2 函數(shù)和成員變量的作用和含義void printToken(TokenType,const char*); /*輸出token */char* copyString(char *); /* 字符串復(fù)制 */TokenType getToken(void); /*

13、 詞法分析函數(shù)*/static int getNextChar(void) /* 獲取下一個(gè)字符 */static void ungetNextChar(void) /* 退回一個(gè)字符 */static TokenType reservedLookup (char * s) /* 查找對(duì)應(yīng)的保留字*/char tokenStringMAXTOKENLEN+1; /* token字符串*/int lineno = 0; /* 當(dāng)前行號(hào) */static char lineBufBUFLEN; /* 整行代碼緩沖區(qū) */ static int linepos = 0; /* 當(dāng)前行的位置*/ st

14、atic int bufsize = 0; /* 緩沖區(qū)大小*/static int EOF_flag = FALSE; /* 文件結(jié)束標(biāo)志 */6 實(shí)驗(yàn)結(jié)果與分析6.1 測(cè)試文件test.c/*test.c*/int main(void)# int a = 0; float b = 20.1; char c = "abcdefg" char d = 'h' if(a>=2) b+=0.1 a+; 6.2 測(cè)試結(jié)果6.3結(jié)果分析test.c文件中包括注釋,保留字,整數(shù)和小數(shù),標(biāo)識(shí)符,特殊符號(hào),字符串以及錯(cuò)誤輸入。本程序成功對(duì)test.c文件進(jìn)行了詞法分

15、析,對(duì)注釋進(jìn)行了忽略,輸出了相應(yīng)的行號(hào)、類型、取值,對(duì)于錯(cuò)誤的輸入顯示ERROR。7 小結(jié)通過編寫C語言詞法分析器,我對(duì)編譯器的基本原理有了更深的認(rèn)識(shí),同時(shí)掌握了DFA的設(shè)計(jì)與實(shí)現(xiàn)。在最開始的編寫過程中,我總是把詞法和語法分析混淆,比如一些錯(cuò)誤應(yīng)該在語法分析中判斷,我卻寫進(jìn)了詞法分析中,后來我逐步認(rèn)識(shí)到詞法分析的作用就是提取源代碼中的Token。在DFA的實(shí)現(xiàn)過程中,我主要參考了書后tiny語言DFA的實(shí)現(xiàn)方法,將它擴(kuò)展到C語言。另外C語言詞法比較復(fù)雜,因?yàn)闀r(shí)間關(guān)系我省略了一些,比如位運(yùn)算符,轉(zhuǎn)義字符等等,希望今后能完善。C-語言語法分析器1 實(shí)驗(yàn)?zāi)康募耙饬x用C語言編制Tiny/C-語言的語法

16、分析程序,實(shí)現(xiàn)對(duì)詞法分析程序所提供的Token序列的語法檢查和結(jié)構(gòu)分析。 2 文法規(guī)則(EBNF)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-stmtpa

17、ramsparam_list | voidparam_listparam, paramparam 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;selectio

18、n-stmtif (expression) statement else statementiteration-stmtwhile (expression)statementreturn-stmtreturn expression;expression var = expression | simple-expressionrelop < = | < | > | > = | = = | ! =varID | ID expressionsimple-expression>additive-expression relop additive-expression ad

19、ditive-expressiontermaddop term addop + | -termfactormulop factor mulop * | /factor(expression) | var | call | NUMcallID( args )argsarg-list | emptyarg-list expression, expression3 節(jié)點(diǎn)類型及定義3.1節(jié)點(diǎn)類型節(jié)點(diǎn)類型描述子節(jié)點(diǎn)IntKInt型變量或返回值無VoidKvoid型變量或返回值無IdK標(biāo)示符id無ConstK數(shù)值無Var_DeclK變量聲明變量類型+變量名Var_DeclK數(shù)組聲明數(shù)組名+數(shù)組大小FunK

20、函數(shù)聲明返回類型+函數(shù)名+參數(shù)列表+函數(shù)體ParamsKFunK的參數(shù)列表參數(shù)(如果有多個(gè)參數(shù),則之間為兄弟節(jié)點(diǎn))ParamKFunK的參數(shù)參數(shù)類型+參數(shù)名CompK復(fù)合語句體變量聲明列表+語句列表Selection_StmtKif條件表達(dá)式+IF體+ELSE體Iteration_StmtKwhile條件表達(dá)式+循環(huán)體Return_StmtKreturn表達(dá)式AssignK賦值被賦值變量+賦值變量OpK運(yùn)算運(yùn)算符左值+運(yùn)算符右值A(chǔ)rry_ElemK數(shù)組元素?cái)?shù)組名+下標(biāo)CallK函數(shù)調(diào)用函數(shù)名+參數(shù)列表ArgsKCallK的參數(shù)列表表達(dá)式UnkownK未知節(jié)點(diǎn)無3.2節(jié)點(diǎn)定義typedef st

21、ruct treeNodestruct treeNode * child4;struct treeNode * sibling;int lineno;NodeKind nodekind;union TokenType op; int val; const char * name; attr; ExpType type; TreeNode;4 代碼結(jié)構(gòu)分析文法programdeclaration-list分析函數(shù)TreeNode * parse(void)說明C-程序由一個(gè)聲明序列組成,parse(void)函數(shù)首先執(zhí)行g(shù)etToken()然后直接調(diào)用declaration_list()返回樹節(jié)

22、點(diǎn)代碼TreeNode * parse(void)TreeNode * t;token = getToken();t = declaration_list();if(token!=ENDFILE) syntaxError("endfile error");return t;文法declaration_list declaration declaration 分析函數(shù)TreeNode * declaration_list(void)說明聲明序列是由若干聲明構(gòu)成,declaration_list(void)函數(shù)中直接調(diào)用declaration()函數(shù)返回樹節(jié)點(diǎn),當(dāng)前token為

23、INT或VOID時(shí),調(diào)用declaration()返回之前樹節(jié)點(diǎn)的兄弟節(jié)點(diǎn)。代碼TreeNode * declaration_list(void)TreeNode * t = declaration();TreeNode * p =t;/程序以變量聲明開始 while(token!=INT)&&(token!=VOID)&&(token!=ENDFILE) syntaxError("開始不是類型聲明"); token = getToken(); if(token=ENDFILE) break; while(token=INT|token=VO

24、ID)TreeNode * q;q = declaration();if (q!=NULL)if (t=NULL)t=p=q;elsep->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-stmt type-specifier int | void分析函

25、數(shù) TreeNode * declaration(void)說明首先判斷類型,執(zhí)行match函數(shù), 匹配類型和ID,向前探測(cè)1個(gè)token的值確定是函數(shù)聲明還是變量聲明,如果token為,則是數(shù)組變量聲明,返回節(jié)點(diǎn)Array_DeclK, token為(,則是函數(shù)聲明,返回節(jié)點(diǎn)FunK, token為;則是普通變量聲明,返回節(jié)點(diǎn)Var_DeclK代碼TreeNode * declaration(void)TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;TreeNode * s = NULL;TreeNode * a = N

26、ULL;if (token=INT)p=newNode(IntK);match(INT);else if (token=VOID)p=newNode(VoidK);match(VOID);else syntaxError("type error");if(p!=NULL&&token=ID)q = newNode(IdK);q-> = copyString(tokenString); match(ID);if (token=LPAREN)t = newNode(FunK);t->child0 = p; /p是t子節(jié)點(diǎn)t->

27、child1 = q;match(LPAREN);t->child2 = params();match(RPAREN);t->child3 = compound_stmt();else if (token=LBRACKET)t = newNode(Var_DeclK);a = newNode(Arry_DeclK);t->child0 = p; /p是t子節(jié)點(diǎn)t->child1 = a;match(LBRACKET);s = newNode(ConstK);s->attr.val = atoi(tokenString);match(NUM);a->child

28、0=q;a->child1=s;match(RBRACKET);match(SEMI);else if (token=SEMI)t = newNode(Var_DeclK);t->child0 = p;t->child1 = q;match(SEMI);elsesyntaxError("");elsesyntaxError("");return t;文法paramsparam_list | void分析函數(shù)TreeNode * params(void)說明參數(shù)列表,根節(jié)點(diǎn)ParamsK,首先判斷token是否是VOID,如果是VOID則

29、匹配,判斷下一個(gè)token,如果是右括號(hào),則參數(shù)列表中只有子節(jié)點(diǎn)VoidK,如果是ID,則子節(jié)點(diǎn)是param_list,如果開始時(shí)token是INT,則參數(shù)列表子節(jié)點(diǎn)是param_list代碼TreeNode * params(void)TreeNode * t = newNode(ParamsK);TreeNode * p = NULL;if (token=VOID)p = newNode(VoidK);match(VOID);if (token=RPAREN)if(t!=NULL)t->child0 = p;else/參數(shù)列表為(void id,) t->child0 = pa

30、ram_list(p);else if (token=INT)t->child0 = param_list(p);else syntaxError("");return t;文法param_listparam, param分析函數(shù)TreeNode * param_list(TreeNode * k)說明說明參數(shù)列表由param序列組成,并由逗號(hào)隔開。param_list(TreeNode * k)函數(shù)使用遞歸向下分析方法直接調(diào)用param(TreeNode * k)函數(shù),并返回樹節(jié)點(diǎn)代碼TreeNode * param_list(TreeNode * k)TreeNo

31、de * t = param(k);TreeNode * p = t; k = NULL;/沒有要傳給param的VoidK,所以將k設(shè)為NULLwhile (token=COMMA)TreeNode * q = NULL;match(COMMA);q = param(k);if (q!=NULL)if (t=NULL)t=p=q;elsep->sibling = q;p = q;return t;文法param type-specifier ID 分析函數(shù)TreeNode * param(TreeNode * k)說明探測(cè)token是INT還是VOID,決定子節(jié)點(diǎn)類型是IntK還是Vo

32、idK,IdK作為第二個(gè)子節(jié)點(diǎn),向前探測(cè)一個(gè)token,如果是左中括號(hào),則產(chǎn)生第三個(gè)子節(jié)點(diǎn)代碼TreeNode * param(TreeNode * k)TreeNode * t = newNode(ParamK);TreeNode * p = NULL;TreeNode * q = NULL;if(k=NULL&&token=VOID)p = newNode(VoidK);match(VOID);else if(k=NULL&&token=INT)p = newNode(IntK);match(INT);else if (k!=NULL)p = k;if(p!

33、=NULL)t->child0 = p;if (token=ID)q = newNode(IdK);q-> = copyString(tokenString);t->child1 = q;match(ID);elsesyntaxError("");if (token=LBRACKET&&(t->child1!=NULL)/match(LBRACKET);t->child2 = newNode(IdK);match(RBRACKET);else return t; else syntaxError("&

34、quot;);return t;文法compound-stmt local-declaration statement-list分析函數(shù)TreeNode * compound_stmt(void)說明復(fù)合語句,直接調(diào)用local_declaration()函數(shù)和statement_list()函數(shù),產(chǎn)生兩個(gè)子節(jié)點(diǎn)代碼TreeNode * compound_stmt(void) TreeNode * t = newNode(CompK);match(LCBRACKET);t->child0 = local_declaration();t->child1 = statement_lis

35、t(); match(RCBRACKET);return t;文法local-declarations empty var- declaration分析函數(shù)TreeNode * local_declaration(void)說明全局變量聲明,可以是空,也可以是若干變量聲明,首先判斷token是否等于INT或VOID,從而得知是否為空,若不為空則創(chuàng)建一個(gè)Var_DeclK節(jié)點(diǎn)代碼TreeNode * local_declaration(void) TreeNode * t = NULL;TreeNode * q = NULL;TreeNode * p = NULL;while(token=INT

36、 | token=VOID) p = newNode(Var_DeclK);if(token=INT)TreeNode * q1 = newNode(IntK);p->child0 = q1;match(INT);else if(token=VOID)TreeNode * q1 = newNode(VoidK);p->child0 = q1;match(INT);if(p!=NULL)&&(token=ID) TreeNode * q2 = newNode(IdK); q2-> = copyString(tokenString);p->

37、child1 = q2;match(ID);if(token=LBRACKET) TreeNode * q3 = newNode(Var_DeclK);p->child3 = q3;match(LBRACKET);match(RBRACKET);match(SEMI);else if(token=SEMI)match(SEMI);elsematch(SEMI); else syntaxError("");if(p!=NULL)if(t=NULL)t = q = p;elseq->sibling = p;q = p;return t;文法statement-lis

38、tstatement分析函數(shù)TreeNode * statement_list(void)說明調(diào)用statement()創(chuàng)建根節(jié)點(diǎn),向前探測(cè)一個(gè)token,創(chuàng)建兄弟節(jié)點(diǎn)代碼TreeNode * statement_list(void) TreeNode * t = statement(); TreeNode * p = t;while (IF=token | LCBRACKET=token | ID=token | WHILE=token | RETURN =token | SEMI=token | LPAREN=token | NUM=token) TreeNode * q;q = stat

39、ement();if(q!=NULL)if(t=NULL) t = p = q;else p->sibling = q;p = q;return t;文法statementexpression-stmt| compound-stmt | selection-stmt | iteration-stmt | return-stmt分析函數(shù)TreeNode * statement(void)說明statement由表達(dá)式或復(fù)合語句或if語句或while語句或return語句構(gòu)成。statement(void)函數(shù)通過判斷先行Token類型確定到底是哪一種類型。如果是IF則調(diào)用selection

40、_statement(),如果是WHILE,則調(diào)用iteration_stmt(),如果是RETURN,則調(diào)用return(),如果是左大括號(hào),則是復(fù)合語句類型,如果是ID、SEMI、LPAREN、NUM,則是表達(dá)式語句類型代碼TreeNode * statement(void) TreeNode * t = NULL;switch(token)case IF:t = selection_stmt(); break;case WHILE:t = iteration_stmt(); break;case RETURN:t = return_stmt(); break;case LCBRACKET

41、:t = compound_stmt(); break;case ID: case SEMI: case LPAREN: case NUM: t = expression_stmt(); break;default:syntaxError("");token = getToken();break;return t;文法expression-stmt expression;分析函數(shù)TreeNode * expression_stmt(void)說明說明表達(dá)式語句有一個(gè)可選的且后面跟著分號(hào)的表達(dá)式。expression_stmt(void)函數(shù)通過判斷先行token類型是否為分

42、號(hào),如果不是則直接調(diào)用函數(shù)expression()代碼TreeNode * expression_stmt(void) TreeNode * t = NULL;if(token=SEMI) match(SEMI);return t;else t = expression();match(SEMI);return t;文法expression var = expression | simple-expression分析函數(shù)TreeNode * expression(void)說明expression(void)函數(shù)通過判斷先行Token類型是否為ID,如果不是說明只能是simple_expres

43、sion情況,則調(diào)用simple_expression(TreeNode * k)函數(shù)遞歸向下分析;如果是ID說明可能是賦值語句,或simple_expression中的var和call類型的情況,所以再求其Follow集合,如果集合求出來是賦值類型的Token,則說明是賦值語句,于是新建一個(gè)AssignK節(jié)點(diǎn)就行;如果集合求出來不是賦值類型的Token則說明是simple_expression中的var和call類型的情況,然后再調(diào)用simple_expression(TreeNode * k)函數(shù)遞歸向下分析,并將已經(jīng)取出IdK節(jié)點(diǎn)傳遞給simple_expression(TreeNode

44、 * k)函數(shù)代碼TreeNode * expression(void) TreeNode * t = var();if(t=NULL)/不是以ID開頭,只能是simple_expression情況 t = simple_expression(t); else/以ID開頭,可能是賦值語句,或simple_expression中的var和call類型的情況 TreeNode * p = NULL;if(token=ASSIGN)/賦值語句 p = newNode(AssignK);/p-> = ;match(ASSIGN);p->child0 = t;p->c

45、hild1 = expression();return p;else /simple_expression中的var和call類型的情況 t = simple_expression(t); return t;文法varID | ID expression分析函數(shù)TreeNode * var(void)說明創(chuàng)建IdK節(jié)點(diǎn),判斷先行token類型是否是中括號(hào),如果是就創(chuàng)建Arry_ElemK節(jié)點(diǎn),調(diào)用expression()得到子節(jié)點(diǎn)代碼TreeNode * var(void) TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;

46、if(token=ID)p = newNode(IdK);p-> = copyString(tokenString); match(ID);if(token=LBRACKET) match(LBRACKET);q = expression();match(RBRACKET);t = newNode(Arry_ElemK);t->child0 = p;t->child1 = q;elset = p;return t;文法simple-expression>additive-expression relop additive-expression relo

47、p < = | < | > | > = | = = | ! =分析函數(shù)TreeNode * simple_expression(TreeNode * k)說明simple_expression(TreeNode * k)函數(shù)先調(diào)用additive_expression(TreeNode * k)函數(shù)返回一個(gè)節(jié)點(diǎn),然后再一直判斷后面的Token是否為<=、<、>、>=、=、!=,如果是則新建OpK節(jié)點(diǎn),然后令之前的節(jié)點(diǎn)為其第一個(gè)子節(jié)點(diǎn),然后繼續(xù)調(diào)用additive_expression(TreeNode * k)函數(shù)返回一個(gè)節(jié)點(diǎn),作為OpK節(jié)點(diǎn)的第

48、二個(gè)節(jié)點(diǎn)代碼TreeNode * simple_expression(TreeNode * k) TreeNode * t = additive_expression(k);k = NULL;if(EQ=token | GT=token | GEQ=token | LT=token | LEQ=token | NEQ=token) TreeNode * q = newNode(OpK);q->attr.op = token; q->child0 = t;t = q;match(token);t->child1 = additive_expression(k); return

49、t;return t;5 實(shí)驗(yàn)結(jié)果與分析測(cè)試文本test.cint a10;int min(int a,int low,void a)int k; int x; int i;k=low;while(i<low)a0=1;if(k>0)x=1;return x;測(cè)試結(jié)果成功實(shí)現(xiàn)語法分析6 小結(jié)通過這次實(shí)驗(yàn),我加深了對(duì)語法分析的認(rèn)識(shí),掌握了遞歸向下分析方法,實(shí)現(xiàn)了對(duì)詞法分析程序所提供的Token序列的語法檢查和結(jié)構(gòu)分析。 語法分析程序編寫相對(duì)于詞法分析要困難得多,首先要將BNF化為EBNF,運(yùn)用遞歸向下的方法進(jìn)行編寫,構(gòu)造出語法樹,判別語法分析過程中是否出錯(cuò)以及出錯(cuò)位置和錯(cuò)誤類型。雖然EBNF轉(zhuǎn)換成代碼的過程原理比較簡(jiǎn)單,但是操作起來比較繁瑣。一開始我對(duì)TreeNode數(shù)據(jù)結(jié)構(gòu)也不是很理解,通過閱讀書后的tiny語言語法分析源代碼,我弄懂了語法樹的輸出。附錄(源代碼)Main.c#include "global.h"#include "util.h"#include "scan.h"/* 全局變量 */int lineno = 0;/* 編譯過程標(biāo)志 */int EchoSource = TRUE;int TraceSca

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論