編譯原理課程設(shè)計(jì)報(bào)告畢業(yè)論文_第1頁
編譯原理課程設(shè)計(jì)報(bào)告畢業(yè)論文_第2頁
編譯原理課程設(shè)計(jì)報(bào)告畢業(yè)論文_第3頁
編譯原理課程設(shè)計(jì)報(bào)告畢業(yè)論文_第4頁
編譯原理課程設(shè)計(jì)報(bào)告畢業(yè)論文_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

編譯原理課程設(shè)計(jì)報(bào)告課程設(shè)計(jì)目的通過課程設(shè)計(jì),可以進(jìn)一步了解高級(jí)語言在計(jì)算機(jī)中的執(zhí)行過程,了解現(xiàn)代編譯器的運(yùn)行機(jī)制,加深對編譯原理中關(guān)鍵算法和編譯技術(shù)的理解,提高自學(xué)和理解能力。了解如何利用現(xiàn)有軟件JFLex和Java_cup構(gòu)造詞法分析器和解析器。設(shè)計(jì)概述這個(gè)tiger語言編譯器的編譯過程涉及到編譯五個(gè)階段中的兩個(gè),即詞法分析器和語法分析器。其中,解析后完成語法樹打印的構(gòu)建,以檢查類型。詞法分析器由JFLex編譯器正則公式生成,詞法分析器由編譯器產(chǎn)生式生成,解析器由CUP生成。結(jié)果通過GUI界面呈現(xiàn)給用戶。編譯器需要對源程序進(jìn)行單詞級(jí)的分析和翻譯,所以首先要做的就是識(shí)別單詞,而詞法分析的任務(wù)就是從左到右掃描源程序的字符串,根據(jù)詞法規(guī)則(常規(guī)語法規(guī)則)識(shí)別出正確的單詞,并轉(zhuǎn)換成單詞對應(yīng)的二進(jìn)制形式(類別碼,屬性值)進(jìn)行語法分析。所以詞法分析是編譯的基礎(chǔ)。執(zhí)行詞法分析的程序叫做詞法分析器。語法分析是編譯器的核心部分。它的主要任務(wù)是確定語法結(jié)構(gòu),檢查語法錯(cuò)誤,報(bào)告錯(cuò)誤的性質(zhì)和位置,并進(jìn)行適當(dāng)?shù)募m錯(cuò)。設(shè)計(jì)程序設(shè)計(jì)構(gòu)思該程序主要完成三個(gè)功能模塊:詞法分析器、語法分析器和GUI人機(jī)界面。詞法分析器由JFLex編譯正則公式生成,其中必須為外界提供一個(gè)獲取令牌流的接口。實(shí)驗(yàn)中命名為Java_cup.runtime.symbolnext_token。解析器是建立在詞法分析器上的,所以它必須包含詞法分析器來獲取令牌流。next_token為解析器提供了令牌。解析器的對外接口是:Java_cup.runtime.symboldebug_parse(),它返回語法樹的根節(jié)點(diǎn)。GUI提供人機(jī)交互。它可以順序顯示詞法分析階段獲得的所有標(biāo)記信息和語法階段生成的語法樹。此外,詞法和語法階段的錯(cuò)誤會(huì)在“錯(cuò)誤提示”文本框中列出,為用戶提供改進(jìn)代碼的信息。流程圖:GUIGUI界面程序輸入流詞匯錯(cuò)誤程序輸入流詞匯錯(cuò)誤詞法分析程序標(biāo)記流詞法分析程序標(biāo)記流代幣代幣句法分析程序語法樹句法分析程序語法樹錯(cuò)誤的語法和類型。錯(cuò)誤的語法和類型。和類文件描述:鮑·阿布辛Print.java//打印出語法樹……//Tiger的抽象語法類數(shù)據(jù)包錯(cuò)誤消息ErrorMsg.java//用于生成包含詳細(xì)信息的錯(cuò)誤消息為cupparser打包Java_cup.runtime//support包解析Grm.java//解析分析器MainInterface.java//圖形用戶界面Sym.java//令牌的十進(jìn)制表示Yylex.java//萊克斯分析器包裝語義Entry.java//用于值環(huán)境中的綁定Env.java//保存一個(gè)值、類型環(huán)境和一個(gè)錯(cuò)誤打印機(jī)ExpTy.java//持有翻譯和類型檢查的結(jié)果FunEntry.java//用于函數(shù)綁定Semant.java//主類型檢查模塊VarEntry.java//用于變量綁定包裝符號(hào)Symbol.java//使字符串成為獨(dú)特的符號(hào)對象Table.java//用示波器做環(huán)境包翻譯包類型//描述tiger_languagetypes詞法分析程序這部分工作主要是通過正則表達(dá)式的編寫,熟悉使用JFLex正確編寫正則表達(dá)式,并生成相應(yīng)的詞法分析器。JFLex的使用修改jflex-1.4.2\bin,Java_home=%Java_home%\lib\classes.zip中jflex.bat文件中的參數(shù);JFLEX_HOME=%JFLEX_HOME%\lib\JFLEX.jar;運(yùn)行jflex.bat并選擇輸入文件(tiger.jlex)。如果沒有錯(cuò)誤,它會(huì)在輸出目錄中生成一個(gè)Yylex.java的詞法分析器。tiger.jlex文件開頭的書寫格式如下:包解析;//在Parse下打包詞法分析器導(dǎo)入錯(cuò)誤消息。ErrorMsg//導(dǎo)入類%%%cup//支持與cup的關(guān)聯(lián)%line//支持yyline()調(diào)用。%column//支持yycolumn()調(diào)用。%char%state注釋,STRING//聲明兩個(gè)新狀態(tài)%{//設(shè)置所有可能的詞法錯(cuò)誤類型stringbufferstr=newstringbuffer();私有靜態(tài)最終字符串錯(cuò)誤M[]={"錯(cuò)誤:注釋結(jié)尾標(biāo)點(diǎn)不匹配.","錯(cuò)誤:注釋開頭標(biāo)點(diǎn)不匹配.","錯(cuò)誤:未閉合的字符串。","錯(cuò)誤:非法字符。"};privatenewline(){//保持errormsg中行號(hào)記錄變量的正確性。errormsg.newline(YYchar);}privateerr(strings){…}//通過errormsg報(bào)告錯(cuò)誤 privateJava_cup.runtime.symbolTok(intkind,Objectvalue){返回newJava_cup.runtime.symbol(kind,yychar,yychar+yylength(),value);//返回已識(shí)別的令牌}publicYYlex(Java.io.filereaders,ErrorMsge){這(些);//重載Yylex構(gòu)造函數(shù)以方便錯(cuò)誤輸出errormsg=e;}privateErrorMsgerrorMsg//ErrorMsg對象聲明privateintcomment_count=0;//變量,用于處理批注嵌套%}%eofval{{//當(dāng)?shù)竭_(dá)文件末尾時(shí),判斷最后的狀態(tài)是否為YYINITIAL,如果不是,則報(bào)告相應(yīng)的錯(cuò)誤。if(zzLexicalState!=0){開關(guān)(zzLexicalState){情況二:{err(errorm[E_startcomment]);打破;}情況4:{err(errorm[E_unclosedstr]);打破;}默認(rèn)值:{/*什么都不做*/}}}返回tok(sym。EOF,null);}%eofval}//一些基本類型簡化了表達(dá)式的定義ALPHA=[A-Za-z]//字母DIGIT=[0-9]//數(shù)字LINE_TERMINATOR=\r|\n|\r\n//newlineNonnewline_white_space_char=[\\t\f\b\012]//非換行空格WHITE_SPACE_CHAR={LINE_TERMINATOR}|nonnewline_WHITE_SPACE_CHAR}//空白%%正則表達(dá)式的編寫Tiger需要識(shí)別的變量和字符有:整數(shù)常量、字符常量、運(yùn)算符、括號(hào)、分隔符、關(guān)鍵字、標(biāo)識(shí)符和注釋。整數(shù)常量: 整數(shù),即任意字母組合。字符常量: 雙引號(hào)中的字符可以跨行,但行尾必須以\結(jié)尾,以\開頭。性格;角色;字母 常數(shù)的中間可以包含轉(zhuǎn)義字符,例如:\r\n\t\f\"\\xyzx,y,z表示從0到127的整數(shù)。運(yùn)算符:+-*/>>=<==:=&|括起來的字符:(){}[]分隔符: ;:關(guān)鍵字:whiledofortoifelsethenletinendtypevar數(shù)組breaknil函數(shù)標(biāo)識(shí)符:以一個(gè)字符開始,添加字符、數(shù)字和下劃線的任意組合。備注:以/*開頭,以*/結(jié)尾。您可以在中間嵌套任何數(shù)字,但它必須是封閉的。通用字符或保留字只需返回其名稱。比如在YYINITAIL的狀態(tài)下,如果最長的匹配字符串被識(shí)別為“array”,就會(huì)直接返回token,數(shù)字就是sym.java定義的數(shù)字。書面格式如下:<YYinitial>"array"{returnTok(sym。數(shù)組,null);}下面重點(diǎn)介紹字符串和注釋的處理:字符串的處理:在YYINITIAL狀態(tài)下遇到“表示開始識(shí)別字符常量。這時(shí)就需要進(jìn)入之前聲明的字符串狀態(tài)。之前聲明的字符串str用于存儲(chǔ)識(shí)別的字符常量(初始化為null)。代碼如下:<YYinitial>\"{str.setlength(0);yybegin(字符串);}如果在識(shí)別過程中遇到轉(zhuǎn)義符\n\t\"\\,則在str后添加相應(yīng)的字符,在str后直接添加非轉(zhuǎn)移字符,忽略兩個(gè)反斜杠之間的所有空白字符。代碼如下:<string>[^\n\r\"\\]+{str.append(YYtext());}<STRING>\\n{str.append('\n');}<STRING>\\\\{str.append('\\');}<STRING>\\{WHITE_SPACE_CHAR}+\\{/*什么都不做*/}尤其是說到\跟上三位數(shù),要判斷數(shù)值范圍是否在ASCII范圍內(nèi)。 <STRING>\\0{DIGIT}{DIGIT}|\\1[0-1]{DIGIT}|\\12[0-7]{str.append((char)integer.valueof(新字符串(yytext()。getBytes(),1,3))。intvalue());}當(dāng)再次識(shí)別“時(shí),它標(biāo)志著字符串識(shí)別的結(jié)束。此時(shí)str中的字符串容量將作為字符串的容量返回,同時(shí)要返回YYINITIAL狀態(tài)繼續(xù)識(shí)別其他TOKEN。<字符串>\"{YYbegin(YYinitial);返回tok(sym。STRING,str.tostring());}如果識(shí)別了這些標(biāo)記以外的其他字符,將直接報(bào)告錯(cuò)誤。<字符串>。{err(errom[E_ILLEGAL]);}評論的處理:當(dāng)在YYINITIAL狀態(tài)中遇到/*時(shí),它指示注釋識(shí)別的開始。此時(shí)需要進(jìn)入之前聲明的注釋狀態(tài),同時(shí)comment_count加1,實(shí)現(xiàn)注釋嵌套。如果/*在注釋狀態(tài)下再次被識(shí)別,表示另一個(gè)注釋嵌套的開始,此時(shí)也有必要用下面的代碼將comment_count加1:<YYINITIAL>"/*"{yybegin(評論);comment_count=comment_count+1;}<COMMENT>"/*"{COMMENT_count=COMMENT_count+1;}但是,如果在YYINITIAL狀態(tài)下遇到*/則是錯(cuò)誤,需要報(bào)告。代碼如下:<YYinitial>"*/"{err(errrm[E_endcomment]);}在注釋狀態(tài)中遇到*/表示嵌套注釋的結(jié)束。這時(shí)候就需要從comment_count中減去1。如果操作后其值為0,則表示整個(gè)注釋已經(jīng)結(jié)束,將返回YYINITIAL狀態(tài)。否則在評論狀態(tài)下會(huì)繼續(xù)被識(shí)別。代碼如下:<注釋>“*/”{comment_count=注釋_計(jì)數(shù)-1;if(comment_count==0)YYbegin(YYinitial);}如果識(shí)別了除這些標(biāo)記之外的其他字符,它們將被直接忽略。<評論>。{/*什么都不做*/}詞法分析器的結(jié)構(gòu)詞法分析器實(shí)現(xiàn)了Lexer接口,也就是實(shí)現(xiàn)了tokenext_token()方法,通過連續(xù)調(diào)用這個(gè)方法可以得到所有的令牌流。使用詞法分析器時(shí),需要用ErrorMsg和InputStream指定InputStream讀取源程序,用ErrorMsg輸出錯(cuò)誤信息。至此,詞法分析器的構(gòu)建基本完成。句法分析程序完成解析器的主要步驟是編譯cup文件。由于已經(jīng)給出了語法樹的數(shù)據(jù)結(jié)構(gòu),制作時(shí)可以直接參考老虎語言的語法模式。當(dāng)然有很多沖突,但是遷入和約定的沖突可以通過設(shè)置符號(hào)的優(yōu)先級(jí)來解決。杯子的使用CUP的使用需要在命令行環(huán)境下進(jìn)行。打開命令提示符并輸入以下語句??梢栽诋?dāng)前目錄下生成解析器Grm.java,Grm.cup的編寫格式如下:Cup開頭的書寫格式如下:包解析;//在解析包中生成進(jìn)口Absyn。*;導(dǎo)入javax.swing.*;操作代碼{:靜態(tài)對稱。symbolsym(strings){//將字符串轉(zhuǎn)換為符號(hào)返回符號(hào)。符號(hào).符號(hào);}:};分析器代碼{:Yylexlexer公共靜態(tài)ExpparseResult//記錄語法根節(jié)點(diǎn)的變量錯(cuò)誤消息。ErrorMsgerrorMsg//用錯(cuò)誤的語法輸出ErrorMsg對象聲明publicvoidsyntax_error(Java_cup.runtime.symbolcurrent){report_error("語法錯(cuò)誤("+current.sym+"),(Java_cup.runtime.symbol)current);}publicvoidreport_error(Stringmessage,java_cup.runtime.Symboltok){errorMsg.error(tok.left,message);}公共Grm(errormsg。ErrorMsgerr,JTextAreatext){this();//解析器的構(gòu)造errorMsg=errtextin=text}:};使用{://解析器初始化并從接口文本框中獲取輸入流。lexer=newYYlex(newJava.io.stringbufferinputstream(textin.gettext()),errormsg);:};用{:Java_cup.runtime.symbolsymb=lexer.debug_next_token()掃描;for(;(sym.sym==sym.error)&&sym.sym!=sym。EOF)symb=lexer.debug_next_token();返回符號(hào);:};//用debug_next_token獲取令牌,并打印出令牌//終止符終端字符串String;終端整數(shù)INT結(jié)尾逗號(hào)、冒號(hào)、分號(hào)、LPAREN、RPAREN、LBRACK、RBRACK、LBRACE、RBRACE、DOT終端加、減、乘、除、EQ、NEQ、LT、LE、GT、GE、AND、OR、ASSIGN、UMINUS終端數(shù)組,IF,THEN,ELSE,WHILE,F(xiàn)OR,TO,DO,LET,IN,END,OF,BREAK,NIL,F(xiàn)UNCTION,VAR,TYPE,ID;//終止符優(yōu)先級(jí)順序優(yōu)先權(quán)利DO,ELSE,THEN優(yōu)先非關(guān)聯(lián)賦值;優(yōu)先左或;優(yōu)先左和;優(yōu)先非ssocEQ,NEQ,LT,LE,GT,GE;優(yōu)先左加號(hào),減號(hào);優(yōu)先左次,除;優(yōu)先左UMINUS優(yōu)先左LBRACK關(guān)于優(yōu)先級(jí)順序的注意事項(xiàng):由于在解析過程中會(huì)出現(xiàn)很多移入和約定沖突的情況,有些情況可以通過設(shè)置終止符的優(yōu)先級(jí)來避免。定義中加號(hào)和減號(hào)的優(yōu)先級(jí)乘除法可以讓乘除法擁有比加減法更高的優(yōu)先級(jí)。此外,通過設(shè)置比較算子的有限階,可以避免分析中的移入和歸約沖突。 另外,在實(shí)際的cup生成過程中,還會(huì)出現(xiàn)一些其他的沖突,比如下面兩個(gè)沖突的解決:№.1沖突發(fā)生了。介于左值::=ID(*)之間和lvalue::=ID(*)LBRACKexprRBRACK和expr::=ID(*)lbrackexprrrackOFexpr在符號(hào)LBRACK下解決方法:將左邊的LBRACK設(shè)置為最高優(yōu)先級(jí),這樣當(dāng)減少ID和移入LBRACK發(fā)生沖突時(shí),系統(tǒng)會(huì)根據(jù)優(yōu)先級(jí)自動(dòng)移入?!?2沖突發(fā)生了。betweenexpr::=IFexprTHENexpr(*)andexpr::=IFexprTHENexpr(*)ELSEexpr在符號(hào)ELSE下解決方案:將rightDO,ELSE,THEN設(shè)置為最低優(yōu)先級(jí),并傳遞優(yōu)先級(jí)right。ELSE,THEN語句;然后,定義為右組合,將與else組合,所以先移入。№.3負(fù)號(hào)和負(fù)號(hào)識(shí)別有沖突。解決方法是在一個(gè)終止符UMINUS算術(shù)運(yùn)算符中重新定義最高優(yōu)先級(jí),在出現(xiàn)負(fù)號(hào)的情況下再次賦予UMINUS優(yōu)先級(jí)。2.寫作語法根據(jù)Tiger手冊中的語法規(guī)則,將上述語法逐一寫入cup文件的后面,必要時(shí)定義適當(dāng)?shù)姆墙K止符,完成語法結(jié)構(gòu)。每個(gè)語法規(guī)則應(yīng)該只返回其對應(yīng)的語句類型,該類型已經(jīng)在Absyn包中定義 根據(jù)語句的類型,可以根據(jù)定義返回。其中要注意一些鏈表的連接,如ExpList、FieldList等。需要保證這些對象連接的正確性。首先,在解析之前完成非終止符的定義,定義如下:非終結(jié)字段列表type_fields,type_fields_n,type_fields_ex非終結(jié)字段列表field_list,field_list_n,field_list_ex非終結(jié)符ExpListexpr_list,expr_list_n,expr_list_ex,expr_seq,expr_seq_n,expr_seq_ex。非終結(jié)符DecListdeclaration_list,declaration_list_ex非終端Ty型;非終結(jié)符Dec聲明、類型聲明、變量聲明、函數(shù)聲明;非終結(jié)符Expexpr,program//語法入門非終結(jié)變量lvalue其次,在語法啟動(dòng)器的語法句的執(zhí)行語句中,將第一個(gè)Exp傳遞給之前定義的parseResul,代碼如下:從程序開始;program::=expr:e{:parser.parseresult=e;:};對于一些常規(guī)語法,只需返回相應(yīng)的語句類型,如賦值語句。表達(dá)式::=左值:l分配表達(dá)式:e{:RESULT=newassignXP(lleft,l,e);:};對于需要連接的類型,如ExpList、FieldEXPLIST、FieldLIST、DECLIST,可以通過消除左遞歸,用向后指針連接類型的多個(gè)語句。另外,鏈表也可以是空的。下面舉一個(gè)EXPLIST的例子來說明處理方法:expr_list::=expr_list_n:l……1{:RESULT=l;:}|{:RESULT=null;:};expr_list_n::=expr:eexpr_list_ex:x………………(2){:RESULT=newExpList(e,x);:};expr_list_ex::=逗號(hào)expr_list_n:l…………(3){:RESULT=l;:}|{:RESULT=null;:};在(1)中,當(dāng)你開始識(shí)別時(shí),首先要判斷這個(gè)表達(dá)式是否為空,如果為空,則直接返回null否則,您將輸入(2)。因?yàn)橹辽儆幸粋€(gè)ExpList,所以可以聲明一個(gè)新的ExpList,并將其尾部指向下一個(gè)可能的Explist。當(dāng)然下一個(gè)ExpList可能是空的,所以你在處理expr_list_ex的時(shí)候需要判斷它是否是空的,如果是空的就直接返回null。語法樹的生成解析完成后,將同時(shí)返回整個(gè)語法樹的根節(jié)點(diǎn)。我們可以用這個(gè)根節(jié)點(diǎn)打印語法樹,在Absyn\Print中調(diào)用prExp(par.parseResult,2)。Java,并在屏幕上打印出整個(gè)語法樹。同時(shí),我們還可以在Print.Java中定義一個(gè)字符串變量來存儲(chǔ)所需的打印容量,在屏幕上打印后顯示在GUI界面的文本框中。類型檢查類型檢查操作理念在語法分析之后,我們還可以檢查整個(gè)語法樹的類型。我們可以從語法樹的根節(jié)點(diǎn)開始掃描每一個(gè)分支,根據(jù)Tiger語言規(guī)定的語法類型規(guī)則,判斷這個(gè)語句或者返回的類型的操作是否符合要求。如果類型不匹配,我們將立即報(bào)告一個(gè)類型錯(cuò)誤。類型檢查的關(guān)鍵是管理符號(hào)表。整個(gè)檢驗(yàn)過程維護(hù)一個(gè)變量表和一個(gè)類型表,都是類型表。表存儲(chǔ)為鍵值,關(guān)鍵字為符號(hào)類型,值為活頁夾類型,活頁夾中的變量值存儲(chǔ)具體信息。變量的值存儲(chǔ)條目類型,條目描述變量的類型和其他信息。該表的值存儲(chǔ)類型,并保存該類型的特定信息。Binder類是一個(gè)鏈表結(jié)構(gòu),意味著一個(gè)符號(hào)可以有幾種類型,比如局部變量覆蓋全局變量,局部類型覆蓋全局類型等。用于類型檢查的類之間的關(guān)系可以從下圖中清楚地看到:包封包封/包圍(動(dòng)詞envelop的簡寫)桌子tenv:表錯(cuò)誤消息:錯(cuò)誤消息進(jìn)入娛樂入口塞曼特進(jìn)入娛樂入口塞曼特VarEntryVarEntry類型桌子類型桌子dic:字典頂部:符號(hào)標(biāo)記:活頁夾粘合劑粘合劑值:對象prevtop:符號(hào)尾部:活頁夾每個(gè)變量或類型都有一個(gè)有效范圍。在聲明函數(shù)的過程中,聲明的變量只在其函數(shù)體內(nèi)有效,離開函數(shù)體就失去了有效范圍,成為無效變量。例如,如果letinend語句嵌套在inend語句中,則outer語句中聲明的變量在inner語句中仍然有效(重復(fù)的聲明將被覆蓋)??梢允褂帽碇械腷eginscope()和endscope()來確定變量的作用域。調(diào)用函數(shù)beginScope()添加一個(gè)標(biāo)記來標(biāo)記起始位置。當(dāng)此變量的范圍到達(dá)末尾時(shí),通過調(diào)用函數(shù)endScope()刪除所有以前的聲明。遇到的實(shí)際問題及思考№.1在類型檢查的過程中,還有一個(gè)遞歸調(diào)用的問題,比如testcase6。讓函數(shù)do_nothing1(a:int,b:string)=1什么都不做2(a+1)函數(shù)do_nothing2(d:int)=1do_nothing1(d,"str")在不做任何事1(0,"str2")目標(biāo)do_nothing1函數(shù)的體需要調(diào)用do_nothing2,但是如果按順序聲明函數(shù),此時(shí)還沒有聲明do_nothing2,所以無法識(shí)別并報(bào)錯(cuò)。解決方法:在let語句檢查declist之前,將所有dec(包括type_declaration,function_declaration)放在對應(yīng)的表中,這樣在檢查上面的函數(shù)DO_NOTHINKING1時(shí),就不會(huì)出現(xiàn)DO_NOTHINKING2沒有聲明的情況?!?2在類型檢查的過程中,還有一個(gè)循環(huán)定義的問題,比如testcase16。讓類型a=cb型=a型類型c=d類型d=a在目標(biāo)解決方法:在這四個(gè)類型定義中,使用了所有其他一起聲明的類型,并且有一個(gè)類似于a-c-d-a的類型循環(huán)定義,最后四個(gè)變量的類型仍然沒有真正定義,這是不允許的。解決方案是在檢查類型定義之前,使用bind(ExpTy)函數(shù)將新聲明的類型綁定到聲明中給出的類型。這樣在類型聲明的檢查中,通過isloop()函數(shù)簡單判斷是否是循環(huán)定義就可以知道是否有錯(cuò)誤。在這樣的設(shè)計(jì)下,代碼讓類型a=cb型=a型類型c=d類型d=int在目標(biāo)不會(huì)出現(xiàn)這樣的錯(cuò)誤,a-c-d-int會(huì)跳出檢查,返回false?!?3Declist中的聲明要求函數(shù)和類型的聲明必須分開放在一起,例如讓函數(shù)g(a:int):int=a類型t=int函數(shù)g(a:int):int=a在目標(biāo)在例子中,據(jù)說這是合法的,因?yàn)樗诼暶鞯臅r(shí)候被當(dāng)作一個(gè)類,funcDec和后面的funcDec一起處理,typeDec和后面的typeDec一起處理,導(dǎo)致無法檢查這個(gè)重復(fù)的定義函數(shù)。我覺得這里不太合理。我的想法是,所有的聲明都可以放入let語句檢查的環(huán)境變量中。這樣既能檢查定義是否重復(fù),又能使該類型的前后調(diào)用暢通無阻。也就是說,在ExpTytransExp(LetExpe)中添加以下代碼:ArrayList<String>list=newArrayList<String>();for(DecListtmp=e.decs;tmp!=nulltmp=tmp.tail){Dechead=tmp.headIf(headinstanceofTypeDec){//放入新類型TypeDectd=(TypeDec)頭;if(list.contains(TD.name.tostring()))env.errorMsg.error(td.pos,"type'"++"'已經(jīng)定義好了);list.add(TD.name.tostring());env.tenv.put(,新名稱(TD.NAME));}If(函數(shù)dec的head實(shí)例){//放一個(gè)新的函數(shù)變量FunctionDecfd=(FunctionDec)頭;typere=transTy(FD.result);記錄RC=transtypefields(FD.params);if(list.contains(FD.name.tostring()))env.errorMsg.error(fd.pos,"function'"++"'已定義");否則{list.add(FD.name.tostring());env.venv.put(,newFunEntry(rc,re));}}}list.clear();經(jīng)過

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論