版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p> 編譯原理課程設(shè)計(jì)報(bào)告</p><p> 課題名稱(chēng): C-編譯器詞法分析與語(yǔ)法分析的實(shí)現(xiàn) </p><p> 指導(dǎo)教師評(píng)閱成績(jī): </p><p> 指導(dǎo)教師評(píng)閱意見(jiàn): </p><p>
2、 . </p><p> . </p><p> 提交報(bào)告時(shí)間:2013年 6 月 5 日</p><p> 編譯原理課程設(shè)計(jì)報(bào)告1</p><p
3、> 1、課程設(shè)計(jì)目標(biāo)3</p><p><b> 2、分析與設(shè)計(jì)3</b></p><p> 2.1、說(shuō)明所用的方法:3</p><p> 2.2、系統(tǒng)總圖:3</p><p> 2.2.1、scanner部分:3</p><p> 2.2.2、parse部分:5&l
4、t;/p><p> 2.2.3、代碼設(shè)計(jì)說(shuō)明7</p><p> 3、程序代碼實(shí)現(xiàn)10</p><p> 3.1、獲取輸入部分(在main.c中):10</p><p> 3.2、詞法分析部分(在scan.c中):10</p><p> 3.3、語(yǔ)法分析部分(在parse.c中):15</p>
5、;<p> 3.4、輸出與結(jié)點(diǎn)的建立(在util.c中)29</p><p> 3.5、TokenType、treeNode與結(jié)點(diǎn)類(lèi)型的聲明(在globals.h中)34</p><p><b> 4、測(cè)試結(jié)果36</b></p><p><b> 5、總結(jié)36</b></p>
6、<p><b> 5.1、收獲36</b></p><p><b> 5.2、不足36</b></p><p><b> 1、課程設(shè)計(jì)目標(biāo)</b></p><p> 本次實(shí)驗(yàn),本C- 編譯器主要設(shè)計(jì)并且實(shí)現(xiàn)了C- 編譯器的詞法分析功能與語(yǔ)法分析功能。</p><
7、;p><b> 2、分析與設(shè)計(jì)</b></p><p> 2.1、說(shuō)明所用的方法:</p><p> 各部分的實(shí)現(xiàn)方法(scanner:手工實(shí)現(xiàn)、Lex;parser:遞歸下降、LL(1)、LR(0)、SLR(1)、LR(1)、LALR(1)、Yacc),所用編程語(yǔ)言</p><p><b> 2.2、系統(tǒng)總圖:<
8、/b></p><p> 2.2.1、scanner部分:</p><p> 2.2.1.1、實(shí)驗(yàn)原理:</p><p> 掃描程序的任務(wù)是從源代碼中讀取字符并形成由編譯器的以后部分(通常是分析程序)處理的邏輯單元。由掃描程序生成的邏輯單元稱(chēng)作記號(hào)(token),將字符組合成記號(hào)與在一個(gè)英語(yǔ)句子中將字母將字母構(gòu)成單詞并確定單次的含義很相像。</p&
9、gt;<p> 在此程序中,我將記號(hào)分成了以下類(lèi)型:</p><p> typedef enum {//按照書(shū)上附錄B程序布局,放在globals.h中</p><p> ENDFILE,ERROR,</p><p> IF,ELSE,INT,RETURN,VOID,WHILE,</p><p><b> I
10、D,NUM,</b></p><p> ASSIGN,PLUS,MINUS,TIMES,OVER,LT,LET,BT,BET,EQ,NEQ,</p><p> // = + - * / < <= > >= == != </p><p> LPAREN_1,RPAREN_1,S
11、EMI,COM,LPAREN_2,RPAREN_2,LPAREN_3,RPAREN_3,LIN,RIN</p><p> //{ } ; , [ ] ( ) /* </p><p> } TokenType;</p><p> 其中,關(guān)鍵字有:else、if、in
12、t、return、void、while;</p><p> 專(zhuān)用符號(hào)有:+、-、*、/、<、<=、>、>=、==、~=、=、;、,、(、)、[、]、{、}、/*、*/</p><p> 其他標(biāo)記是ID、NUM,通過(guò)下列正則表達(dá)式定義:</p><p> ID = letter letter*</p><p>
13、 NUM = digit digit*</p><p> letter = a|..|z|A|..|Z</p><p> digit = 0|..|9</p><p> 小寫(xiě)大寫(xiě)字母是有區(qū)別的。</p><p> 空格由空白、換行符和制表符組成。空格通常被忽略,除了他必須分開(kāi)ID、NUM關(guān)鍵字。</p><p&g
14、t; 注釋常用通常的C語(yǔ)言符號(hào)/*...*/圍起來(lái)。注釋可以放在任何空白出現(xiàn)的位置(即注釋不能放在標(biāo)記內(nèi))上,且可以超過(guò)一行。注釋不能嵌套。</p><p> 2.2.1.2、實(shí)驗(yàn)方法:</p><p> 我通過(guò)對(duì)scanner部分原理的了解,確定了他的NFA,再將NFA轉(zhuǎn)化成DFA,并且將狀態(tài)數(shù)最小化。最后根據(jù)我所得的DFA與課后TINY的示例程序編寫(xiě)scanner.c。</
15、p><p><b> 最后所得的DFA:</b></p><p> 2.2.1.3、編程方法:</p><p><b> 編程采用C語(yǔ)言。</b></p><p> 初始狀態(tài)設(shè)置為START,當(dāng)需要得到下一個(gè)token時(shí),取得此token的第一個(gè)字符,并且按照DFA與對(duì)此字符的類(lèi)型的分析,轉(zhuǎn)換狀
16、態(tài)。重復(fù)此步驟,直到DONE為止,輸出token類(lèi)型。</p><p> 此中難點(diǎn)在于對(duì)于注釋的分析,因此我將判斷注釋分成幾個(gè)步驟。當(dāng)字符為“/”時(shí),狀態(tài)轉(zhuǎn)換為INASSIGN_1(自創(chuàng)的)再判斷下一個(gè)字符,如果為“*”則是注釋?zhuān)绻瞧渌膭t字符停滯與當(dāng)前字符(ungetNextChar()),并且輸出“/”。在開(kāi)始時(shí)一直未注意停滯與當(dāng)前字符,因此總是讀不出“/v*”中的“v”,在調(diào)試多次后才得以解決。<
17、;/p><p> 2.2.2、parse部分:</p><p> 2.2.2.1、實(shí)驗(yàn)原理:</p><p> C-語(yǔ)言的各個(gè)語(yǔ)法規(guī)則: </p><p> 1. program → declaration-list </p><p> 2. declaration-list → declaration-list
18、 declaration | declaration </p><p> 3. declaration → var-declaration | fun-declaration </p><p> 4. var-declaration → type-specifier ID ; | type-specifier ID [ NUM ] ; </p><p> 5.
19、 type-specifier → int | void </p><p> 6. fun-declaration → type-specifier ID ( params ) compound-stmt (在課后解釋中compound-stmt前面沒(méi)有“|”符號(hào)) </p><p> 7. params → params-list | void </p><p&
20、gt; 8. param-list → param-list , param | param </p><p> 9. param → type-specifier ID | type-specifier ID [ ] </p><p> 10. compound-stmt → { local-declarations statement-list } </p><
21、;p> 11. local-declarations → local-declarations var-declaration | empty </p><p> 12. statement-list → statement-list statement | empty </p><p> 13. statement → expression-stmt | compound-s
22、tmt | selection-stmt | </p><p> iteration-stmt | return-stmt </p><p> 14. expression-stmt → expression ; | ; </p><p> 15. selection-stmt → if ( expression ) statement | if ( expr
23、ession ) </p><p> statement else statement </p><p> 16. iteration-stmt → while(expression) statement </p><p> 17. return-stmt → return ; | return expression ; </p><p&g
24、t; 18. expression → var = expression | simple-expression </p><p> 19. var → ID | ID [ expression ] </p><p> 20. simple-expression → additive-expression relop additive-expression | </p>
25、<p> additive-expression </p><p> 21. relop → <= | < | > | >= | == | != </p><p> 22. additive-expression → additive-expression addop term | term </p><p> 23. a
26、ddop → + | - </p><p> 24. term → term mulop factor | factor </p><p> 25. mulop → * | / </p><p> 26. factor → ( expression ) | var | call | NUM </p><p> 27. call → I
27、D ( args ) </p><p> 28. args → arg-list | empty </p><p> 29. arg-list → arg-list , expression | expression </p><p> 2.2.2.2、實(shí)驗(yàn)方法:</p><p> 本次試驗(yàn)完成parse方法我采用的是遞歸下降的方法。
28、根據(jù)C- 語(yǔ)言的規(guī)則,我們可以得出C- 語(yǔ)言語(yǔ)法的EBNF。下面是我在代碼中所使用的自己整理出來(lái)的語(yǔ)法規(guī)則:</p><p> 注:{ }為重復(fù)[ ]為選擇,{}為本來(lái)的意思</p><p> 1. program → declaration-list </p><p> 2. declaration-list → declaration { declarat
29、ion }</p><p> 3. declaration → int|void|empty ID [factor];| (params)compound-stmt</p><p> 4. params → params-list | void </p><p> 5. param-list → param { param }</p><
30、;p> 6. param → int|void ID empty|[] </p><p> 7. compound-stmt → { local-declarations statement-list } </p><p> 8. local-declarations → { declaration }|empty</p><p> 9. stat
31、ement-list → { statement }|empty </p><p> 10. statement → expression-stmt | compound-stmt | selection-stmt | </p><p> iteration-stmt | return-stmt </p><p> 11. expression-stmt →
32、expression ; | ; </p><p> 12. selection-stmt → if ( expression ) statement { else statement }</p><p> 13. iteration-stmt → while(expression) statement </p><p> 14. return-stmt →
33、return ;|expression ; </p><p> 15. expression → simple-expression { = expression }</p><p> 16. var → ID [ [ expression ] ] </p><p> 17. simple-expression → additive-expression {
34、 relop additive-expression }</p><p> 18. relop → <= | < | > | >= | == | != </p><p> 19. additive-expression → additive-expression { addop term } </p><p> 20. addop →
35、+ | - </p><p> 21. term → term mulop { factor } </p><p> 22. mulop → * | / </p><p> 23. factor → ( expression ) | NUM | ID (args)|[expression]|empty</p><p> 24.
36、 args → arg-list | empty </p><p> 25. arg-list → expression{ expression } </p><p> 其中,3條declaration15條expression和23條factor是重點(diǎn)修改內(nèi)容。</p><p> 2.2.2.3、編程方法:</p><p><b
37、> 編程采用C語(yǔ)言。</b></p><p> 分析從program開(kāi)始,逐層向下擴(kuò)展。依靠下一步所得到的token,根據(jù)整理過(guò)后的語(yǔ)法規(guī)則來(lái)判斷語(yǔ)法樹(shù)的結(jié)點(diǎn)生成與走向。并且根據(jù)語(yǔ)法規(guī)則來(lái)確定語(yǔ)法樹(shù)的末結(jié)點(diǎn)的內(nèi)容。</p><p> 此處的難點(diǎn)在于語(yǔ)法規(guī)則的整理。若是按照書(shū)上原來(lái)的29條語(yǔ)法規(guī)則來(lái)寫(xiě),就會(huì)發(fā)現(xiàn)在樹(shù)的生成方法與邏輯上會(huì)很難實(shí)現(xiàn)。最開(kāi)始時(shí)我便參照著原29
38、條語(yǔ)法規(guī)則來(lái)寫(xiě)的,雖然全程序都沒(méi)有報(bào)錯(cuò),但是分析程序時(shí)一直分析不了。最后停下編程來(lái)從筆頭整理了一陣子語(yǔ)法規(guī)則后,語(yǔ)法分析程序可以分析了,只有個(gè)別錯(cuò)誤了。再不斷地在每一個(gè)結(jié)點(diǎn)生成時(shí)fprintf(listing,”\n-------its XXXX time\n”)一下,逐步排查錯(cuò)誤,最終才確定了剩下的這25個(gè)語(yǔ)法規(guī)則。</p><p> 2.2.3、代碼設(shè)計(jì)說(shuō)明</p><p> 程序
39、globals files包里面分為Source Files文件夾和Header Files文件夾</p><p> Source Files文件夾中包含:main.c ;parse.c ;scan.c ;util.c</p><p> Header Files文件夾中包含:globals.h ;parse.h ;scan.h ;util.h</p><
40、p><b> 其中:</b></p><p> main.c負(fù)責(zé)程序的執(zhí)行方式(cmd命令行下執(zhí)行g(shù)lobals.exe +測(cè)試代碼文件名)</p><p> globals.h負(fù)責(zé)treeNode的聲明,TokenType類(lèi)型的聲明,與NodeKind等的聲明</p><p> util.c負(fù)責(zé)新結(jié)點(diǎn)的構(gòu)造,詞法的輸出,語(yǔ)法的輸
41、出,以及輸出顯示的布局</p><p> void printToken( TokenType token, const char * tokenString) {}</p><p> //根據(jù)書(shū)上原型做的,但根據(jù)語(yǔ)法規(guī)則所需要的,做過(guò)大量修改</p><p> TreeNode * newStmtNode(StmtKind kind) {}</p>
42、;<p> //根據(jù)書(shū)上原型做的,未經(jīng)修改</p><p> TreeNode * newExpNode(ExpKind kind) {}</p><p> //根據(jù)書(shū)上原型做的,未經(jīng)修改</p><p> TreeNode * newParamNode(void) {}</p><p> //自己根據(jù)所需建立<
43、/p><p> TreeNode * newDecNode(void) {}</p><p> //自己根據(jù)所需建立</p><p> char * copyString(char * s) {}</p><p> //根據(jù)書(shū)上原型做的,未經(jīng)修改</p><p> static void printSpaces(
44、void) {}</p><p> //根據(jù)書(shū)上原型做的,未經(jīng)修改</p><p> void printTree( TreeNode * tree ){}</p><p> //根據(jù)書(shū)上原型做的,但根據(jù)語(yǔ)法規(guī)則所需要的,做過(guò)大量修改</p><p> util.h負(fù)責(zé)util.c中所用函數(shù)的聲明</p><p&g
45、t; scan.c負(fù)責(zé)詞法狀態(tài)的聲明,詞法的分析</p><p> typedef enum {START,INASSIGN_1,L_ASSIGN,R_ASSIGN,</p><p> E_ASSIGN,N_ASSIGN,INASSIGN_2,INCOMMENT,</p><p> INNUM,INID,DONE} StateType;</p>
46、<p> //根據(jù)書(shū)上原型做的,但根據(jù)語(yǔ)法規(guī)則所需要的,做過(guò)大量修改</p><p> static int getNextChar(void) {}</p><p> //根據(jù)書(shū)上原型做的,未經(jīng)修改</p><p> static void ungetNextChar(void) {}</p><p> //根據(jù)書(shū)上原
47、型做的,未經(jīng)修改</p><p> static struct {char* str;TokenType tok;} reservedWords[MAXRESERVED] = </p><p> {"if",IF},{"else",ELSE},{"int",INT},{"return",RETURN},{
48、"void",VOID},{"while",WHILE}};</p><p> //根據(jù)書(shū)上原型做的,但根據(jù)語(yǔ)法規(guī)則所需要的,做過(guò)大量修改</p><p> static TokenType reservedLookup (char * s) {}</p><p> //根據(jù)書(shū)上原型做的,未經(jīng)修改</p>
49、<p> TokenType getToken(void) {}</p><p> //根據(jù)書(shū)上原型做的,但根據(jù)語(yǔ)法規(guī)則所需要的,做過(guò)大量修改</p><p> scan.h負(fù)責(zé)對(duì)scan.c中所用函數(shù)的聲明</p><p> parse.c負(fù)責(zé)語(yǔ)法樹(shù)的分析</p><p> static void syntaxError
50、(char * message) {}</p><p> //根據(jù)書(shū)上原型做的,未經(jīng)修改</p><p> static void match(TokenType expected) {}</p><p> //根據(jù)書(shū)上原型做的,未經(jīng)修改</p><p> //以下的全部為自己所寫(xiě)</p><p> stat
51、ic TreeNode * program(void);</p><p> static TreeNode * declaration_list(void);</p><p> static TreeNode * declaration(void);</p><p> static TreeNode * params(void);<
52、/p><p> static TreeNode * param_list(void);</p><p> static TreeNode * param(void);</p><p> static TreeNode * compound_stmt(void);</p><p> static TreeNode * local_
53、declaration(void);</p><p> static TreeNode * statement_list(void);</p><p> static TreeNode * statement(void);</p><p> static TreeNode * expression_stmt(void);</p>&l
54、t;p> static TreeNode * selection_stmt(void);</p><p> static TreeNode * iteration_stmt(void);</p><p> static TreeNode * return_stmt(void);</p><p> static TreeNode * expr
55、ession(void);</p><p> static TreeNode * var(void);</p><p> static TreeNode * simple_expression(void);</p><p> static TreeNode * additive_expression(void);</p>&l
56、t;p> static TreeNode * term(void);</p><p> static TreeNode * factor(void);</p><p> static TreeNode * args(void);</p><p> static TreeNode * arg_list(void);</p>&
57、lt;p> parse.h負(fù)責(zé)parse.c中所用函數(shù)的聲明</p><p> 此次所做程序輸入格式為:</p><p> cmd命令行下執(zhí)行g(shù)lobals.exe +測(cè)試代碼文件名</p><p><b> 輸出地方:</b></p><p><b> cmd命令行</b><
58、/p><p><b> 輸出內(nèi)容:</b></p><p><b> 詞法分析與語(yǔ)法樹(shù)</b></p><p><b> 3、程序代碼實(shí)現(xiàn)</b></p><p> 3.1、獲取輸入部分(在main.c中):</p><p> 此處因?yàn)椴⑽从兴薷?/p>
59、,均參照附錄B所寫(xiě),所以略去。</p><p> 3.2、詞法分析部分(在scan.c中):</p><p> 其中部分代碼因?yàn)閰⒄崭戒汢中內(nèi)容而未修改,所以略去。</p><p> typedef enum {//此處便如2.2.1.2圖所示,定義11個(gè)中間狀態(tài),其中INASSIGN分成了L_ASSIGN,R_ASSIGN,而在分析注釋結(jié)束時(shí)添加了INASS
60、IGN_2狀態(tài)</p><p> E_ASSIGN,N_ASSIGN,</p><p> START,INASSIGN_1,L_ASSIGN,R_ASSIGN,</p><p> E_ASSIGN,N_ASSIGN,INASSIGN_2,INCOMMENT,</p><p> INNUM,INID,DONE</p>&l
61、t;p> } StateType;</p><p> static struct {char* str;TokenType tok;} reservedWords[MAXRESERVED] = </p><p> {{"if",IF},{"else",ELSE},{"int",INT},{"return&
62、quot;,RETURN},{"void",VOID},{"while",WHILE}};//此處根據(jù)C- 的保留字做了一定的修改</p><p> TokenType getToken(void) {//獨(dú)立完成</p><p> int tokenStringIndex = 0;</p><p> TokenTyp
63、e currentToken;</p><p> StateType state = START;</p><p><b> int save;</b></p><p> while (state !=DONE) {</p><p> int c = getNextChar();</p><p
64、> save = TRUE;</p><p> //fprintf(listing,"\nScanner: state = %d\n",state);//測(cè)試每一步狀態(tài)</p><p> switch (state) {</p><p> case START:</p><p> if(isdigit(c)
65、)</p><p> state = INNUM;//是數(shù)字</p><p> else if(isalpha(c))</p><p> state = INID;//是ID</p><p> //fprintf(listing,"\n--is alpha\n");}//測(cè)試是否進(jìn)行到此處</p>
66、<p> else if(c == '/') {</p><p> save = FALSE;</p><p> state = INASSIGN_1;//判斷注釋</p><p> //fprintf(listing,"\n--is /\n");</p><p><b&g
67、t; }</b></p><p> else if((c == ' ') || (c == '\t') || (c == '\n'))</p><p> save = FALSE;</p><p> else if(c == '<') {</p><p>
68、; save = FALSE;</p><p> state = L_ASSIGN;</p><p><b> }</b></p><p> else if(c == '>') {</p><p> save = FALSE;</p><p> state = R
69、_ASSIGN;</p><p><b> }</b></p><p> else if(c == '=') {</p><p> save = FALSE;</p><p> state = E_ASSIGN;</p><p><b> }</b>
70、</p><p> else if(c == '!') {</p><p> save = FALSE;</p><p> state = N_ASSIGN;</p><p><b> }</b></p><p><b> else {</b><
71、;/p><p> state = DONE;</p><p> switch(c) {</p><p><b> case EOF:</b></p><p> save = FALSE;</p><p> currentToken = ENDFILE;</p><p>
72、;<b> break;</b></p><p><b> case ',':</b></p><p> currentToken = COM;</p><p><b> break;</b></p><p><b> case '=
73、':</b></p><p> currentToken = EQ;</p><p><b> break;</b></p><p><b> case '+':</b></p><p> currentToken = PLUS;</p>&
74、lt;p><b> break;</b></p><p><b> case '-':</b></p><p> currentToken = MINUS;</p><p><b> break;</b></p><p><b> ca
75、se '*':</b></p><p> currentToken = TIMES;</p><p><b> break;</b></p><p><b> case '(':</b></p><p> currentToken = LPAREN
76、_3;</p><p><b> break;</b></p><p><b> case ')':</b></p><p> currentToken = RPAREN_3;</p><p><b> break;</b></p><
77、;p><b> case '[':</b></p><p> currentToken = LPAREN_2;</p><p><b> break;</b></p><p><b> case ']':</b></p><p>
78、 currentToken = RPAREN_2;</p><p><b> break;</b></p><p><b> case '{':</b></p><p> currentToken = LPAREN_1;</p><p><b> break;<
79、;/b></p><p><b> case '}':</b></p><p> currentToken = RPAREN_1;</p><p><b> break;</b></p><p><b> case ';':</b>
80、</p><p> currentToken = SEMI;</p><p><b> break;</b></p><p><b> default:</b></p><p> currentToken = ERROR;</p><p><b> bre
81、ak;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> break;</b></p><p> case INCOMMENT:</p><p> save = FALSE
82、;</p><p> if (c == EOF) {</p><p> state = DONE;</p><p> currentToken = ENDFILE;</p><p><b> }</b></p><p> else if (c=='*') state =
83、INASSIGN_2;//判斷 出 注釋</p><p> else state = INCOMMENT;</p><p><b> break;</b></p><p> case INASSIGN_1:</p><p> if (c == '*') {</p><p>
84、 //fprintf(listing,"\n--is zs\n");</p><p> save = FALSE;</p><p> state = INCOMMENT;//是注釋</p><p><b> }</b></p><p><b> else {</b>&
85、lt;/p><p> state = DONE;</p><p> ungetNextChar();//char停住,否則會(huì)令“/”號(hào)后面的char讀不出來(lái)</p><p> currentToken = OVER;</p><p><b> }</b></p><p><b>
86、break;</b></p><p> case INASSIGN_2:</p><p> if (c == '/') {//是 出 注釋</p><p> save = FALSE;</p><p> state = START;</p><p><b> }</
87、b></p><p> else state = INCOMMENT;//不是,返回注釋</p><p><b> break;</b></p><p> case L_ASSIGN:</p><p> if(c == '=') </p><p> currentT
88、oken = LET;</p><p> else currentToken = LT;</p><p> state = DONE;</p><p><b> break;</b></p><p> case R_ASSIGN:</p><p> if(c == '='
89、) </p><p> currentToken = BET;</p><p> else currentToken = BT;</p><p> state = DONE;</p><p><b> break;</b></p><p> case E_ASSIGN:</p>
90、;<p> if(c == '=') </p><p> currentToken = EQ;</p><p> else currentToken = ASSIGN;</p><p> state = DONE;</p><p><b> break;</b></p>
91、<p> case N_ASSIGN:</p><p> if(c == '=') </p><p> currentToken = NEQ;</p><p> else ungetNextChar();</p><p> state = DONE;</p><p><b&
92、gt; break;</b></p><p> case INNUM:</p><p> if (!isdigit(c)) {</p><p> ungetNextChar();</p><p> save = FALSE;</p><p> state = DONE;</p>&
93、lt;p> currentToken = NUM;</p><p><b> }</b></p><p><b> break;</b></p><p> case INID:</p><p> if (!isalpha(c)) {</p><p> //
94、fprintf(listing,"\n--is ID over\n");</p><p> ungetNextChar();</p><p> save = FALSE;</p><p> state = DONE;</p><p> currentToken = ID;</p><p>&
95、lt;b> }</b></p><p><b> break;</b></p><p> case DONE:</p><p><b> default:</b></p><p> fprintf(listing,"Scanner Bug: state = %d
96、\n",state);</p><p> state = DONE;</p><p> currentToken = ERROR;</p><p><b> break;</b></p><p><b> }</b></p><p> //fprintf
97、(listing,"out switch");</p><p> //getchar();</p><p> if ((save) && (tokenStringIndex <= MAXTOKENLEN))</p><p> tokenString[tokenStringIndex++] = (char) c;<
98、;/p><p> if (state == DONE) {</p><p> tokenString[tokenStringIndex] = '\0';</p><p> if(currentToken == ID)</p><p> currentToken = reservedLookup(tokenString);&
99、lt;/p><p><b> }</b></p><p><b> }</b></p><p> if (TraceScan) {</p><p> fprintf(listing,"\n%d: ",lineno);</p><p> printTo
100、ken(currentToken,tokenString);</p><p><b> }</b></p><p> return currentToken;</p><p><b> }</b></p><p> 3.3、語(yǔ)法分析部分(在parse.c中):</p><
101、p> 其中部分代碼因?yàn)閰⒄崭戒汢中內(nèi)容而未修改,所以略去。</p><p> TreeNode * stmt_program(void) {</p><p> //program -> declaration-list</p><p> TreeNode * t = declaration_list();</p><p>
102、<b> return t;</b></p><p><b> }</b></p><p> TreeNode * declaration_list(void) {</p><p> //declaration-list -> declaration-list declaration | declarati
103、on</p><p> // declaration{declaration}</p><p> TreeNode * t = NULL;</p><p> TreeNode * p = NULL;</p><p> TreeNode * q = NULL;</p><p> //fprintf(li
104、sting,"\n------------------------its dec_li time\n");</p><p> //fprintf(listing,"\n+++++%s+++++\n",tokenString);//此兩處語(yǔ)句用于程序最初的運(yùn)行測(cè)試,基本上每一個(gè)函數(shù)里都有,用來(lái)測(cè)試哪一步有問(wèn)題</p><p> if(token!
105、=ENDFILE&&(token==INT||token==VOID)) {</p><p> t = declaration();</p><p><b> p = t;</b></p><p> while (token!=ENDFILE&&(token==INT||token==VOID)) {<
106、;/p><p> q = declaration();</p><p> if(q!=NULL) {</p><p> if(t == NULL) t = p = q;</p><p><b> else {</b></p><p> p->sibling = q;</p>
107、<p><b> p = q;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p>
108、<p><b> return t;</b></p><p><b> }</b></p><p> TreeNode * declaration(void) {</p><p> //declaration -> var-declaration | fun-declaration
109、</p><p> // (int|void) ID [[NUM]]; | ((int|void) ID (params) compound-stmt)</p><p> // int a[]; | int a; | void a?;| void main (void) | int gcd (int a[],int b) | { {var-declaration} {sta
110、tement(if,while...)} }//此處曾糾結(jié)過(guò)很久,最后發(fā)現(xiàn)附錄A開(kāi)始陳列29條語(yǔ)法部分和后來(lái)詳解29條語(yǔ)法時(shí)有不同的地方。compound-stmt前面的“|”沒(méi)了。。。十分無(wú)語(yǔ)。而且這里是個(gè)難點(diǎn)。我發(fā)現(xiàn)如果真的有var-declaration那些東西又麻煩又累贅,就去掉了幾句語(yǔ)法</p><p> //&&var-declaration&&type_specif
111、ier&&fun_declaration</p><p> TreeNode * t = newDecNode();</p><p> //fprintf(listing,"\n------------------------its dec time\n");</p><p> //fprintf(listing,&qu
112、ot;\n+++++%s+++++\n",tokenString);</p><p> switch(token) {</p><p><b> case INT:</b></p><p> t -> attr.type = "int";</p><p> match(INT)
113、;</p><p><b> break;</b></p><p> case VOID:</p><p> t -> attr.type = "void";</p><p> match(VOID);</p><p><b> break;</
114、b></p><p><b> case EOF:</b></p><p><b> return t;</b></p><p><b> default:</b></p><p> syntaxError("unexpected token in Ty
115、pe-> ");</p><p> printToken(token,tokenString);</p><p> token = getToken();</p><p><b> break;</b></p><p><b> }</b></p><p&
116、gt; // fprintf(listing,"\n+++++%s+++++\n",tokenString);</p><p> t -> attr.name = copyString(tokenString);</p><p> match(ID);</p><p> // fprintf(listing,"
117、;\n+++++%s+++++\n",tokenString);</p><p> switch(token) {</p><p> case LPAREN_2:</p><p> t -> kind.dec = ArrayK;</p><p> t -> child[0] = factor();</p&g
118、t;<p> match(RPAREN_2);</p><p> match(SEMI);</p><p><b> break;</b></p><p> case SEMI:</p><p> t -> kind.dec = VarK;</p><p> mat
119、ch(SEMI);</p><p><b> break;</b></p><p> case LPAREN_3:</p><p> match(LPAREN_3);</p><p> //fprintf(listing,"\n+++++%s+++++\n",tokenString);&l
120、t;/p><p> t -> kind.dec = FunK;</p><p> if(t!=NULL) t->child[0] = params();</p><p> match(RPAREN_3);</p><p> // fprintf(listing,"\n+++++%s+++++\n",
121、tokenString);</p><p> if(t!=NULL) t->child[1] = compound_stmt();</p><p><b> break;</b></p><p><b> default:</b></p><p> syntaxError("
122、declaration wrong");</p><p> token = getToken();</p><p><b> break;</b></p><p><b> }</b></p><p><b> return t;</b></p>
123、<p><b> }</b></p><p> TreeNode * params(void) {</p><p> TreeNode * t = newParamNode();</p><p> //fprintf(listing,"\n------------------------its par time\
124、n");</p><p> //fprintf(listing,"\n+++++%s+++++\n",tokenString);</p><p> switch(token) {</p><p> case VOID:</p><p> t ->attr.type = copyString(tok
125、enString);</p><p> match(VOID);</p><p><b> break;</b></p><p><b> default:</b></p><p> t -> kind.param = UNull;</p><p> t -&
126、gt;child[0] = param_list();</p><p><b> break;</b></p><p><b> }</b></p><p><b> return t;</b></p><p><b> }</b></p&g
127、t;<p> TreeNode * param_list(void) {</p><p> TreeNode * t = param();</p><p> TreeNode * p = t;</p><p> //fprintf(listing,"\n------------------------its par_l time\n
128、");</p><p> //fprintf(listing,"\n+++++%s+++++\n",tokenString);</p><p> while ( (token != RPAREN_3) && ( token != ENDFILE )) {</p><p> TreeNode * q;</p&
129、gt;<p> match(COM);</p><p> q = param();</p><p> if (q != NULL) {</p><p> if (t == NULL) t = p = q;</p><p><b> else {</b></p><p>
130、p->sibling = q;</p><p><b> p = q;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><
131、b> return t;</b></p><p><b> }</b></p><p> TreeNode * param(void) {</p><p> TreeNode * t = newParamNode();//這是參數(shù)結(jié)點(diǎn),區(qū)別與聲明結(jié)點(diǎn)</p><p> //fprintf(l
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- c-minus詞法分析和語(yǔ)法分析設(shè)計(jì)編譯器編譯原理課程設(shè)計(jì)
- 編譯原理詞法分析器語(yǔ)法分析課程設(shè)計(jì)
- 編譯原理課程設(shè)計(jì)-詞法語(yǔ)法分析器
- 語(yǔ)法分析課程設(shè)計(jì)---編譯原理語(yǔ)法分析器的設(shè)計(jì)與實(shí)現(xiàn)
- C編譯器語(yǔ)法分析的設(shè)計(jì)與實(shí)現(xiàn).pdf
- 編譯原理課程設(shè)計(jì)(c++)-語(yǔ)法分析器
- 編譯原理課程設(shè)計(jì)--pascal語(yǔ)言詞法、語(yǔ)法分析器設(shè)計(jì)
- 編譯原理課程設(shè)計(jì)--- 語(yǔ)法分析器
- 編譯原理課程設(shè)計(jì)---語(yǔ)法分析器
- 編譯原理課程設(shè)計(jì)--語(yǔ)法分析器
- 編譯原理語(yǔ)法分析器課程設(shè)計(jì)
- 編譯原理課程設(shè)計(jì)--c語(yǔ)言編譯器實(shí)現(xiàn)
- 編譯原理課程設(shè)計(jì)--c語(yǔ)言編譯器實(shí)現(xiàn)
- c語(yǔ)言編譯器實(shí)現(xiàn)-編譯原理課程設(shè)計(jì)
- 編譯原理課程設(shè)計(jì)____c語(yǔ)言編譯器的實(shí)現(xiàn)-
- 編譯原理課程設(shè)計(jì)---c語(yǔ)言編譯器的實(shí)現(xiàn)
- 編譯原理課程設(shè)計(jì)---編譯器的實(shí)現(xiàn)
- 編譯原理課程設(shè)計(jì)報(bào)告--編譯器實(shí)現(xiàn)
- 編譯原理課程設(shè)計(jì)--編譯器
- 編譯原理課程設(shè)計(jì)---簡(jiǎn)單編譯器的設(shè)計(jì)與實(shí)現(xiàn)
評(píng)論
0/150
提交評(píng)論