编译原理课程设计C词法扫描器及语法分析器实现.docx
《编译原理课程设计C词法扫描器及语法分析器实现.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计C词法扫描器及语法分析器实现.docx(61页珍藏版)》请在冰豆网上搜索。
![编译原理课程设计C词法扫描器及语法分析器实现.docx](https://file1.bdocx.com/fileroot1/2022-11/25/2e0beafc-75cd-4447-b604-9bce74dfe4cf/2e0beafc-75cd-4447-b604-9bce74dfe4cf1.gif)
编译原理课程设计编译原理课程设计C词法扫描器及语法分析器实现词法扫描器及语法分析器实现编译原理课程设计报告课题名称:
词法扫描器及语法分析器实现提交文档学生姓名:
提交文档学生学号:
同组成员名单:
无指导教师姓名:
金军指导教师评阅成绩:
指导教师评阅意见:
。
提交报告时间:
201年6月x日1课程设计目标22。
程序结构3程序代码实现93.代码结构9.2。
1gobals。
h3。
2.3prser。
c1.5tes。
pp364测试结果34。
1.1词法分析结果34。
1.语法分析结果414.修改代码后的结果:
4.21修改2.本课程设计我的独创工作46。
总结41课程设计目标课程设计目标学生在学习编译原理课程过程中,结合各章节的构造编译程序的基本理论,要求用或+语言描述及上机调试,实现一个CMinus小编译程序(包括词法分析,语法分析等重要子程序),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。
要求:
(1)设计词法分析器设计各单词的状态转换图,并为不同的单词设计种别码。
将词法分析器设计成供语法分析器调用的子程序.功能包括:
a.具备预处理功能。
将不翻译的注释等符号先滤掉,只保留要翻译的符号串,即要求设计一个供词法分析调用的预处理子程序;b。
能够拼出语言中的各个单词;c。
返回(种别码,属性值)。
(2)语法分析要求用学习过的自底向上或自顶向下的分析方法等,实现对表达式、各种说明语句、控制语句进行语法分析。
若语法正确,则用语法制导翻译法进行语义翻译;生成并打印出语法树;若语法错误,要求指出出错性质和出错位置(行号).2分析与设计分析与设计2。
1程序结构程序结构本程序采用C+语言以面向对象的思想编写,程序分为两部分:
词法分析(nnr)和语法分析(Parse)。
扫描程序执行词法分析,并将字符序列收集到tken中,并将每一行的Tkn打印出来。
实现方法:
Scanner:
手工实现Parer:
递归下降系统总图:
sucecodeTokenSytaxre程序流程:
在程序中,词法分析获取所有Tokn,并将获取的Token存储在snner对象的tokering中.然后aser类的语法分析程序就根据okenSting中的Token进行语法分析,生成语法树,最后打印语法树。
同时,这也是程序的流程.扫描器:
C惯用的词法1、语言的关键字:
elsefinteturnvoidwile、专用符号:
/=!
=;,()/*/3、其他标记是I和NUM,通过下列正则表达式定义:
ID=ltrleterNUM=digd*ettea|。
|z|。
|Zdt=0.。
、空格由空白、换行符和制表符组成。
空格通常被忽略,除了它必须分开ID、NUM关键字。
5。
注释用通常的C语言符号/.*/围起来。
注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行注释不能嵌套.DF图如下:
初始状态设置为STAR,当需要得到下一个toke时,取得此ten的第一个字符,并且按照DFA与对此字符的类型的分析,转换状态。
重复此步骤,直到DNE为止,输出okn类型。
参考课本中所给的TIN扫描程序的FA,的DFA不同之处在于注释以及(=,!
=,,=)的处理:
1.注释部分参考了课本中C风格注释的FA;Otherothr*/*/Orothr2.处理(=,!
=,=,=)时并没有新建状态,而是在状态INASIG中分了种情况,通过一个变量分别处理。
语法分析:
C语法与语义:
1prorecaratin-ls2。
delratiolistelaraonisteclarato|delaron3.dclaratnrdelaraton|fu-decaratio4.var-delatoyespciI;typepcfierDNUM;5。
pe-speifierint|d6.fun-dclartiontype-pfeD(aams)compounstmt(在课后解释中coundstmt前面没有“|”符号)7。
parasaram-lis|vid。
aralitparam-list,paamam9。
aramypespecirID|type-specifierIDpondtmtlocldeclatsstatemet-ist1.lcdclratiocaclaratonsvadclaration|emty12。
statemnlistsateenststatent|empy。
ttmenexprsionstt|compu-tmt|selection-stm|iteraiostmtetrnstmt14。
expresionstexpresio;;5。
sletionttf(exreson)tatment|f(expession)tatemenelsestaement6。
eationstmtil(epression)atement17。
rtrnsttetun;|reurexpesin;8。
exprssinv=exprssion|ipleepeson9。
vrID|IDxession2.simplexsioadditiveexpressionreloaitieepress|aditivexpresion2.relop=|#inlueSDLIB。
nclude#incldenclueiostreaminclddirect.hsingnmesacest;ifndefAL#efieFAL0#endi#fndfTRUE#defTRE1;endi/保留字的个数#dfineMAXRESRED6ypeenu/bookkeepingtknsDIL,EROR,/eservedwodIF,ESE,NT,RETURN,VO,WILE,/ltiharactokenI,NUM,/speialymbols/RACKTRBACKETLBCE/RBAESIGN,EQ,LT,RT,US,MINUS,IES,OVER,LPAREN,RAR,E,LBRACKT,RBRAT,NEQ,COMM,LRAE,RBRACE,LTEQ,TEQTkenype;extrFE*oce;/源代码文件externILElistn;/listinoutputtextfileexternFILE*coe;/extrntlineno;/语法分析树typedfenumNodeindStmtK,ExpK,eclrtionK,;tpeefenuStmtKindIfK,he,Ai,RetrnK,VoidK,;typeefenmExpKindOp,ConstK,IdK,Aray_exp,FntionexpK,;typdeenmxpypeVoi,Intge;yedeenumcraonKndFuctonK,VarK,AryK,PaaterK;#deieMXCHLRE3pdefstrutreeodsrutteeNodeelartin;strctteNoe*childMAXCHILDREN;srctreeNoe*silin;structtreoe*pars;intli;odeKidnodkd;ionindSmtKindmt;ExKinex;DeclaratiKiddeclaraton;knd;trctMyStructTokenypeop;itv;char*;nse;at;pTypeype;Teede;extrnintEhSourc;exteintTraceScn;eerntTraePare;xteritTcAnaze;xrinraceCode;extrtErro;#endi3.2.2can。
c最主要的过程是GtToke,它消耗输入字符并根据DFA图返回下一个被识别的记号。
这个实现利用了双重嵌套情况分析,以及一个有关状态的大型情况列表,在大列表中是基于当前输入字符的单独列表。
记号本身被定义成gos。
h中的枚举类型。
扫描程序的状态也被定义为一个枚举类型,位于扫描程序之中。
扫描程序使用了三个全局变量,文件变量ource,isting在globals中声明且在mn。
c中被分配和初始化的整型变量ineno。
由gtTon过程完成的额外的簿记如下所述:
表resed和过程reservedlooup完成位于由tToen的主要循环识别的标识符之后的保留字的查找,urrentTokn的值也随之改变。
标志变量save被用作指示是否将第一个字符增加到tokenStrg之上;由于需要包括空白格和非消耗的先行,因此这些东西都是必要的。
到扫描程序的字符输入由gNextCha函数提供,该函数将一个26字符缓冲区内部的lineBuf中的字符取到扫描程序中,如果已经耗尽了这个缓冲区,且假设每一次都获取了一个新的源代码行,那么getextChar就利用ge从source文件更新该缓冲区。
最后由于从INUM和INID到最终状态的转换是非消耗的.可以通过一个gtnxthar的过程在输入缓冲区的反填一个字符来完成这一任务.#includ”globals。
h”#inclue”il.h”ncud”san。
hpedefenumSTAT,IASGN,INCOMMENT,NENDCMENT,INNUM,IID,DNE,LT,IRT,INEQSateType;caroknStrngMTOKNLE;#defineFLEN124staticcharlineBFLEN;sttntlinpos=0;saticintbfsize=0;/geextChar从lineBf获得下一个非空字符,读入新的一行如果lineBf耗尽sachagtextCHar(void)if(!
(iosbufiz))lnno+;f(fges(lineBuf,BUN-1,sorce))if(EchoSourc)fint(litin,%d,%,nen,ineB);busestrlen(lieBuf);ieos=0;reuineBulinepo+;lseeturnOF;elereturnineufnpos+;/bckrcksnehaaceriineBufstatcoidungeNexthar(void)linepos-;/查找表的保留字satcstrtchar*sr;TknTpet;reserveWordsAXESERVD”i,IF,”int,T,”ele,EL,rurn”,RETR,voi,VID,”whie,WHIL;/查找一个标识符,看看这是否是一个保留字/使用线性搜索satcTokeTypersevedLookup(char)inti;or(i=0;iMARESERE;+)f(!
strp(s,resrvedWords.st))reurnrserveWrds。
to;retrnI;okenTypegtTo(id)/索引存储为“tkenStrig”intkenStnIe=0;/返回当前onoenTypecurrenoken;/当前状态总是以ART开始tteypestat=TR;/指示存放至toknString的标志intsaveTRUE;whie(s!
DONE)in=getNxtCHr();ave=TUE;sich(state)caeSAT:
f(sgt(c))state=INNM;lseif(isalh()stae=INID;lsef(c=)stat=INASSIGN;esif(c=)|(c)|(c=n))saveFLS;elseif(c=)/遇到”则假定就是注释,进入注释状态stateCOMMEN;saveFLSE;eef(c=)stae=INRT;else(=)stat=INL;eleif(c=!
)tate=INN;elsetat=D;swic(c)defult:
currenkeEROR;eak;asEOF:
sv=LE;currentTokn=EDFI;beak;cas:
urenTokn=LRCE;break;cs:
crentTn=RCKT;brek;cas,:
rrntToen=OMM;brea;cse+:
urentToken=PUS;beak;se-:
currntToken=IU;break;ae*:
currentToken=TIMES;beak;cae:
curtTen=LBRACE;beak;case:
rrnToken=RBRACE;break;case(:
curntTokenLPAREN;brak;cas):
urrTken=RPARE;break;cse;:
cretTokenEMI;brek;eak;*=注释改动=*/caseINENDCOMENT:
if(=*&getextCar()=)/toke是*且下一个tokn是/则结束注释sve=FALSE;state=STAR;/注释不作处理,直到注释结束,lseaveFLS;tt=NNOMMENT;brea;caseIOMMET:
if(c=)/“/”后是则进入注释/ugNethar();svFALSE;t=NDCOMMENT;/若是注释开头,转入注释结尾处理lseif(=OF)tate=DON;crrnTo=END;else/“/”后不是*则为除法ugetNextChar();sae=FALE;crntTokn=OVER;tae=DONE;beak;=*/赋值改动=*/ceIASIN:
steDONE;i(c=)/下一个仍是等号就为相等currentToke=EQ;lse否则回退,netNtCar();save=LSE;curetTken=ASSG;bea;=*/小于等于=*/caseNLT:
tateDONE;if(c=)currntoke=LTEQ;eleugeNxtChar();saeFALSE;crenoke=T;brea;=/大于等于=caeNRT:
sate=ONE;if(=)currentToke=RTEQ;esneNexChar();ave=FLSE;rntokn=RT;be;/*=不等于=*/aeINNEQ:
statDON;if(c=)curentToken=NQ;elseungetNextCar();sv=LE;currentToen=ERROR;brek;cseINUM:
i(!
isdigt(c))ungetNetChar();se=FALE;ta=DON;curretToken=NU;brek;aseIN:
(!
isapha())ungtNextChar();save=FALSE;tae=ONE;crrenten=ID;bre;caeDONE:
efalt:
rint(lsting,”SerBug:
state=dn”,tate);staeDON;enToen=ERROR;break;if((ave)&(oknSingIndexAXTKENE)oketrnoenStigInx+=(har)c;if(stae=DONE)oentrinoenSingnde=0;if(centokn=)urretTen=reservedLup(toknSig);if(TraeScan)printf(lstng,d:
lnno);printToken(curentToken,tkenString);tuncuentTken;3.23parser.cincludeloals.h”iclude”til。
”#ncudecan.h”#include”prse。
h”staticTkenTpetok;/ldsurnttokensaticTreeNode*stm_sequence(vod);taticTreNoetatee(oi);statcTreeNoeif_mt(vid);stareeNode*whil_tmt(oid);/自定义函数saicTreNod*reurtmt(vid);staticTreeNoe*intst(vod);saiceNoevoid_sm(voi);stacTreeoe*declaaio(vod);statirNdeparameter(void);staticTeeNode*xp(id);tacTreeNoe*ipleex(oi);staticTreede*em(od);ttreeNodeaco(void);staivoiinFuncion(vo);staticdsynaxrro(carmessage)prit(istin,”n);fprif(ist,Sntaxroratlied:
%s,ino,message);Error=TUE;stativoiath(okenTpexpected)if(toke=expecte)token=token();elsesyntxrr(”nepcttoke”);printToe(tokn,toenStrin);fprint(litin,”);TreNoestt_seqece(voi)TreNode*t=statmen();TreNoe*p=t;hie(en!
=ENDFILE)&(tke!
=BRACE))reeod*;/h(SEMI);q=stateet();i(tken!
=RBRACE)f(q!
=ULL)if(t=NUL)=q;sep-sbi=;p=q;returnt;TeNodetatemet(void)reeodeNLL;wich(token)caseIF:
t=f_tmt();brea;caseWLE:
wilestt();bre;caeID:
/若为D不直接进行赋值,进入exp()至act(),将赋值加入至fator()=ex();break;caeETRN:
t=retur_smt();break;caseNT:
t=it_stmt();beak;aseOID:
toid_tmt();br;caseSEMI:
matc(EMI);bak;dault:
ntaxr(”unexpectetoken);printTok(oen,okeSting);toen=getTokn();brea;rturnt;Treee*decaatin(vid)reeNodt=newDclaatioNode(tken);if(t!
=L)/名称tokeneto();/ID赋给attr。
namet-attr。
ame=coyStrin(tokntrng);oke=getToen();/oken是”(”则为函数声明if(toke=LPREN)tkidecaationFunctionK;mah(LPRN);TreNoe*paramets=paraeer();/函数参数匹配if(araes!
=NLL)t-child0=parames;atch(PRN);mat(LRCE);/匹配函数体TeeNd*bod=sttseuen();if(body=NUL)sntxErr(errorbody!
);elsetchid1=bod;mtch(RBRAE);/toen后不是(则是变量声明else/普通变量类型tin。
dcraio=VK;/进入数组类型if(token=LBRCKET)match(LRKT);kid.eclaration=AK;tat。
z=aoi(toknString);token=getoken();mah(RRKT);match(SMI);rturn;TreeNode*aramer(id)TeeNodet=NUL;if(tken=OI)mtch(OID);/结束elsei(toenRBAE)reurnt;/有参数eletnewDecaatinNo(toke);toknetokn();tatr。
name=opySring(tokStri);toe=etToen();/数组if(ten=LACET)tnd.clarin=AryK;match(LBRACET);tttr.ize0;math(RRACKET);IDelset-kind。
earationarK;f(oke=CMA)c();bngprametr();reurnt;TeeNodeif_stmt(void)TreNoet=newSmtNode(f);match(I);(t!
=NUL)matc(LAEN);tchildex();mtch(RPREN);f(t!
NULL)/如果带大括号if(token=BRACE)mtch(LBRACE);whie(toke!
=RAC)thildstaemen();matc(BACE);/无括号eset-ci1staeent();i(tok=ELSE)match(ELSE);f(t!
=NLL)/如果带大括号if(tken=LRACE)atch(LBRAE);whie(toke!
RBRACE)tchild=statent();match(RBRACE);/无括号etchil2=taten();rert;reeNode*hsm(v)Teede*t=ewSttNoe(WhileK);atch(WHIL);Treoe=NUL;mtch(LPAREN);while(tken!
=RPREN)(t-cild=NUL)p=exp();hild0=p;elep=p-chi0;pep();match(RPREN);/hile函数大括号可有可无/如果有括号if(tken=LBRACE)match(LBRAC);wile(oken!
=RBACE)thild1atment();atch(RRACE);/无lst-child1=satemnt();f(token=SEMI)math(SEMI);retrnt;TeeNode*rtunt(void)TreNodtwSmtNoe(Ren);tattr。
ameopyStig(kentring);atc(TUR);f(tke!
=SEMI)t-hild0=exp();ach(SEMI);ert;reeNdeinttmt(vid)TeNde*t=newDeaaonode(INT);match(INT);tatr。
neopStrn(tokStrng);mat(ID);/函数if(token=AREN)mac(LPAREN);tkd.eclratin=FunctinK;if(toke=VOD)ath(VID);lse/函数参数匹配inFucion();match(RREN);/函数体mth(LBRCE);wle(tken!
=RRAE)stament();mac(RBRACE);数组ese(token=LBRAKET)tindex=ArrapK;ch(BRAK);t-ild0=exp();mah(BACKET);/变量if(oken=EMI)tkindelarainVar;mach(SEMI);retrnt;/voi函数reNod*vo_stm(void)Tede=neDclaratiooe(VOI);ac(ID);-atr.namecopyrin(knSrng);math(ID);math(LPEN);i(token=VOID)at(VOID);linFcon();match(RPAN);match(LBRA);while(tn!
ACE)stteent();mtch(RRACE);returnt;/函数参数匹配vidinFnio(void)mtc(INT);at(I);if(oken=L