下载

1下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 C-Minus词法分析和语法分析设计编译器编译原理课程设计

C-Minus词法分析和语法分析设计编译器编译原理课程设计.doc

C-Minus词法分析和语法分析设计编译器编译原理课程设计

如此熟悉_
2017-09-02 0人阅读 举报 0 0 暂无简介

简介:本文档为《C-Minus词法分析和语法分析设计编译器编译原理课程设计doc》,可适用于综合领域

CMinus词法分析和语法分析设计编译器编译原理课程设计编译原理课程设计报告课题名称:CMinus词法分析和语法分析设计提交文档学生姓名:XXX提交文档学生学号:XXXXXXXXXX同组成员名单:XXX指导教师姓名:XX指导教师评阅成绩:指导教师评阅意见:提交报告时间:年月日课程设计目标实验建立C编译器。只含有扫描程序,scanner,和语法分析,parser,部分。分析与设计C编译器设计的整体框架~本实验实现扫描处理和语法分析程序,图中粗黑部分,。打开源代码文件sourcetxt扫描处理(词法分析)记号语法分析程序语法树语义分析程序错误处理器注释树记号表源代码优化程序文字表、扫描程序scanner部分中间代码系统设计思想设计思想,根据DFA图用switchcase结构实现状态转换。代码生成器惯用词法,目标代码目标代码优化程序目标代码语言的关键字,elseifintreturnvoidwhile专用符号,*<<=>>===!==,(){}**其他标记是ID和NUM,通过下列正则表达式定义,ID=letterletter*NUM=digitdigit*letter=a||z|A||Zdigit=||大写和小写字母是有区别的空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开ID、NUM关键字。注释用通常的C语言符号**围起来。注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。注释不能嵌套scanner的DFA*<=>===!=,(){}INASSIGNWhitespace=>,<,=,!digittnotherNUMdigitotherSTARTDONEletterotherletterINIDotherZHU*otherINCOMMENT*otherZZHU*说明,当输入的字符使DFA到达接受状态的时候,则可以确定一个单词了。初始状态设置为START,当需要得到下一个token时,取得次token的第一个字符,并且按照DFA与对此字符的类型分析,转换状态。重复此步骤,直到DONE为止,输出token类型。当字符为“”时,状态转换为SLAH再判断下一个字符,如果为“*”则继续转到INCOMMENT,最后以“*”时转到ENDCOMMENT状态,表明是注释,如果其他的则是字符停滞于当前字符,并且输出“”。程序流程图源文件读取源文件一行输)TreeNode*expressionstmt(void)TreeNode*selectionstmt(void)TreeNode*iterationstmt(void)TreeNode*returnstmt(void)TreeNode*expression(void)TreeNode*var(void)TreeNode*simpleexpression(TreeNode*k)TreeNode*additiveexpression(TreeNode*k)TreeNode*term(TreeNode*k)TreeNode*factor(TreeNode*k)TreeNode*call(TreeNode*k)TreeNode*args(void)测试程序说明根据附录A后面的例子~程序输入两个整数~计算并打印出它们的最大公因子~保存为atxt。*AprogramtoperformEucild'sAlgorithmtocomputegcd*intgcd(intu,intv){if(v==)returnuelsereturngcd(v,uuv*v)*uuv*v==umodv*}voidmain(void){intxintyx=input()y=input()output(gcd(x,y))}程序代码实现按文件列出主要程序代码,添加必要的注释Scannercpp:#include<cstdlib>#include<iostream>#include<fstream>#include<string>#include"scannerh"#include<vector>usingnamespacestd*Name:词法分析器Copyright:Author:XXXDate::Description:提取出token*Scanner::Scanner(){scanSuccess=truecharIndex=str=""commentFlag=truesourseString=""lineCount=}voidScanner::scan(){cout<<"开始词法分析"<<endlbooldoubleSym=falsegetSourseStringFromFile("sourseFiletxt")intstate=STARTlineCount=charchwhile(state<){ch=getNextChar()if(''==ch){TokenttlineNo=lineCountttokenString=""ttokenType=ENDFILEtokenListpushback(t)break}if(START==state)初始状态和空格{state=charType(ch)if(state!=START)str=ch}elseif(INNUM==state)digit{state=charType(ch)if(state!=INNUM)state=DONEelsestr=ch}elseif(INID==state)letter{state=charType(ch)if(state!=INID)state=DONEelsestr=ch}elseif(INDBSYM==state)除了<>=!之外的各种符号{if('='==ch){str=chdoubleSym=true}elsedoubleSym=falsestate=DONE}if(DONE==state)接收状态{inttp=if('n'==ch)tp=TokenttlineNo=lineCounttpttokenString=strttokenType=returnTokenType(str)tokenListpushback(t)if(ERROR==ttokenType)scanSuccess=falseintlastState=charType(strstrlength())if(lastState==INNUM||lastState==INID||(lastState==INDBSYMdoubleSym==false))backToLastChar()str=""state=STARTif(doubleSym==true)doubleSym=false}}if(scanSuccess==false)cout<<"词法分析出错:"<<endlelsecout<<"词法分析成功了:"<<endlprintToken()输出Token到文件Tokentxt中}TokenScanner::getTokenAt(inttokenIndex){TokentokentokenlineNo=lineCounttokentokenString=""tokentokenType=ENDFILEif(tokenIndex<tokenListsize()){token=tokenListat(tokenIndex)}returntoken}voidScanner::getSourseStringFromFile(stringpath){ifstreamfin(pathcstr())stringtempsourseString=""while(getline(fin,temp)){sourseString=tempsourseString='n'}finclose()charIndex=}voidScanner::deleteComments(){cout<<"正在删除注释"<<endlofstreamfoutSourse("sourseFiletxt")intstate=charchwhile(state<){ch=getNextChar()if(''==ch)文件结束breakif(==state){if(''==ch)state=else{state=foutSourse<<ch}}elseif(==state){if('*'==ch){state=commentFlag=false}else{state=foutSourse<<""<<ch}}elseif(==state){if('*'==ch)state=else{state=}}elseif(==state){if('*'==ch)state=elseif(''==ch)state=else{state=}}if(==state)结束状态~处理{commentFlag=truestate=}}if(!commentFlag){cout<<"注释错误~没有结束符:"<<endlscanSuccess=false}elsecout<<"注释已经成功删除:"<<endl}TokenTypeScanner::returnTokenType(strings)返回Token的类型{TokenTypetif(s=="else"){t=ELSE}elseif(s=="if"){t=IF}elseif(s=="int"){t=INT}elseif(s=="return"){t=RETURN}elseif(s=="void"){t=VOID}elseif(s=="while"){t=WHILE}elseif(s==""){t=PLUS}elseif(s==""){t=MINUS}elseif(s=="*"){t=TIMES}elseif(s==""){t=OVER}elseif(s=="<"){t=LT}elseif(s=="<="){t=LEQ}elseif(s==">"){t=GT}elseif(s==">="){t=GEQ}elseif(s=="=="){t=EQ}elseif(s=="!="){t=NEQ}elseif(s=="="){t=ASSIGN}elseif(s==""){t=SEMI}elseif(s==","){t=COMMA}elseif(s=="("){t=LPAREN}elseif(s==")"){t=RPAREN}elseif(s==""){t=LMBRACKET}elseif(s==""){t=RMBRACKET}elseif(s=="{"){t=LBBRACKET}elseif(s=="}"){t=RBBRACKET}elseif(s=="*"){t=LCOMMENT}elseif(s=="*"){t=RCOMMENT}elseif(==charType(sslength())){t=NUM}elseif(==charType(sslength())){t=ID}else{t=ERROR}returnt}DFAStateScanner::charType(charc)返回字符的类型{if(''==c||'n'==c||'t'==c||'r'==c)returnSTARTelseif(c>=''c<='')returnINNUMelseif((c>='A'c<='Z')||(c>='a'c<='z'))returnINIDelseif(c=='<'||c=='>'||c=='='||c=='!')returnINDBSYMelsereturnDONE}charScanner::getNextChar(){if(charIndex<sourseStringlength()){charch=sourseStringcharIndexcharIndexif('n'==ch)lineCountreturnch}elsereturn''}voidScanner::backToLastChar(){if(charIndex>){charch=sourseStringcharIndexcharIndexif('n'==ch)lineCount}}voidScanner::printToken(){ofstreamfoutToken("Tokentxt")ifstreamfin("sourseFiletxt")stringtempintlineCount=intindex=while(getline(fin,temp)){foutToken<<lineCount<<":"foutToken<<temp<<endlwhile(index<tokenListsize()){Tokent=tokenListat(index)if(lineCount==tlineNo){foutToken<<""<<lineCount<<":"indexintwidth=stringheadS=""if(ttokenType>=ttokenType<=)关键字{stringtp=""for(inti=i<widthttokenStringlength()i)tp=""foutToken<<"keyWord:"<<headS<<ttokenString<<""<<tp<<""<<tokenTypeStringttokenType<<""<<endl}elseif(ttokenType>=ttokenType<=)符号{stringtp=""for(inti=i<widthttokenStringlength()i)tp=""foutToken<<"symbols:"<<headS<<ttokenString<<""<<tp<<""<<tokenTypeStringttokenType<<""<<endl}elseif(ttokenType==)NUM{stringtp=""for(inti=i<widthttokenStringlength()i)tp=""foutToken<<"NUM:"<<headS<<ttokenString<<""<<tp<<""<<tokenTypeStringttokenType<<""<<endl}elseif(ttokenType==)ID{stringtp=""for(inti=i<widthttokenStringlength()i)tp=""foutToken<<"ID:"<<headS<<ttokenString<<""<<tp<<""<<tokenTypeStringttokenType<<""<<endl}elseif(ttokenType==)错误{stringtp=""for(inti=i<widthttokenStringlength()i)tp=""foutToken<<"error:"<<headS<<ttokenString<<""<<tp<<""<<tokenTypeStringttokenType<<""<<endl}elseif(ttokenType==ENDFILE)结束{foutToken<<""<<lineCount<<":"foutToken<<ttokenString<<""<<""<<tokenTypeStringttokenType<<""<<endl}}if(lineCount<tlineNo)break}lineCount}finclose()foutTokenclose()}scannerh:#include<string>#include<vector>usingnamespacestd定义的Token的类型(种)~分别对应于else、if、int、return、void、while、、、*、、<、<=、>、>=、==、!=、=、、,、(、)、、、{、}、*、*、num、id、错误、结束typedefenum{ELSE=,IF,INT,RETURN,VOID,WHILE,PLUS,MINUS,TIMES,OVER,LT,LEQ,GT,GEQ,EQ,NEQ,ASSIGN,SEMI,COMMA,LPAREN,RPAREN,LMBRACKET,RMBRACKET,LBBRACKET,RBBRACKET,LCOMMENT,RCOMMENT,NUM,ID,ERROR,ENDFILE}TokenTypetypedefenum{START=,INNUM,INID,INDBSYM,DONE}DFAState定义的Token结构体~包括类型、对应的串、所在代码的行号structToken{TokenTypetokenTypestringtokenStringintlineNo}每种TokenType对应的串~如tokenTypeStringELSE=="ELSE"conststringtokenTypeString={"OTHER","ELSE","IF","INT","RETURN","VOID","WHILE","PLUS","MINUS","TIMES","OVER","LT","LEQ","GT","GEQ","EQ","NEQ","ASSIGN","SEMI","COMMA","LPAREN","RPAREN","LMBRACKET","RMBRACKET","LBBRACKET","RBBRACKET","LCOMMENT","RCOMMENT","NUM","ID","ERROR","ENDFILE"}classScanner{public:boolscanSuccess词法分析是否成功的标志voidgetSourseStringFromFile(strings)通过提供的文件名获取源代码voiddeleteComments()删除注释voidscan()词法分析~将分析的Token放在tokenList数组中Scanner()TokengetTokenAt(int)根据下标从tokenList数组中获取Tokenprivate:DFAStatecharType(char)返回字符的类型~如:空格:数字:字母等chargetNextChar()获取到下一个字符voidbackToLastChar()TokenTypereturnTokenType(strings)根据字符串返回Token类型voidprintToken()将词法分析好的Token输出到文件Tokentxt中stringsourseString获取源代码的字符串intcharIndex配合getNextChar()~指定要取的字符位置stringstr在分析过程中保存Token对应的串boolcommentFlag标注注释开始的标志intlineCount对行号计数~每次获取到'n'就自增vector<Token>tokenList保存的Token序列}Parsercpp:#include"scannerh"#include"parserh"#include<iostream>#include<string>usingnamespacestdParser::Parser(){step=tokenIndex=Error=falsestringpath="atxt"cout<<"请输入文件名:"cin>>pathscannergetSourseStringFromFile(path)scannerdeleteComments()if(scannerscanSuccess){scannerscan()if(scannerscanSuccess){cout<<"开始语法分析"<<endlsyntaxTree=parse()printTree(syntaxTree)if(Error)cout<<"语法分析过程出错:"<<endlelsecout<<"语法分析成功:"<<endl}}}TokenParser::getToken()获取scanner中保存在TokenList数组中的Token~并且每次获取完之后数组下标指向下一个{lastToken=currentTokencurrentToken=scannergetTokenAt(tokenIndex)returncurrentToken}voidParser::syntaxError(strings){foutTree<<s<<">Syntaxerroratline"<<lastTokenlineNo<<"出错附近Token:"<<lastTokentokenString<<"Token类型:"<<tokenTypeStringlastTokentokenType<<endlError=true}voidParser::match(TokenTypeex){if(currentTokentokenType==ex){getToken()}else{syntaxError("匹配"tokenTypeStringex"出错")}}voidParser::printSpace(intn){for(inti=i<ni)foutTree<<""}voidParser::printTree(TreeNode*t){intiwhile(t!=){printSpace(step)switch(t>nodekind){caseVoidK:foutTree<<"VoidK"<<endlbreakcaseIntK:foutTree<<"IntK"<<endlbreakcaseIdK:foutTree<<"IdK:"<<t>attrname<<endlbreakcaseConstK:foutTree<<"ConstK:"<<t>attrval<<endlbreakcaseVarDeclK:foutTree<<"VarDeclK"<<endlbreakcaseArryDeclK:foutTree<<"ArryDeclK"<<endlbreakcaseFunK:foutTree<<"FuncK"<<endlbreakcaseParamsK:foutTree<<"ParamsK"<<endlbreakcaseParamK:foutTree<<"ParamK"<<endlbreakcaseCompK:foutTree<<"CompK"<<endlbreakcaseSelectionStmtK:foutTree<<"If"<<endlbreakcaseIterationStmtK:foutTree<<"While"<<endlbreakcaseReturnStmtK:foutTree<<"Return"<<endlbreakcaseAssignK:foutTree<<"Assign"<<endlbreakcaseOpK:foutTree<<"Op:"foutTree<<tokenTypeStringt>attrop<<endlbreakcaseArryElemK:foutTree<<"ArryElemK"<<endlbreakcaseCallK:foutTree<<"CallK"<<endlbreakcaseArgsK:foutTree<<"ArgsK"<<endlbreakdefault:foutTree<<"UnknownK:Unknownexpkind"<<endlbreak}step进入子节点多输出空格for(i=i<MAXCHILDRENi){if(t>childi!=)printTree(t>childi)}step进入兄弟节点时~由于进入子节点时n了~所以要n回来~从而输出一样的空格空格t=t>sibling}}TreeNode*Parser::newNode(Nodekindkind){TreeNode*p=(TreeNode*)malloc(sizeof(TreeNode))intkif(p==){cout<<"内存分配出错:"<<endl}else{for(k=k<MAXCHILDRENk){p>childk=}p>sibling=p>nodekind=kindp>lineno=currentTokenlineNoif(kind==OpK||kind==IntK||kind==IdK)p>type=Integerif(kind==IdK)p>attrname=""if(kind==ConstK)p>attrval=}returnp}TreeNode*Parser::parse(void){TreeNode*tcurrentToken=getToken()lastToken=currentTokent=declarationlist()if(currentTokentokenType!=ENDFILE){syntaxError("结束错误")}returnt}TreeNode*Parser::declarationlist(){TreeNode*t=declaration()TreeNode*p=t在开始语法分析出错的情况下找到int和void型~过滤掉int和void之前的所有Token~防止在开始时出错后面一错百错while((currentTokentokenType!=INT)(currentTokentokenType!=VOID)(currentTokentokenType!=ENDFILE)){syntaxError("")getToken()if(currentTokentokenType==ENDFILE)break}寻找语法分析的入口~即找到int和voidwhile((currentTokentokenType==INT)||(currentTokentokenType==VOID)){TreeNode*qq=declaration()if(q!=){if(t==){t=p=q}else{p>sibling=qp=q}}}match(ENDFILE)returnt}TreeNode*Parser::declaration(void){TreeNode*t=TreeNode*p=TreeNode*q=TreeNode*s=if(currentTokentokenType==INT){p=newNode(IntK)match(INT)}elseif(currentTokentokenType==VOID){p=newNode(VoidK)match(VOID)}else{syntaxError("类型匹配错误")}if((p!=)(currentTokentokenType==ID)){q=newNode(IdK)q>attrname=currentTokentokenStringcstr()match(ID)if(currentTokentokenType==LPAREN)'(':函数情况{t=newNode(FunK)t>child=pt>child=qmatch(LPAREN)t>child=params()match(RPAREN)t>child=compoundstmt()}elseif(currentTokentokenType==LMBRACKET)'':数组声明{t=newNode(VarDeclK)TreeNode*m=newNode(ArryDeclK)match(LMBRACKET)match(NUM)s=newNode(ConstK)s>attrval=atoi(lastTokentokenStringcstr())m>child=qm>child=st>child=pt>child=mmatch(RMBRACKET)match(SEMI)}elseif(currentTokentokenType==SEMI)''结尾:普通变量声明{t=newNode(VarDeclK)t>child=pt>child=qmatch(SEMI)}else{syntaxError("")}}else{syntaxError("")}returnt}TreeNode*Parser::params(void){TreeNode*t=newNode(ParamsK)TreeNode*p=if(currentTokentokenType==VOID)开头为void~参数列表可能是(void)和(voidid,……)两种情况{p=newNode(VoidK)match(VOID)if(currentTokentokenType==RPAREN)参数列表为(void){if(t!=)t>child=p}else参数列表为(voidid,……)>void类型的变量{t>child=paramlist(p)}}elseif(currentTokentokenType==INT)参数列表为(intid,……){t>child=paramlist(p)}else{syntaxError("")}returnt}TreeNode*Parser::paramlist(TreeNode*k)k可能是已经被取出来的VoidK~但又不是(void)类型的参数列表~所以一直传到param中去~作为其一个子节点{TreeNode*t=param(k)TreeNode*p=tk=没有要传给param的VoidK~所以将k设为while(currentTokentokenType==COMMA){TreeNode*q=match(COMMA)q=param(k)if(q!=){if(t==){t=p=q}else{p>sibling=qp=q}}}returnt}TreeNode*Parser::param(TreeNode*k){TreeNode*t=newNode(ParamK)TreeNode*p=ParamK的第一个子节点TreeNode*q=ParamK的第二个子节点if(k==currentTokentokenType==INT){p=newNode(IntK)match(INT)}elseif(k!=){p=k}if(p!=){t>child=pif(currentTokentokenType==ID){q=newNode(IdK)q>attrname=currentTokentokenStringcstr()t>child=qmatch(ID)}else{syntaxError("")}if((currentTokentokenType==LMBRACKET)(t>child!=)){match(LMBRACKET)t>child=newNode(IdK)match(RMBRACKET)}else{returnt}}else{syntaxError("")}returnt}TreeNode*Parser::compoundstmt(void){TreeNode*t=newNode(CompK)match(LBBRACKET)t>child=localdeclaration()t>child=statementlist()match(RBBRACKET)returnt}TreeNode*Parser::localdeclaration(void){TreeNode*t=TreeNode*q=TreeNode*p=while(currentTokentokenType==INT||currentTokentokenType==VOID){p=newNode(VarDeclK)if(currentTokentokenType==INT){TreeNode*q=newNode(IntK)p>child=qmatch(INT)}elseif(currentTokentokenType==VOID){TreeNode*q=newNode(VoidK)p>child=qmatch(INT)}if((p!=)(currentTokentokenType==ID)){TreeNode*q=newNode(IdK)q>attrname=currentTokentokenStringcstr()p>child=qmatch(ID)if(currentTokentokenType==LMBRACKET){TreeNode*q=newNode(VarDeclK)p>child=qmatch(LMBRACKET)match(RMBRACKET)match(SEMI)}elseif(currentTokentokenType==SEMI){match(SEMI)}else{match(SEMI)}}else{syntaxError("")}if(p!=){if(t==)t=q=pelse{q>sibling=pq=p}}}returnt}TreeNode*Parser::statementlist(void){TreeNode*t=statement()TreeNode*p=twhile(IF==currentTokentokenType||LBBRACKET==currentTokentokenType||ID==currentTokentokenType||WHILE==currentTokentokenType||RETURN==currentTokentokenType||SEMI==currentTokentokenType||LPAREN==currentTokentokenType||NUM==currentTokentokenType){TreeNode*qq=statement()if(q!=){if(t==){t=p=q}else{p>sibling=qp=q}}}returnt}TreeNode*Parser::statement(void){TreeNode*t=switch(currentTokentokenType){caseIF:t=selectionstmt()breakcaseWHILE:t=iterationstmt()breakcaseRETURN:t=returnstmt()breakcaseLBBRACKET:t=compoundstmt()breakcaseID:caseSEMI:caseLPAREN:caseNUM:t=expressionstmt()breakdefault:syntaxError("")currentToken=getToken()break}returnt}TreeNode*Parser::selectionstmt(void){TreeNode*t=newNode(SelectionStmtK)match(IF)match(LPAREN)if(t!=){t>child=expression()}match(RPAREN)t>child=statement()if(currentTokentokenType==ELSE){match(ELSE)if(t!=){t>child=statement()}}returnt}TreeNode*Parser::expressionstmt(void){TreeNode*t=if(currentTokentokenType==SEMI){match(SEMI)returnt}else{t=expression()match(SEMI)}returnt}TreeNode*Parser::iterationstmt(void){TreeNode*t=newNode(IterationStmtK)match(WHILE)match(LPAREN)if(t!=){t>child=expression()}match(RPAREN)if(t!=){t>child=statement()}returnt}TreeNode*Parser::returnstmt(void){TreeNode*t=newNode(ReturnStmtK)match(RETURN)if(currentTokentokenType==SEMI){match(SEMI)returnt}else{if(t!=){t>child=expression()}}match(SEMI)returnt}TreeNode*Parser::expression(void){TreeNode*t=var()if(t==)不是以ID开头~只能是simpleexpression情况{t=simpleexpression(t)}else以ID开头~可能是赋值语句~或simpleexpression中的var和call类型的情况{TreeNode*p=if(currentTokentokenType==ASSIGN)赋值语句{p=newNode(AssignK)p>attrname=lastTokentokenStringcstr()match(ASSIGN)p>child=tp>child=expression()returnp}elsesimpleexpression中的var和call类型的情况{t=simpleexpression(t)}}returnt}TreeNode*Parser::simpleexpression(TreeNode*k){TreeNode*t=additiveexpression(k)k=if(EQ==currentTokentokenType||GT==currentTokentokenType||GEQ==currentTokentokenType||LT==currentTokentokenType||LEQ==currentTokentokenType||NEQ==currentTokentokenType){TreeNode*q=newNode(OpK)q>attrop=currentTokentokenTypeq>child=tt=qmatch(currentTokentokenType)t>child=additiveexpression(k)returnt}returnt}TreeNode*Parser::additiveexpression(TreeNode*k){TreeNode*t=term(k)k=while((currentTokentokenType==PLUS)||(currentTokentokenType==MINUS)){TreeNode*q=newNode(OpK)q>attrop=currentTokentokenTypeq>child=tmatch(currentTokentokenType)q>child=term(k)t=q}returnt}TreeNode*Parser::term(TreeNode*k){TreeNode*t=factor(k)k=while((currentTokentokenType==TIMES)||(currentTokentokenType==OVER)){TreeNode*q=newNode(OpK)q>attrop=currentTokentokenTypeq>child=tt=qmatch(currentTokentokenType)q>child=factor(k)}returnt}TreeNode*Parser::factor(TreeNode*k){TreeNode*t=if(k!=)k为上面传下来的已经解析出来的以ID开头的var,可能为call或var{if(currentTokentokenType==LPARENk>nodekind!=ArryElemK)call{t=call(k)}else{t=k}}else没有从上面传下来的var{switch(currentTokentokenType){caseLPAREN:match(LPAREN)t=expression()match(RPAREN)breakcaseID:k=var()if(LPAREN==currentTokentokenTypek>nodekind!=ArryElemK){t=call(k)}breakcaseNUM:t=newNode(ConstK)if((t!=)(currentTokentokenType==NUM)){t>attrval=atoi(currentTokentokenStringcstr())}match(NUM)breakdefault:syntaxError("")currentToken=getToken()break}}returnt}TreeNode*Parser::var(void){TreeNode*t=TreeNode*p=TreeNode*q=if(currentTokentokenType==ID){p=newNode(IdK)p>attrname=currentTokentokenStringcstr()match(ID)if(currentTokentokenType==LMBRACKET){match(LMBRACKET)q=expression()match(RMBRACKET)t=newNode(ArryElemK)t>child=pt>child=q}else{t=p}}returnt}TreeNode*Parser::call(TreeNode*k){TreeNode*t=newNode(CallK)if(k!=)t>child=kmatch(LPAREN)if(currentTokentokenType==RPAREN){match(RPAREN)returnt}elseif(k!=){t>child=args()match(RPAREN)}returnt}TreeNode*Parser::args(void){TreeNode*t=newNode(ArgsK)TreeNode*s=TreeNode*p=if(currentTokentokenType!=RPAREN){s=expression()p=swhile(currentTokentokenType==COMMA){TreeNode*qmatch(COMMA)q=expression()if(q!=){if(s==){s=p=q}else{p>sibling=qp=q}}}}if(s!=){t>child=s}returnt}intmain(intargc,char*argv){Parserpsystem("PAUSE")returnEXITSUCCESS}parseh:#include<string>#include<fstream>usingnamespacestd种节点类型~分别表示int、id、void、数值、变量声明、数组声明、函数声明、函数声明参数列表、函数声明参数、复合语句体、if、while、return、赋值、运算、数组元素、函数调用、函数调用参数列表、未知节点typedefenum{IntK,IdK,VoidK,ConstK,VarDeclK,ArryDeclK,FunK,ParamsK,ParamK,CompK,SelectionStmtK,IterationStmtK,ReturnStmtK,AssignK,OpK,ArryElemK,CallK,ArgsK,UnkownK}Nodekindtypedefenum{Void,Integer}ExpTypeofstreamfoutTree("tokenTreetxt")输出语法树到文件constintMAXCHILDREN=treeNode定义包括子节点、兄弟节点、所处行号、节点类型、属性、表达式返回类型typedefstructtreeNode{structtreeNode*childMAXCHILDRENstructtreeNode*siblingintlinenoNodekindnodekindunion{TokenTypeopintvalconstchar*name}attrExpTypetype}TreeNodeclassParser{public:Parser()TreeNode*parse(void)TreeNode*syntaxTree语法树根节点private:ScannerscannerTokencurrentToken当前获取的TokenTokenlastToken前一个TokeninttokenIndex配合getToken使用~每获取一次~tokenIndex自增boolError语法分析是否出错intstep用于节点输出时表征节点的先行空格TokengetToken()获取保存在scanner中TokenList数组中的Token~每次获取完之后数组下标指向下一个voidprintSpace(intn)打印n个空格voidsyntaxError(strings)报错的函数~报告出错位置,行号,、出错位置附近的Tokenvoidmatch(TokenTypeex)与目标Token类型ex匹配~如果匹配成功则获取下一个Token,为currentToken赋值,~否则报错voidprintTree(TreeNode*t)打印生成的语法树TreeNode*newNode(Nodekindk)根据节点类型新建节点TreeNode*declarationlist(void)TreeNode*declaration(void)TreeNode*params(void)TreeNode*paramlist(TreeNode*k)TreeNode*param(TreeNode*k)TreeNode*compoundstmt(void)TreeNode*localdeclaration(void)TreeNode*statementlist(void)TreeNode*statement(void)TreeNode*expressionstmt(void)TreeNode*selectionstmt(void)TreeNode*iterationstmt(void)TreeNode*returnstmt(void)TreeNode*expression(void)TreeNode*var(void)TreeNode*simpleexpression(TreeNode*k)TreeNode*additiveexpression(TreeNode*k)TreeNode*term(TreeNode*k)TreeNode*factor(TreeNode*k)TreeNode*call(TreeNode*k)TreeNode*args(void)}测试结果测试数据选择,保存atxt文档中:*AprogramtoperformEucild'sAlgorithmtocomputegcd*intgcd(intu,intv){if(v==)returnuelsereturngcd(v,uuv*v)*uuv*v==umodv*}voidmain(void){intxintyx=input()y=input()output(gcd(x,y))}测试结果分析正确用例结果运行程序结果:去掉注释之后自动生成sourceFiletxt中,正确词法分析结果输出自动生成在Tokentxt中:正确语法分析的结果输出自动生成在tokenTreetxt中:错误用例结果错误处理,,将atxt中“return”改为“return”之后再运行,,错误词法分析结果输出自动生成在Tokentxt中:错误语法分析结果输出自动生成在tokenTreetxt中:总结,收获熟悉C语言的结构、指针、文件方面的使用,学会用startUml构造状态图及用switchcase结构实现状态转换实现词法分析,学会用递归下降方法实现EBNF文法规则进而实现语法分析,熟悉构造编译器的步骤及程序实现的框架及部分方法。,特色有良好的输出界面通过tiny程序修改成CMinus程序其思路和方法和tiny差不多方便理解。,不足程序语法实现部分只用了递归下降分析一种方法。此程序框架与教材《编译原理及实践》附录BTiny编译器的程序框架相似。递归下降分析方法手工实现应经验少程序逻辑错误多调试费时久不能保证程序的高健壮性

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/70

C-Minus词法分析和语法分析设计编译器编译原理课程设计

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利