




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、編譯原理課程設計課程報告題目 C語言詞法分析器和C-語言語法分析器 學生姓名 學生學號 指導教師 提交報告時間 2019 年 6 月 8 日C語言詞法分析器1 實驗目的及意義1. 熟悉C語言詞法2. 掌握構造DFA的過程3. 掌握利用DFA實現(xiàn)C語言的詞法分析器4. 理解編譯器詞法分析的工作原理2 詞法特點及正則表達式2.1詞法特點2.1.1 保留字AUTO, BREAK , CASE , CHAR , CONST , CONTINUE , DEFAULT , DO , DOUBLE , ELSE, ENUM , EXTERN , FLOAT , FOR , GOTO, IF , INT ,
2、LONG , REGISTER , RETURN, SHORT , SIGNED , SIZEOF , STATIC , STRUCT , SWITCH , TYPEDEF , UNION , UNSIGNED , VOID, VOLATILE , WHILE,2.1.2 符號 + - * / + - += -= *= = = != = ; , ( ) /* */ : 2.2 正則表達式 whitespace = (newline|blank|tab|comment)+ digit=0|.|9 nat=digit+ signedNat=(+|-)?nat NUM=signedNat(“.”na
3、t)? 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 switch typedef union unsignedvoid volatile whi
4、le特殊符號+ - * / + - += -= *= = = != = ; , ( ) /* */ :文件結束、錯誤EOF ERROR其它tokenNUM ID CHARACTER STRINGtypedef enum /錯誤、結束 ENDFILE,ERROR, /保留字 AUTO,BREAK,CASE,CHAR,CONST,CONTINUE ,DEFAULT , DO ,DOUBLE, ELSE, ENUM, EXTERN , FLOAT ,FOR , GOTO,IF, INT, LONG,REGISTER , RETURN, SHORT, SIGNED ,SIZEOF ,STATIC, S
5、TRUCT ,SWITCH, TYPEDEF ,UNION, UNSIGNED , VOID,VOLATILE , WHILE, /其他token ID,NUM,CHARACTER,STRING,/特殊符號 /+、-、*、/、+、-、+=、-=、*=、=、=、!=、=、;、,、(、)、/、/*、*/、:PLUS,MINUS,TIMES,OVER,SELFPLUS,SELFMINUS,PLUSASSIGN,MINUSASSIGN,TIMESASSIGN,LT,LEQ,GT,GEQ,EQ,NEQ,ASSIGN,SEMI,COMMA,LPAREN, MINUSASSIGN,TIMESASSIGN,L
6、T,LEQ,GT,GEQ,EQ,NEQ,ASSIGN,SEMI,COMMA,LPAREN, RPAREN,LBRACKET,RBRACKET, LCBRACKET,RCBRACKET,LCOMMENT,RCOMMENT,COLON TokenType;3.2 tokenType類型代碼4 DFA設計4.1 注釋的DFA設計注釋的DFA如下所示,一共分為5個狀態(tài),在開始狀態(tài)1時,如果輸入的字符為/,則進入狀態(tài)2,此時有可能進入注釋狀態(tài),如果在狀態(tài)2時,輸入的字符為*,則進入注釋狀態(tài),狀態(tài)將轉到3,如果在狀態(tài)3時,輸入的字符為*,則有可能結束注釋狀態(tài),此時狀態(tài)將轉到狀態(tài)4,如果在狀態(tài)4時輸入的字符
7、為/,則注釋狀態(tài)結束,狀態(tài)轉移到結束狀態(tài)。4.2 詞法分析的DFA設計詞法分析的DFA如下所示,一共分為10個狀態(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表示標示符(ID)類型Token的狀態(tài),狀態(tài)INOPERATE表示算數(shù)運算符型Token的狀態(tài),狀態(tài)INOCOMPARE表示比較運算符型Token的狀態(tài),INSTRING表示字符串(STRING)類型Token的狀態(tài),
8、INCHAR表示字符(CHARACTER)類型Token的狀態(tài),狀態(tài)DONE表示接收狀態(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) 如果輸入的字符為、=2) b+=0.1 a+; 6.2 測試結果6.3結果分析test.c文件中包括注釋,保留字,整數(shù)和小數(shù),標識符,特殊符號,字符串以及錯誤輸入。本程序成功對test.c文件進行了詞法分析,對注釋進行了忽略,輸出了相應的行號
9、、類型、取值,對于錯誤的輸入顯示ERROR。7 小結通過編寫C語言詞法分析器,我對編譯器的基本原理有了更深的認識,同時掌握了DFA的設計與實現(xiàn)。在最開始的編寫過程中,我總是把詞法和語法分析混淆,比如一些錯誤應該在語法分析中判斷,我卻寫進了詞法分析中,后來我逐步認識到詞法分析的作用就是提取源代碼中的Token。在DFA的實現(xiàn)過程中,我主要參考了書后tiny語言DFA的實現(xiàn)方法,將它擴展到C語言。另外C語言詞法比較復雜,因為時間關系我省略了一些,比如位運算符,轉義字符等等,希望今后能完善。C-語言語法分析器1 實驗目的及意義用C語言編制Tiny/C-語言的語法分析程序,實現(xiàn)對詞法分析程序所提供的T
10、oken序列的語法檢查和結構分析。 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-stmtparamsparam_list | vo
11、idparam_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;selection-stmtif (expressio
12、n) statement else statementiteration-stmtwhile (expression)statementreturn-stmtreturn expression;expression var = expression | simple-expressionrelop = | | = | = = | ! =varID | ID expressionsimple-expressionadditive-expression relop additive-expression additive-expressiontermaddop term addop + | -te
13、rmfactormulop factor mulop * | /factor(expression) | var | call | NUMcallID( args )argsarg-list | emptyarg-list expression, expression3 節(jié)點類型及定義3.1節(jié)點類型節(jié)點類型描述子節(jié)點IntKInt型變量或返回值無VoidKvoid型變量或返回值無IdK標示符id無ConstK數(shù)值無Var_DeclK變量聲明變量類型+變量名Var_DeclK數(shù)組聲明數(shù)組名+數(shù)組大小FunK函數(shù)聲明返回類型+函數(shù)名+參數(shù)列表+函數(shù)體ParamsKFunK的參數(shù)列表參數(shù)(如果有多個
14、參數(shù),則之間為兄弟節(jié)點)ParamKFunK的參數(shù)參數(shù)類型+參數(shù)名CompK復合語句體變量聲明列表+語句列表Selection_StmtKif條件表達式+IF體+ELSE體Iteration_StmtKwhile條件表達式+循環(huán)體Return_StmtKreturn表達式AssignK賦值被賦值變量+賦值變量OpK運算運算符左值+運算符右值Arry_ElemK數(shù)組元素數(shù)組名+下標CallK函數(shù)調(diào)用函數(shù)名+參數(shù)列表ArgsKCallK的參數(shù)列表表達式UnkownK未知節(jié)點無3.2節(jié)點定義typedef struct treeNodestruct treeNode * child4;struct
15、treeNode * sibling;int lineno;NodeKind nodekind;union TokenType op; int val; const char * name; attr; ExpType type; TreeNode;4 代碼結構分析文法programdeclaration-list分析函數(shù)TreeNode * parse(void)說明C-程序由一個聲明序列組成,parse(void)函數(shù)首先執(zhí)行getToken()然后直接調(diào)用declaration_list()返回樹節(jié)點代碼TreeNode * parse(void)TreeNode * t;token =
16、 getToken();t = declaration_list();if(token!=ENDFILE) syntaxError(endfile error);return t;文法declaration_list declaration declaration 分析函數(shù)TreeNode * declaration_list(void)說明聲明序列是由若干聲明構成,declaration_list(void)函數(shù)中直接調(diào)用declaration()函數(shù)返回樹節(jié)點,當前token為INT或VOID時,調(diào)用declaration()返回之前樹節(jié)點的兄弟節(jié)點。代碼TreeNode * declar
17、ation_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=VOID)TreeNode * q;q = declaration();if (q!=NULL)if (t=NULL)t=p=q;elsep-sibling=q;p=q;matc
18、h(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分析函數(shù) TreeNode * declaration(void)說明首先判斷類型,執(zhí)行match函數(shù), 匹配類型和ID,向前探測1個token的值確定是函數(shù)聲明還是變量聲明,如果toke
19、n為,則是數(shù)組變量聲明,返回節(jié)點Array_DeclK, token為(,則是函數(shù)聲明,返回節(jié)點FunK, token為;則是普通變量聲明,返回節(jié)點Var_DeclK代碼TreeNode * declaration(void)TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;TreeNode * s = NULL;TreeNode * a = NULL;if (token=INT)p=newNode(IntK);match(INT);else if (token=VOID)p=newNode(VoidK);match(VOI
20、D);else syntaxError(type error);if(p!=NULL&token=ID)q = newNode(IdK); = copyString(tokenString); match(ID);if (token=LPAREN)t = newNode(FunK);t-child0 = p; /p是t子節(jié)點t-child1 = q;match(LPAREN);t-child2 = params();match(RPAREN);t-child3 = compound_stmt();else if (token=LBRACKET)t = newNode(Va
21、r_DeclK);a = newNode(Arry_DeclK);t-child0 = p; /p是t子節(jié)點t-child1 = a;match(LBRACKET);s = newNode(ConstK);s-attr.val = atoi(tokenString);match(NUM);a-child0=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();elsesy
22、ntaxError();return t;文法paramsparam_list | void分析函數(shù)TreeNode * params(void)說明參數(shù)列表,根節(jié)點ParamsK,首先判斷token是否是VOID,如果是VOID則匹配,判斷下一個token,如果是右括號,則參數(shù)列表中只有子節(jié)點VoidK,如果是ID,則子節(jié)點是param_list,如果開始時token是INT,則參數(shù)列表子節(jié)點是param_list代碼TreeNode * params(void)TreeNode * t = newNode(ParamsK);TreeNode * p = NULL;if (token=VOI
23、D)p = newNode(VoidK);match(VOID);if (token=RPAREN)if(t!=NULL)t-child0 = p;else/參數(shù)列表為(void id,) t-child0 = param_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序列組成,并由逗號隔開。param_list(TreeNode
24、 * k)函數(shù)使用遞歸向下分析方法直接調(diào)用param(TreeNode * k)函數(shù),并返回樹節(jié)點代碼TreeNode * param_list(TreeNode * k)TreeNode * t = param(k);TreeNode * p = t; k = NULL;/沒有要傳給param的VoidK,所以將k設為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
25、type-specifier ID 分析函數(shù)TreeNode * param(TreeNode * k)說明探測token是INT還是VOID,決定子節(jié)點類型是IntK還是VoidK,IdK作為第二個子節(jié)點,向前探測一個token,如果是左中括號,則產(chǎn)生第三個子節(jié)點代碼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=NU
26、LL&token=INT)p = newNode(IntK);match(INT);else if (k!=NULL)p = k;if(p!=NULL)t-child0 = p;if (token=ID)q = newNode(IdK); = copyString(tokenString);t-child1 = q;match(ID);elsesyntaxError();if (token=LBRACKET&(t-child1!=NULL)/match(LBRACKET);t-child2 = newNode(IdK);match(RBRACKET);else retur
27、n t; else syntaxError();return t;文法compound-stmt local-declaration statement-list分析函數(shù)TreeNode * compound_stmt(void)說明復合語句,直接調(diào)用local_declaration()函數(shù)和statement_list()函數(shù),產(chǎn)生兩個子節(jié)點代碼TreeNode * compound_stmt(void) TreeNode * t = newNode(CompK);match(LCBRACKET);t-child0 = local_declaration();t-child1 = stat
28、ement_list(); match(RCBRACKET);return t;文法local-declarations empty var- declaration分析函數(shù)TreeNode * local_declaration(void)說明全局變量聲明,可以是空,也可以是若干變量聲明,首先判斷token是否等于INT或VOID,從而得知是否為空,若不為空則創(chuàng)建一個Var_DeclK節(jié)點代碼TreeNode * local_declaration(void) TreeNode * t = NULL;TreeNode * q = NULL;TreeNode * p = NULL;while(
29、token=INT | 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); = copyString(tokenString);p-child1 = q2;matc
30、h(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-liststatement分析函數(shù)TreeNode * statement_l
31、ist(void)說明調(diào)用statement()創(chuàng)建根節(jié)點,向前探測一個token,創(chuàng)建兄弟節(jié)點代碼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 = statement();if(q!=NULL)if(t=NULL) t = p
32、= q;else p-sibling = q;p = q;return t;文法statementexpression-stmt| compound-stmt | selection-stmt | iteration-stmt | return-stmt分析函數(shù)TreeNode * statement(void)說明statement由表達式或復合語句或if語句或while語句或return語句構成。statement(void)函數(shù)通過判斷先行Token類型確定到底是哪一種類型。如果是IF則調(diào)用selection_statement(),如果是WHILE,則調(diào)用iteration_stmt(
33、),如果是RETURN,則調(diào)用return(),如果是左大括號,則是復合語句類型,如果是ID、SEMI、LPAREN、NUM,則是表達式語句類型代碼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:t = compound_stmt(); break;case ID: cas
34、e SEMI: case LPAREN: case NUM: t = expression_stmt(); break;default:syntaxError();token = getToken();break;return t;文法expression-stmt expression;分析函數(shù)TreeNode * expression_stmt(void)說明說明表達式語句有一個可選的且后面跟著分號的表達式。expression_stmt(void)函數(shù)通過判斷先行token類型是否為分號,如果不是則直接調(diào)用函數(shù)expression()代碼TreeNode * expression_stm
35、t(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_expression情況,則調(diào)用simple_expression(TreeNode * k)函數(shù)遞歸向下分析;如果
36、是ID說明可能是賦值語句,或simple_expression中的var和call類型的情況,所以再求其Follow集合,如果集合求出來是賦值類型的Token,則說明是賦值語句,于是新建一個AssignK節(jié)點就行;如果集合求出來不是賦值類型的Token則說明是simple_expression中的var和call類型的情況,然后再調(diào)用simple_expression(TreeNode * k)函數(shù)遞歸向下分析,并將已經(jīng)取出IdK節(jié)點傳遞給simple_expression(TreeNode * k)函數(shù)代碼TreeNode * expression(void) TreeNode * t =
37、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);/ = ;match(ASSIGN);p-child0 = t;p-child1 = expression();return p;else /simple_expression中的var和call類
38、型的情況 t = simple_expression(t); return t;文法varID | ID expression分析函數(shù)TreeNode * var(void)說明創(chuàng)建IdK節(jié)點,判斷先行token類型是否是中括號,如果是就創(chuàng)建Arry_ElemK節(jié)點,調(diào)用expression()得到子節(jié)點代碼TreeNode * var(void) TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;if(token=ID)p = newNode(IdK); = copyString(tokenStrin
39、g); 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-expressionadditive-expression relop additive-expression relop = | | = | = = | ! =分析函數(shù)TreeNode * simple_expression(TreeNode * k)說明simple_expr
40、ession(TreeNode * k)函數(shù)先調(diào)用additive_expression(TreeNode * k)函數(shù)返回一個節(jié)點,然后再一直判斷后面的Token是否為=、=、=、!=,如果是則新建OpK節(jié)點,然后令之前的節(jié)點為其第一個子節(jié)點,然后繼續(xù)調(diào)用additive_expression(TreeNode * k)函數(shù)返回一個節(jié)點,作為OpK節(jié)點的第二個節(jié)點代碼TreeNode * simple_expression(TreeNode * k) TreeNode * t = additive_expression(k);k = NULL;if(EQ=token | GT=token |
41、 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 t;return t;5 實驗結果與分析測試文本test.cint a10;int min(int a,int low,void a)int k; int x; int i;k=low;while(i0)x=1;return x;測試結果成功實現(xiàn)語法分析6 小結通
42、過這次實驗,我加深了對語法分析的認識,掌握了遞歸向下分析方法,實現(xiàn)了對詞法分析程序所提供的Token序列的語法檢查和結構分析。 語法分析程序編寫相對于詞法分析要困難得多,首先要將BNF化為EBNF,運用遞歸向下的方法進行編寫,構造出語法樹,判別語法分析過程中是否出錯以及出錯位置和錯誤類型。雖然EBNF轉換成代碼的過程原理比較簡單,但是操作起來比較繁瑣。一開始我對TreeNode數(shù)據(jù)結構也不是很理解,通過閱讀書后的tiny語言語法分析源代碼,我弄懂了語法樹的輸出。附錄(源代碼)Main.c#include global.h#include util.h#include scan.h/* 全局變量 */int lineno = 0;/* 編譯過程標志 */int EchoSource = TRUE;int TraceScan = TRUE;int Error = FALSE;int main(void)TreeNode * syntaxTree; char pgm120; /*用于存儲文件名*/print
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 出售電廠配煤合同范本
- 勞動合同范本免
- 企業(yè)管道施工合同范本
- 醫(yī)療美容股東合同范本
- 醫(yī)院入職合同范本
- 倉儲承諾合同范本
- 三年級口算題庫匯編1000道
- 二年級口算題目全集100道
- 2025云南省安全員C證考試題庫
- 工傷授權委托書填寫模板范文
- 校園食品安全和膳食經(jīng)費管理方案3篇
- TSGD7002-2023-壓力管道元件型式試驗規(guī)則
- 九年級化學下冊 第12單元 化學與生活教案 (新版)新人教版
- 金融服務消費糾紛調(diào)解工作規(guī)范
- 后腹腔鏡下輸尿管切開取石術
- 二手車購買收據(jù)合同范本
- 《國際貿(mào)易實務(英文版)》(英文課件) - Ch 1 Introduction to International Trade Practices-Ch 5 Price
- 2022版義務教育英語課程標準整體解讀課件
- 2024精美復工復產(chǎn)安全培訓
- 01 H5入門知識課件
- 神經(jīng)重癥氣管切開患者氣道功能康復與管理專家共識(2024)解讀
評論
0/150
提交評論