1、 编译原理课程设计编译原理课程设计 C 词法扫描器及语法分析器实现词法扫描器及语法分析器实现 编译原理课程设计报告 课题名称:词法扫描器及语法分析器实现 提交文档学生姓名:提交文档学生学号:同组 成 员 名 单:无 指导 教 师 姓 名:金军 指导教师评阅成绩:指导教师评阅意见:。提交报告时间:201年 6月 x 日 1 课程设计目标 2 2。程序结构 3 程序代码实现 9 3.代码结构 9.2。1 gobals。h 3。2.3 prser。c 1.5 tes。pp36 4 测试结果3 4。1.1 词法分析结果3 4。1.语法分析结果41 4.修改代码后的结果:4.21修改2 .本课程设计我的
2、独创工作4 6。总结 4 1 课程设计目标课程设计目标 学生在学习编译原理课程过程中,结合各章节的构造编译程序的基本理论,要求用或+语言描述及上机调试,实现一个 CMinus 小编译程序(包括词法分析,语法分析等重要子程序),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。要求:(1)设计词法分析器 设计各单词的状态转换图,并为不同的单词设计种别码。将词法分析器设计成供语法分析器调用的子程序.功能包括:a.具备预处理功能。将不翻译的注释等符号先滤掉,只保留要翻译的符号串,即要求设计一个供词法分析调用的预处理子程序;b。能够拼出语言中的各个单词;c。
3、返回(种别码,属性值)。(2)语法分析 要求用学习过的自底向上或自顶向下的分析方法等,实现对表达式、各种说明语句、控制语句进行语法分析。若语法正确,则用语法制导翻译法进行语义翻译;生成并打印出语法树;若语法错误,要求指出出错性质和出错位置(行号).2 分析与设计分析与设计 2。1 程序结构程序结构 本程序采用 C+语言以面向对象的思想编写,程序分为两部分:词法分析(nnr)和语法分析(Parse)。扫描程序执行词法分析,并将字符序列收集到 tken中,并将每一行的 Tkn打印出来。实现方法:Scanner:手工实现 Parer:递归下降 系统总图:suce code Token Sytax r
4、e 程序流程:在程序中,词法分析获取所有 Tokn,并将获取的 Token存储在 snner对象的tokering中.然后aser类的语法分析程序就根据okenSting中的 Token 进行语法 分析,生成语法树,最后打印语法树。同时,这也是程序的流程.扫描器:C惯用的词法 1、语言的关键字:else f int eturn void wile、专用符号:/=!=;,()/*/3、其他标记是 I和 NUM,通过下列正则表达式定义:ID=ltr leter NUM=dig d*ette a|。|z|。|Z dt=0.。、空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开 ID、NU
5、M 关键字。5。注释用通常的 C 语言符号/.*/围起来。注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行注释不能嵌套.DF图如下:初始状态设置为 STAR,当需要得到下一个 toke时,取得此 ten的第一个字符,并且按照 DFA 与对此字符的类型的分析,转换状态。重复此步骤,直到 DNE为止,输出okn类型。参考课本中所给的 TIN扫描程序的FA,的 DFA不同之处在于注释以及(=,!=,,=)的处理:1.注释部分参考了课本中 C 风格注释的FA;Other othr */*/Or othr 2.处理(=,!=,=,=)时并没有新建状态,而是在状态 INASIG中分
6、了种情况,通过一个变量分别处理。语法分析:C语法与语义:1 pror ecaratin-ls 2。delratiolist elaraonist eclarato|delaron 3.dclaratn rdelaraton|fu-decaratio 4.var-delato yespci I;typepcfier D NUM ;5。pe-speifier int|d 6.fun-dclartion type-pfe D(aams)compounstmt(在课后解释中 coundstmt 前面没有“|”符号)7。paras aram-lis|vid 。aralit param-list,paam
7、 am 9。aram ypespecir ID|type-specifier ID pondtmt locldeclats statemet-ist 1.lcdclrati ocaclaratons vadclaration|emty 12。statemnlist sateenst statent|empy 。ttmen exprsionstt|compu-tmt|selection-stm|iteraiostmt etrnstmt 14。expresionst expresio;;5。sletiontt f(exreson)tatment|f(expession)tatemen else s
8、taement 6。eationstmt il(epression)atement 17。rtrnstt etun;|reur expesin;8。exprssin v=exprssion|ipleepeson 9。vr ID|ID xession 2.simplexsio additiveexpression relo aitieepress|aditivexpresion 2.relop =|#inlue SDLIB。nclude#inclde nclueiostream incld direct.h sing nmesace st;ifndef AL#efie FAL 0#endi#fn
9、df TRUE#def TRE 1;endi /保留字的个数#dfine MAXRESRED 6 ype enu /bookkeeping tkns DIL,EROR,/eserved wod IF,ESE,NT,RETURN,VO,WILE,/ltiharact oken I,NUM,/speial ymbols /RACKTRBACKET LBCE/RBAE SIGN,EQ,LT,RT,US,MINUS,IES,OVER,LPAREN,RAR,E,LBRACKT,RBRAT,NEQ,COMM,LRAE,RBRACE ,LTEQ,TEQ Tkenype;extr FE*oce;/源代码文件
10、extern ILE listn;/listin output text file extern FILE*coe;/extrn t lineno;/语法分析树 typedf enum Nodeind StmtK,ExpK,eclrtionK,;tpeef enu StmtKind IfK,he,Ai,RetrnK,VoidK,;typeef enm ExpKind Op,ConstK,IdK,Aray_exp,FntionexpK,;typde enm xpype Voi,Intge;yede enum craonKnd FuctonK,VarK,AryK,PaaterK ;#deie MX
11、CHLRE 3 pdef stru treeod srut teeNode elartin;strct teNoe*childMAXCHILDREN;src treeNoe*silin;struct treoe*pars;int li;odeKid nodkd;ion ind SmtKind mt;ExKin ex;DeclaratiKid declaraton;knd;trct MyStruct Tokenype op;it v;char*;n se;at;pType ype;Teede;extrn int EhSourc;exte int TraceScn;eer nt TraePare;
12、xter it TcAnaze;xr in raceCode;extr t Erro;#endi 3.2.2 can。c 最主要的过程是 GtToke,它消耗输入字符并根据 DFA图返回下一个被识别的记号。这个实现利用了双重嵌套情况分析,以及一个有关状态的大型情况列表,在大列表中是基于当前输入字符的单独列表。记号本身被定义成 gos。h 中的枚举类型。扫描程序的状态也被定义为一个枚举类型,位于扫描程序之中。扫描程序使用了三个全局变量,文件变量ource,isting在 globals中声明且在 mn。c中被分配和初始化的整型变量ineno。由 gtTon过程完成的额外的簿记如下所述:表 res
13、ed 和过程reservedlooup完成位于由tToen的主要循环识别的标识符之后的保留字的查找,urrentTokn的值也随之改变。标志变量 save被用作指示是否将第一个字符增加到 tokenStrg之上;由于需要包括空白格和非消耗的先行,因此这些东西都是必要的。到扫描程序的字符输入由 gNextCha函数提供,该函数将一个 26 字符缓冲区内部的 lineBuf中的字符取到扫描程序中,如果已经耗尽了这个缓冲区,且假设每一次都获取了一个新的源代码行,那么 getextChar 就利用ge从 source文件更新该缓冲区。最后由于从 INUM 和 INID到最终状态的转换是非消耗的.可以通
14、过一个gtnxthar的过程在输入缓冲区的反填一个字符来完成这一任务.#includ”globals。h”#inclue”il.h”ncud”san。h pedef enum STAT,IASGN,INCOMMENT,NENDCMENT,INNUM,IID,DNE,LT,IRT,INEQSateType;car oknStrngMTOKNLE;#define FLEN 124 static char lineBFLEN;stt nt linpos=0;satic int bfsize=0;/geextChar 从 lineBf获得下一个非空字符,读入新的一行如果 lineBf 耗尽 sa ch
15、a gtextCHar(void)if(!(iosbufiz))lnno+;f(fges(lineBuf,BUN-1,sorce))if(EchoSourc)fint(litin,%d,%,nen,ineB);busestrlen(lieBuf);ieos=0;reu ineBulinepo+;lse eturn OF;ele return ineufnpos+;/bckrcks ne haacer i ineBuf statc oid ungeNexthar(void)linepos-;/查找表的保留字 satc strt char*sr;TknTpe t;reserveWordsAXESE
16、RVD”i,IF,”int,T,”ele,EL,rurn”,RETR,voi,VID,”whie,WHIL;/查找一个标识符,看看这是否是一个保留字/使用线性搜索 satc TokeType rsevedLookup(char)int i;or(i=0;iMARESERE;+)f(!strp(s,resrvedWords.st))reurn rserveWrds。to;retrn I;okenType gtTo(id)/索引存储为“tkenStrig”int kenStnIe=0;/返回当前on oenType currenoken;/当前状态总是以ART开始 tteype stat=TR;/
17、指示存放至 toknString的标志 int saveTRUE;whie(s!DONE)in =getNxtCHr();ave=TUE;sich(state)cae SAT:f(sgt(c))state=INNM;lse if(isalh()stae=INID;lse f(c=)stat=INASSIGN;es if(c=)|(c )|(c=n))save FLS;else if(c=)/遇到”则假定就是注释,进入注释状态 state COMMEN;save FLSE;ee f(c=)stae=INRT;else (=)stat=INL;ele if(c=!)tate=INN;else ta
18、t=D;swic(c)defult:currenke EROR;eak;as EOF: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(:curntToken LPAREN;brak;cas
19、):urrTken=RPARE;break;cse;:cretToken EMI;brek;eak;*=注释改动=*/case INENDCOMENT:if(=*&getextCar()=)/toke是*且下一个 tokn是/则结束注释 sve=FALSE;state=STAR;/注释不作处理,直到注释结束,lse ave FLS;tt=NNOMMENT;brea;case IOMMET:if(c=)/“/”后是则进入注释 /ugNethar();sv FALSE;t=NDCOMMENT;/若是注释开头,转入注释结尾处理 lse if(=OF)tate=DON;crrnTo=END;else
20、/“/”后不是*则为除法 ugetNextChar();sae=FALE;crntTokn=OVER;tae=DONE;beak;=*/赋值改动=*/ce IASIN:ste DONE;i(c=)/下一个仍是等号就为相等 currentToke=EQ;lse 否则回退,netNtCar();save=LSE;curetTken=ASSG;bea;=*/小于等于=*/case NLT:tate DONE;if(c=)currntoke=LTEQ;ele ugeNxtChar();sae FALSE;crenoke=T;brea;=/大于等于=cae NRT:sate=ONE;if(=)curre
21、ntToke=RTEQ;es neNexChar();ave=FLSE;rntokn=RT;be;/*=不等于=*/ae INNEQ:stat DON;if(c=)curentToken=NQ;else ungetNextCar();sv=LE;currentToen=ERROR;brek;cse INUM:i(!isdigt(c))ungetNetChar();se=FALE;ta=DON;curretToken=NU;brek;ase IN:(!isapha())ungtNextChar();save=FALSE;tae=ONE;crrenten=ID;bre;cae DONE:efalt
22、:rint(lsting,”Ser Bug:state=dn”,tate);stae DON;enToen=ERROR;break;if((ave)&(oknSingIndex AXTKENE)oketrnoenStigInx+=(har)c;if(stae=DONE)oentrinoenSingnde=0;if(centokn=)urretTen=reservedLup(toknSig);if(TraeScan)printf(lstng,d:,lnno);printToken(curentToken,tkenString);tun cuentTken;3.23 parser.c includ
23、eloals.h”iclude”til。”#ncudecan.h”#include”prse。h”static TkenTpe tok;/lds urnt token satic TreeNode*stm_sequence(vod);tatic TreNoe tatee(oi);statc TreeNoe if_mt(vid);sta reeNode*whil_tmt(oid);/自定义函数 saic TreNod*reurtmt(vid);static TreeNoe*intst(vod);saic eNoe void_sm(voi);stac Treeoe*declaaio(vod);st
24、ati rNde parameter(void);static TeeNode*xp(id);tac TreeNoe*ipleex(oi);static Treede*em(od);tt reeNode aco(void);stai voi inFuncion(vo);static d synaxrro(car message)prit(istin,”n);fprif(ist,Sntax ror at lie d:%s,ino,message);Error=TUE;stati voi ath(okenTp expected)if(toke=expecte)token=token();else
25、syntxrr(”nepct toke”);printToe(tokn,toenStrin);fprint(litin,”);TreNoe stt_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;se p-sbi=;p=q;return t;TeNode tatemet(void)reeode NLL;wich(token)case IF:t=f_tmt();brea;ca
26、se WLE:wilestt();bre;cae ID:/若为D不直接进行赋值,进入 exp()至act(),将赋值加入至fator()=ex();break;cae ETRN:t=retur_smt();break;case NT:t=it_stmt();beak;ase OID:t oid_tmt();br;case SEMI:matc(EMI);bak;dault:ntaxr(”unexpecte token );printTok(oen,okeSting);toen=getTokn();brea;rturn t;Treee*decaatin(vid)reeNod t=newDclaat
27、ioNode(tken);if(t!=L)/名称 token eto();/ID赋给 attr。name t-attr。ame=coyStrin(tokntrng);oke=getToen();/oken 是”(”则为函数声明 if(toke=LPREN)tkidecaation FunctionK;mah(LPRN);TreNoe*paramets=paraeer();/函数参数匹配 if(araes!=NLL)t-child0=parames;atch(PRN);mat(LRCE);/匹配函数体 TeeNd*bod=sttseuen();if(body=NUL)sntxErr(error
28、body!);else tchid1=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)TeeNode t=NUL;if(tken=OI)mtch(OID);/结束 else i(toen RBAE)reurn t;/有参数 ele t newDecaa
29、tinNo(toke);tokn etokn();tatr。name=opySring(tokStri);toe=etToen();/数组 if(ten=LACET)tnd.clarin=AryK;match(LBRACET);tttr.ize 0;math(RRACKET);ID else t-kind。earation arK;f(oke=CMA)c();bng prametr();reurn t;TeeNode if_stmt(void)TreNoe t=newSmtNode(f);match(I);(t!=NUL)matc(LAEN);tchild ex();mtch(RPREN);f
30、(t!NULL)/如果带大括号 if(token=BRACE)mtch(LBRACE);whie(toke!=RAC)thild staemen();matc(BACE);/无括号 ese t-ci1 staeent();i(tok=ELSE)match(ELSE);f(t!=NLL)/如果带大括号 if(tken=LRACE)atch(LBRAE);whie(toke!RBRACE)tchild=statent();match(RBRACE);/无括号 e tchil2=taten();rer t;reeNode*hsm(v)Teede*t=ewSttNoe(WhileK);atch(WHI
31、L);Treoe =NUL;mtch(LPAREN);while(tken!=RPREN)(t-cild=NUL)p=exp();hild0=p;ele p=p-chi0;p ep();match(RPREN);/hile函数大括号可有可无/如果有括号 if(tken=LBRACE)match(LBRAC);wile(oken!=RBACE)thild1 atment();atch(RRACE);/无 ls t-child1=satemnt();f(token=SEMI)math(SEMI);retrn t;TeeNode*rtunt(void)TreNod t wSmtNoe(Ren);ta
32、ttr。ame opyStig(kentring);atc(TUR);f(tke!=SEMI)t-hild0=exp();ach(SEMI);er t;reeNde inttmt(vid)TeNde*t=newDeaaonode(INT);match(INT);tatr。ne opStrn(tokStrng);mat(ID);/函数 if(token=AREN)mac(LPAREN);tkd.eclratin=FunctinK;if(toke=VOD)ath(VID);lse /函数参数匹配 inFucion();match(RREN);/函数体 mth(LBRCE);wle(tken!=RR
33、AE)stament();mac(RBRACE);数组 ese (token=LBRAKET)tindex=ArrapK;ch(BRAK);t-ild0=exp();mah(BACKET);/变量 if(oken=EMI)tkindelarain Var;mach(SEMI);retrn t;/voi 函数 reNod*vo_stm(void)Tede =neDclaratiooe(VOI);ac(ID);-atr.name copyrin(knSrng);math(ID);math(LPEN);i(token=VOID)at(VOID);l inFcon();match(RPAN);match(LBRA);while(tn!ACE)stteent();mtch(RRACE);return t;/函数参数匹配 vid inFnio(void)mtc(INT);at(I);if(oken=L
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1