广工编译原理课程设计报告
编译原理课程设计报告
《编译原理》课程设计报告一、课程设计目的通过课程设计进一步理解高级语言在计算机中的执行过程,了解现代编译器的运作机制,加深对编译原理中重点算法和编译技术的理解,提高自己自学和理解的能力。
学会如何利用已有软件JFLex、Java_cup对词法分析器及语法分析器的构造。
二、设计概述本tiger语言编译器的编译过程涉及到编译五个阶段中的二个,即词法分析器、语法分析器。
其中语法分析后还完成了语法树的打印的构造以及类型检查。
词法分析器由JFLex编译正则式生成,词法分析器编译产生式生成,语法分析器由CUP生成。
结果通过GUI界面呈现在使用者面前。
编译程序需要在单词级别上来分析和翻译源程序,所以首先要识别出单词,而词法分析部分的任务是:从左至右扫描源程序的字符串,按照词法规则(正则文法规则)识别出一个个正确的单词,并转换成该单词相应的二元式(种别码、属性值)交给语法分析使用。
因此,词法分析是编译的基础。
执行词法分析的程序称为词法分析器。
语法分析是编译程序的核心部分,其主要任务是确定语法结构,检查语法错误,报告错误的性质和位置,并进行适当的纠错工作。
三、设计过程(一)设计构思程序主要完成三大功能模块:词法分析器、语法分析器、GUI人机交互界面。
词法分析器由JFLex编译正则式生成,其中必须为外界提供一个获取记号流的接口,实验中定为java_cup.runtime.Symbol next_token。
语法分析器是建立在词法分析器上的,故必须包含词法分析器以便获得记号流,next_token为语法分析器提供TOKEN,语法分析器的对外接口是:java_cup.runtime.Symbol debug_parse(),同时返回语法树的根节点。
GUI 界面是提供人机交互的,它能够依次显示词法分析阶段分析得到的所有TOKEN 的信息,语法阶段生成的语法树,另外对于词法和语法阶段出现的错误在“错误提示”文本框中一一列举出来,提供用户改进代码的信息。
编译原理课程设计报告
课程设计报告( 2021--2022年度第一学期)名称:编译技术课程设计题目:算符优先分析法研究院系:班级:学号:学生姓名:指导教师:设计周数:一周成绩:日期:2021年12 月31日1 课程设计的目的和要求1.1 课程设计的目的本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。
设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。
1.2 课程设计的要求1. 文法使用产生式来定义;2. 分别给出每一个非终结符的FIRSTVT和LASTVT集。
3. 画出算符优先关系表;4. 判定给定的文法是否是算符优先文法;5. 给定符号串判定是否是文法中的句子,分析过程用分析表格的方式打印出来。
2 系统描述举例如下:本次实验使用Visual Studio 2019软件,利用只规定终结符之间的优先关系的自底向上移进-规约法实现对算符优先分析法的研究,输出非终结符的FIRSTVT和LASTVT集,算符优先关系表和对句子的分析表格,均在DOS窗口显示。
2.1 文法的描述G[S]: S->#E#;E->E+T|T;F-P!F|P;T->T*F|F;P->(E)|i2.2 属性文法的描述表2-1 条件语句及其语义规则3 概要设计3.1 概要设计(体现系统的设计思路和主要功能)主要步骤包括:用户自己输入文法,实质上是算数表达式的计算。
构建每个非终结符的FirstVT()和LastVT()集。
构建优先关系符号表。
构建词法分析的程序。
编写主函数,用户输入文法对语句利用算符优先文法进行判别。
算法的主体思想:用栈存储已经看到的输入符号,用优先关系指导移动归约语法分析器的动作,如果栈顶的终结符和下一个输入符之间的优先关系是<或=,则语法分析器移动,表示还没有发现句柄的右端,如果是>关系,就调用归约。
3.2 开发环境实验采用C++程序语言进行设计开发工具为Visual Studio 20194 详细设计4.1 系统的类图图4-1 文法类图4.2 主要算法的流程图图4-2 求非终结符的FIRSTVT 和LASTVT 集流程图求LASTVT 集的过程与此类似,但符号串的扫描顺序是从后开始若产生式右部第一个字符为非终结符 则直接将其加入first 集中else first[x].insert(str[0]);寻找该非终结符 的first 集 dfs(y);将该非终结符的first 集也加进去for (; it != first[y].end(); it++)first[x].insert(*it);if (isupper(str[0]))若产生式右部第一个字符为非终结符 string& left = VN_set[x].left;string&str = VN_set[x].right[i];产生产生式左部非终结符的FIRSTVT 集图4-3 构造算符优先关系表流程图图4-4 对输入串进行算符优先分析流程图4.3 数据分析与定义char relation[MAX][MAX]; //算符优先关系表vector<char> VT;vector<WF> VN_set; //类型为文法的数组VN_setmap<string, int> VN_dic; //map映射,一条产生式对应的第几条的序号set<char> first[MAX]; //FIRSTVT集set<char> last[MAX]; //LASTVT集4.4 系统界面设计用户输入文法个数和每条产生式的内容后,输出结果格式如下:分为:产生式、FIRSTVT集、;LASTVT集、算符优先关系表和分析过程图4-5 系统输出界面概况5 测试方法和测试结果5.1 测试用例1输入如程序5-1所示。
广东工业大学编译原理课设
课程设计课程名称编译原理题目名称对PL/0的修改与扩充学生学院计算机学院专业班级学号学生姓名指导教师2014 年 1 月 3 日一.课程设计目的在分析理解一个教学型编译程序(如PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。
达到进一步了解程序编译过程的基本原理和基本实现方法的目的。
二.课程设计要求(1)扩充赋值运算:*= 和 /=(2)扩充语句(Pascal 的FOR 语句):FOR <变量>:=<表达式>STEP<表达式> UNTIL<表达式>Do<语句>三.课程设计环境与工具1. 程序运行环境:(1)运行平台:Windows XP(2)实现工具:Borland C++ Building 6.0(3)教学型编译程序:PL/0 2.源程序:PL/0 源代码四.结构设计说明PL/0编译程序的结构图Pl0 源 程 序词法分析程序语法分析程序代码生产程序目 标 程 序表 格 管 理程序出错 处 理 程 序各功能模块描述过程或函数名简要功能说明pl0 主程序error 出错处理,打印出错位置和错误编码getsym 词法分析,读取一个单词getch 漏掉空格,读取一个字符gen 生成目标代码,并送入目标程序区test 测试当前单词符号是否合法block 分程序分析处理过程enter 登录名字表position(函数) 查找标识符在名字表中的位置constdeclaration 常量定义处理vardeclaration 变量说明处理listode 列出目标代码清单statement 语句处理expression 表达式处理term 项处理factor 因子处理condition 条件处理interpret 对目标代码的解释执行程序base(函数) 通过静态链求出数据区的基地址PL/0编译程序的总体流程图五、主要成分描述 1、符号表全程量一维数组。
编译原理课程设计 期末实验报告 编译原理中重要的、有机联系的文法、词法、语法,作一个具体的了解和掌握
编译原理课程设计[课程设计目的]使学生能通过课程设计,对编译原理中重要的、有机联系的文法、词法、语法,作一个具体的了解和掌握。
[课程设计要求]要求对一个简单的数值表达式进行文法、词法、语法分析,并结合实验,写出课程设计报告。
[课程设计时数] 8学时。
[课程设计内容]对一个简单的数值表达式进行文法、词法、语法分析。
该表达式只含双目运算符:+、-、*、/ ,1位的数值和括号。
一:词法部分实验1,词法源程序代码:#include<stdio.h>#include<string.h>#include<iostream.h>char prog[80],token[8];char ch;int syn,p,m=0,n,row,sum=0;char *rwtab[6]={"begin","if","then","while","do","end"};void scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0'&&ch<='9')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=11;if(sum>32767)syn=-1;}else switch(ch){case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break; case'/':syn=14;token[0]=ch;break; case'+':syn=15;token[0]=ch;break; case'-':syn=16;token[0]=ch;break; case'=':syn=25;token[0]=ch;break; case';':syn=26;token[0]=ch;break; case'(':syn=27;token[0]=ch;break; case')':syn=28;token[0]=ch;break; case'#':syn=0;token[0]=ch;break; case'\n':syn=-2;break;default: syn=-1;break;}}void main(){p=0;row=1;cout<<"Please input string:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){case 11: cout<<"("<<syn<<","<<sum<<")"<<endl; break;case -1: cout<<"Error in row "<<row<<"!"<<endl; break;case -2: row=row++;break;default: cout<<"("<<syn<<","<<token<<")"<<endl;break;}}while (syn!=0);}2,词法实验结果验证:(1)给定源程序begin x:=10; if x>2 then x:=3*x+1/2; end#输出结果如下2,源程序(包括上式未有的while/,do以及判断错误语句),结果图如上:beginx<=$;whilea<2dob<>10-x;end#。
广工编译原理实验报告
<<编译原理>>课内实验报告项目名称 PL/0编译器学院____ 计算机学院_______专业_ _年级班别________学号 _学生姓名_______ ___辅导教师_______成绩_______ _______目录一、课内实验的内容------------------------------------------4二、实验修改部分--------------------------------------------4三、概述-------------------------------------------------11四、结构设计说明-------------------------------------------11五、各功能模块描述-----------------------------------------14六、主要成份描述------------------------------------------14七、测试用例----------------------------------------------16八、开发过程和完成情况--------------------------------------21一、课内实验的内容对PL/0作以下修改扩充:(1)增加单词:保留字 ELSE,FOR, STEP,RETURN运算符 +=,-=,++,--,&,|,~(2)修改单词:不等号# 改为 <>(3)增加条件语句的ELSE子句二、实验修改部分:1、增加四个保留字和七个运算符,共十一个单词。
修改部分:#define symnum 43 //保留字从32增加到43个2、增加五个保留字:ELSE,FOR,STEP,RETURN○1头文件pl0.henum symbol { 新增加单词: elsesym, forsym, stepsym,returnsym, pluseq/* += */,plusone/* ++ */,plus/* + */,minuseq/* -= */,minusone/* -- */,minus/* - */,and,or,not}○2头文件pl0.h#define norw 24 //关键字从13增加到24个○3PL0.cppinit();新增加:(增加后数组的内容要再次根据字母顺序重新排列)strcpy(&(word[0][0]),"begin");strcpy(&(word[1][0]),"call");strcpy(&(word[2][0]),"const");strcpy(&(word[3][0]),"do");strcpy(&(word[4][0]),"else"); /*增加单词:保留字else*/strcpy(&(word[5][0]),"end");strcpy(&(word[6][0]),"for"); /*增加单词:保留字 for*/strcpy(&(word[7][0]),"if");strcpy(&(word[8][0]),"odd");strcpy(&(word[9][0]),"procedure");strcpy(&(word[10][0]),"read");strcpy(&(word[11][0]),"return");/*增加单词:保留字 return*/strcpy(&(word[12][0]),"step"); /*增加单词:保留字step*/strcpy(&(word[13][0]),"then");strcpy(&(word[14][0]),"while");strcpy(&(word[15][0]),"write");wsym[0]=beginsym;wsym[1]=callsym;wsym[2]=constsym;wsym[3]=dosym;wsym[4]=elsesym; /*else*/wsym[5]=endsym;wsym[6]=forsym; /*for*/wsym[7]=ifsym;wsym[8]=oddsym;wsym[9]=procsym;wsym[10]=readsym;wsym[11]=returnsym; /*return*/wsym[12]=stepsym; /*step*/wsym[13]=thensym;wsym[14]=whilesym;wsym[15]=writesym;3、增加四个运算符:+=,-=,++,-- ,∧,∨,┓PL0.cppgetsym();增加对+,-,++,--,+=,-=的识别;Statement();增加对+,-,++,--,-=的语句的处理;○1Init()中改动:ssym[‘&’]=and;ssym[‘|’]=or;ssym[‘~’]=not;facbegsys[plusone]=true; // 添加前自加运算facbegsys[minusone]=true;// 添加前自减运算○2Getsym()增加的内容:int getsym() {int i,j,k;while( ch==' '||ch==10||ch==9){getchdo;}if(ch>='a'&&ch<='z'){k=0;do{if(k<al){a[k]=ch;k++;}getchdo;}while(ch>='a'&&ch<='z'||ch >='0'&&ch<='9');a[k]=0;strcpy(id,a);i=0;j=norw-1;do{k=(i+j)/2;if(strcmp(id,word[k])<=0){j=k-1;}if(strcmp(id,word[k])>=0){i=k+1;}}while(i<=j);if(i-1>j){sym=wsym[k];}else{sym=ident;}}else{if(ch>='0'&&ch<='9'){k=0;num=0;sym=number;do{num=10*num+ch-'0';k++;getchdo;}while(ch>='0'&&ch<='9'); /*获取数字的值*/k--;if(k>nmax){error(30);}}else{if(ch==':')/*检测赋值符号*/{getchdo;if(ch=='='){sym=becomes;getchdo;}else{sym=nul; /*不能识别的符号*/}}else{if(ch=='<')/*检测小于或小于等于符号*/{getchdo;if(ch=='='){sym=leq;getchdo;}else{sym=lss;}}else if(ch=='>') /*检测大于或大于等于符号*/{getchdo;if(ch=='='){sym=geq;getchdo;}else{sym=gtr;}}/*这里之间为添加的内容*/else if(ch=='+'){ /*检测+,+=,++符号*/getchdo;if(ch=='='){sym=pluseq;getchdo;}elseif(ch=='+'){sym=plusone;getchdo;}else{sym=plus;}}elseif(ch=='-'){/*检测-,-=,--符号*/getchdo;if(ch=='='){sym=minuseq;getchdo;}elseif(ch=='-'){sym=minusone;getchdo;}else{sym=minus;}}/*这里之间为添加的内容*/else{sym=ssym[ch];/* 当符号不满足上述条件时,全部按照单字符号处理*///getchdo;//richardif(sym!=period){getchdo;}//end richard}}}}return 0; }○3Statement()增加的内容:(将本来“if(sym==becomes)……”部分的内容修改为处理++,+=,--,-=),并在Statement()中定义变量int sym2;if(sym==becomes||sym==pluseq||sy m==minuseq||sym==plusone||sym==minusone){sym2=sym;getsymdo;gendo(lod,lev-table[i].level,tab le[i].adr);}else{error(13);}if(sym2==plusone||sym2==minusone )/* 准备按照a++、a--语句处理,与read类似*/{if(i!=0){if(sym2==plusone){gendo(lit,0,1);gendo(opr,0,2);gendo(sto,lev-table[i].level,table[ i].adr);}if(sym2==minusone){gendo(lit,0,1);gendo(opr,0,3);gendo(sto,lev-table[i].level,table[ i].adr);}}}else{memcpy(nxtlev,fsys,sizeof(bool)* symnum);expressiondo(nxtlev,ptx,lev);if(i!=0){if(sym2==becomes)gendo(sto,lev-table[i].level,tab le[i].adr);if(sym2==pluseq){gendo(opr,0,2);gendo(sto,lev-table[i].level,tab le[i].adr);}if(sym2==minuseq){gendo(opr,0,3);gendo(sto,lev-table[i].level,tab le[i].adr);}}}//else}}}4、修改单词:不等号# 改为 <>●PL0.cppinit();移除: ssym['#']=neq;○1在getsym()里增加对<>的识别(在<或<=基础上修改)。
《编译原理》设计方案报告
《编译原理》课程设计报告设计题目:pl0编译器设计一、PL0程序的文法及,指令及属性翻译简化c语言文法定义(LL(1)文法)C程序::=void main(){函数体}函数体::=变量定义部分语句列变量定义部分::=变量定义变量定义部分| ɛ变量定义::=int 变量表变量表::=标识符|标识符,变量表语句列::=语句语句列| ɛ语句::=条件语句| 循环语句| 读语句| 写语句| 复合语句| 表达式语句| 空语句条件语句::=if(表达式)语句循环语句::=while(表达式)语句读语句::=read(变量表);写语句::=write(表达式表);复合语句::={语句列};表达式语句::=表达式;空语句::=;表达式定义(算符优先文法)表达式::=变量=表达式| 变量+=表达式| 变量-=表达式| 变量*=表达式| 变量/=表达式| 变量%=表达式| 表达式1表达式1::=表达式1 || 表达式2 | 表达式2表达式2::=表达式2&&表达式3 | 表达式3表达式3::=表达式3==表达式4 | 表达式3!=表达式4 | 表达式3>=表达式4 | 表达式3>表达式4 | 表达式3<=表达式4 | 表达式3<表达式4 | 表达式4表达式4::=表达式4+表达式5 | 表达式4-表达式5 | 表达式5表达式5::=表达式5*表达式6 | 表达式5/表达式6 |表达式5/表达式6 |表达式6表达式6::=!表达式7表达式7::=(表达式) | 变量| 常量PL0文法定义《程序》::=《分程序》.《分程序》::=《常量定义》;《常后分程序》|《常后分程序》《常后分程序》::=《变量定义》;《变后分程序》|《变后分程序》《变后分程序》::=《过程定义》;《变后分程序》|《语句》《常量定义》::=const 《常量定义表》《常量定义表》::=id = number | id = number,《常量定义表》《变量定义》::= var 《变量表》《变量表》::=id | id,《变量表》《过程定义》::=procedure id ;《分程序》《语句》::=《赋值语句》|《条件语句》|《循环语句》|《读语句》|《写语名》|《复合语句》| 《过程调用语句》|ε《赋值语句》::=id := 《表达式》《读语句》::=read(《变量表》)《写语句》::=write(《表达式表》)《表达式表》::=《表达式》| 《表达式》,《表达式表》《条件语句》::=if 《条件表达式》then 《语句》《循环语句》::=while 《条件表达式》do 《语句》《复合语句》::=begin 《语句列》end《过程调用语句》::=call id《参量表》::=《有参表》|ε《有参表》::=《表达式》,《有参表》|《表达式》《表达式》::=+《表达式1》|-《表达式1》|《表达式1》《表达式1》::=《表达式1》+《表达式2》|《表达式1》-《表达式2》|《表达式2》《表达式2》::=《表达式2》*《表达式3》|《表达式2》/《表达式3》| 《表达式2》mod 《表达式3》|《表达式3》《表达式3》::=id | number | (《表达式》)《条件表达式》::=《条件表达式》or 《条件表达式1》|《条件表达式1》《条件表达式1》::=《条件表达式1》and 《条件表达式2》| 《条件表达式2》《条件表达式2》::=not 《条件表达式3》|《条件表达式3》《条件表达式3》::=(《条件表达式》)|《关系表达式》《关系表达式》::=《表达式》>《表达式》《关系表达式》::=《表达式》>=《表达式》《关系表达式》::=《表达式》<《表达式》《关系表达式》::=《表达式》<=《表达式》《关系表达式》::=《表达式》=《表达式》《关系表达式》::=《表达式》#《表达式》PL0栈式机指令指令格式:指令码(f) 所在层数差(l),操作数(a)PL0栈式机指令:LIT:将常数a取到栈顶LOD:将位于(当前层-l)层处的变量a取到栈顶STO:将栈顶处值存储到指定位置,l,a同上CALL 调用当前-l层处的过程aINT:为调用过程在栈中开辟数据区,a为单元个数JMP:无条件转移指令,a目标地址JPC:条件转移指令,栈顶值的布尔值为非真时转移到a处,否则执行下面语句OPR:关系运算或算术运算PL0属性翻译MCONST(const:常量定义开始), V AR(var:变量定义开始), PROCEDURE(procedure:过程定义开始),CALL(call:过程调用语句),BEGIN(begon:复合语句开始),END(end:复合语句结束),IF(if:条件语句开始),THEN(then:条件结束),WHILE(while:循环语句开始), DO(do:循环条件结束), READ(read:读语句),WRITE(write:输出语句), ODD(odd:判奇运算),//分隔符、运算符号DOT(点:.),COMMA(逗号:,), SEMICOLON(分号:;), LPAREN(左括号:(), RPAREN(右括号:)), ASSIGNOP(赋值::=), PLUSOP(加法运算符号:+), MINUSOP(减法运算符:-), MULTOP(乘法运算符:*), DIVOP(除法运算符:/),GT(大于:>),GE(大于等于:>=),LT(小于:<),LE(小于等于:<=),EQ(等于:=),NE(不等:#),ENDF(输入结束符),//分析过程中需要的非终结符号SERVERKEY(保留字), FACTOR(因子),ROP(关系运算), CONSTANT(常量部份定义), V ARIABLE(变量部份定义), IDENT(自定义标识符), NUMBER(常数)二、符号表的结构,组织,填写及查找1、符号表结构const char *pName; //符号名称int kind; //符号类别,由上面单词分类确定int val; //符号表中的位置值int level; //符号的层数int parent; //符号的作用域int size; //过程长度char strBuff[MAXLENSTR]; //符号堆2、符号表的组织符号表的组织方式有:线性表、散列表、树结构等,其必须维持源程序中的作用域信息。
广工编译原理课程设计
广工编译原理课程设计一、课程目标知识目标:1. 理解编译原理的基本概念,掌握编译器各阶段的工作原理及相互关系。
2. 学会使用一种编程语言(如C语言)进行词法分析、语法分析、语义分析及中间代码生成。
3. 掌握基本的代码优化和目标代码生成方法。
技能目标:1. 能够运用所学编译原理知识,独立完成一个简单的程序设计语言的编译器设计。
2. 培养学生运用形式语言和自动机理论解决实际问题的能力。
3. 提高学生的编程实践能力,培养良好的编程习惯。
情感态度价值观目标:1. 培养学生对编译原理课程的兴趣,激发学习热情,形成积极的学习态度。
2. 培养学生的团队协作意识,学会与他人共同分析问题、解决问题。
3. 增强学生的创新意识,鼓励尝试不同的编译技术,培养勇于探索的精神。
课程性质:本课程为计算机科学与技术专业核心课程,旨在教授编译原理的基本知识,提高学生的编程实践能力。
学生特点:学生已具备一定的编程基础,具有较强的逻辑思维能力和抽象思维能力。
教学要求:结合课程性质和学生特点,注重理论与实践相结合,强调动手实践,培养学生解决实际问题的能力。
通过课程目标的具体分解,使学生在掌握编译原理知识的同时,提高编程技能和团队协作能力。
二、教学内容1. 编译原理概述:介绍编译器的定义、编译过程、编译器的结构及其各阶段的作用。
教材章节:第1章 编译原理概述2. 词法分析:讲解词法分析的基本概念、词法分析器的功能、词法规则及其实现方法。
教材章节:第2章 词法分析3. 语法分析:介绍语法分析的基本概念、自上而下和自下而上的语法分析方法、语法分析器的实现技术。
教材章节:第3章 语法分析4. 语义分析:讲解语义分析的作用、类型检查、语义分析器的实现方法。
教材章节:第4章 语义分析5. 中间代码生成:介绍中间代码的定义、中间代码的表示形式、中间代码生成的方法。
教材章节:第5章 中间代码生成6. 代码优化:讲解代码优化的目的、基本优化方法、目标代码生成。
编译原理课程设计报告
实验1:用Lex设计词法分析器1实验目的:学会用lex设计一个词法分析器。
实验内容:使用lex为下述文法语言写一个词法分析器。
实验要求:输入为用该语言所写的源程序文件;输出为记号序列,每个记号显示为二元组(记号名,记号属性值)的形式。
输出可以在屏幕上,也可以输出到文件中。
不要求建立符号表。
在cygwin下用flex和gcc工具将实验调试通过,并能通过例子parser0中testcases 目录下的测试例的测试。
实验参考:和。
语言文法:<程序> PROGRAM <标识符> ; <分程序><分程序> <变量说明> BEGIN <语句表> END.<变量说明> VAR <变量说明表>;<变量说明表><变量表>: <类型> | <变量表>: <类型>; <变量说明表><类型> INTEGER | REAL<变量表> <变量> | <变量>, <变量表><语句表> <语句> | <语句>; <语句表><语句> <赋值语句> | <条件语句> | <WHILE语句> | <复合语句><赋值语句><变量> := <算术表达式><条件语句> IF <关系表达式> THEN <语句> ELSE <语句><WHILE语句> WHILE <关系表达式> DO <语句><复合语句> BEGIN <语句表> END<算术表达式> <项> | <算术表达式> + <项> | <算术表达式> - <项><项> <因式> | <项> * <因式> | <项> / <因式><因式> <变量> | <常数> | (<算术表达式>)<关系表达式> <算术表达式> <关系符> <算术表达式><变量> <标识符><标识符> <标识符><字母> | <标识符><数字> | <字母><常数> <整数> | <浮点数><整数> <数字> | <数字> <整数><浮点数> .<整数> | <整数>.<整数><关系符> < | <= | = | > | >=| <><字母> A | B | …| X | Y | Z | a | b | …| x | y | z<数字>0|1|2|…|9程序代码:%{#include <>#define LT 1#define LE 2#define GT 3#define GE 4#define EQ 5#define NE 6#define PROGRAM 7#define END 13#define VAR 9#define IF 10#define THEN 11#define ELSE 12#define WHILE 18#define DO 19#define ID 20#define NUMBER 21#define RELOP 22#define NEWLINE 23#define ERRORCHAR 24%}delim [ \t \n]ws {delim}+letter [A-Za-z]digit [0-9]id _|{letter}({letter}|{digit})*number {digit}+(\.{digit}+)?(E[+-]?{digit}+)?int1 {digit}|{digit}{int1}*/%s COMMENT%%<INITIAL>"/*" {BEGIN COMMENT;ECHO;} <COMMENT>"*/" {BEGIN INITIAL;ECHO;} <COMMENT>.|\n {ECHO;}/* ECHO是一个宏,相当于 fprintf(yyout, "%s", yytext)*/ <INITIAL>{ws} {;}<INITIAL>while {return (WHILE);}<INITIAL>do {return (DO);}<INITIAL>PROGRAM {return (PROGRAM);}<INITIAL>end {return (END);}<INITIAL>VAR {return (VAR);}<INITIAL>if {return (IF);}<INITIAL>then {return (THEN);}<INITIAL>else {return (ELSE);}<INITIAL>{id} {return (ID);}<INITIAL>{number} {return (NUMBER);}<INITIAL>"<" {return (RELOP);}<INITIAL>"<=" {return (RELOP);}<INITIAL>"=" {return (RELOP);}<INITIAL>"<>" {return (RELOP);}<INITIAL>">" {return (RELOP);}<INITIAL>">=" {return (RELOP);}<INITIAL>"+" {return (RELOP);}<INITIAL>"-" {return (RELOP);}<INITIAL>"*" {return (RELOP);}<INITIAL>"/" {return (RELOP);}<INITIAL>":=" {return (RELOP);}<INITIAL>";" {return (RELOP);}<INITIAL>"." {return (RELOP);}<INITIAL>"," {return (RELOP);}<INITIAL>. {return ERRORCHAR;}%%int yywrap (){return 1;}void writeout(int c){switch(c){case ERRORCHAR: fprintf(yyout, "(ERRORCHAR, \"%s\") ", yytext);break;case RELOP: fprintf(yyout, "(RELOP, \"%s\") ", yytext);break;case WHILE: fprintf(yyout, "(WHILE, \"%s\") ", yytext);break;case DO: fprintf(yyout, "(DO, \"%s\") ", yytext);break;case NUMBER: fprintf(yyout, "(NUM, \"%s\") ", yytext);break;case ID: fprintf(yyout, "(ID, \"%s\") ", yytext);break;case NEWLINE: fprintf(yyout, "\n");break;case PROGRAM: fprintf(yyout, "(PROGRAM, \"%s\") ", yytext);break;case END: fprintf(yyout, "(END, \"%s\") ", yytext);break;case VAR: fprintf(yyout, "(VAR, \"%s\") ", yytext);break;case IF: fprintf(yyout, "(IF, \"%s\") ", yytext);break;case THEN: fprintf(yyout, "(THEN, \"%s\") ", yytext);break;case ELSE: fprintf(yyout, "(ELSE, \"%s\") ", yytext);break;default:break;}return;}int main (int argc, char ** argv){int c,j=0;if (argc>=2){if ((yyin = fopen(argv[1], "r")) == NULL){printf("Can't open file %s\n", argv[1]);return 1;}if (argc>=3){yyout=fopen(argv[2], "w");}}while (c = yylex()){writeout(c);j++;if (j%5 == 0) writeout(NEWLINE);}if(argc>=2){fclose(yyin);if (argc>=3) fclose(yyout);}return 0;}测试文件为:PROGRAM test;VAR i, j, k: INTEGER;f0: REAL;BEGINi := 1;j := 1;k := 0;f0 := ;WHILE k<=100 DOBEGINIF j <20 THENBEGINj := i;k := k+1;f0 := f0*ENDELSEBEGINj := k;k := k-2;f0 := f0/.2ENDENDEND.运行结果:实验2:用Lex设计词法分析器2实验目的:学会用lex设计一个词法分析器,并考虑其与后续语法分析器的链接问题。
编译原理课程设计报告毕业论文
编译原理课程设计报告一、课程设计目的通过课程设计,可以进一步了解高级语言在计算机中的执行过程,了解现代编译器的运行机制,加深对编译原理中关键算法和编译技术的理解,提高自学和理解能力。
了解如何利用现有软件JFLex和Java_cup构造词法分析器和解析器。
二、设计概述这个tiger语言编译器的编译过程涉及到编译五个阶段中的两个,即词法分析器和语法分析器。
其中,解析后完成语法树打印的构建,以检查类型。
词法分析器由JFLex 编译器正则公式生成,词法分析器由编译器产生式生成,解析器由CUP生成。
结果通过GUI界面呈现给用户。
编译器需要对源程序进行单词级的分析和翻译,所以首先要做的就是识别单词,而词法分析的任务就是从左到右扫描源程序的字符串,根据词法规则(常规语法规则)识别出正确的单词,并转换成单词对应的二进制形式(类别码,属性值)进行语法分析。
所以词法分析是编译的基础。
执行词法分析的程序叫做词法分析器。
语法分析是编译器的核心部分。
它的主要任务是确定语法结构,检查语法错误,报告错误的性质和位置,并进行适当的纠错。
三、设计程序(一)设计构思该程序主要完成三个功能模块:词法分析器、语法分析器和GUI人机界面。
词法分析器由JFLex编译正则公式生成,其中必须为外界提供一个获取令牌流的接口。
实验中命名为Java _ cup . runtime . symbol next _ token。
解析器是建立在词法分析器上的,所以它必须包含词法分析器来获取令牌流。
next_token为解析器提供了令牌。
解析器的对外接口是:Java _ cup . runtime . symbol debug _ parse(),它返回语法树的根节点。
GUI 提供人机交互。
它可以顺序显示词法分析阶段获得的所有标记信息和语法阶段生成的语法树。
此外,词法和语法阶段的错误会在“错误提示”文本框中列出,为用户提供改进代码的信息。
流程图:鲍·阿布辛Print.java//打印出语法树……//Tiger 的抽象语法类数据包错误消息ErrorMsg.java//用于生成包含详细信息的错误消息为cupparser 打包Java _ cup.runtime//support包解析Grm.java//解析分析器MainInterface.java//图形用户界面Sym.java//令牌的十进制表示Yylex.java//莱克斯分析器包装语义Entry.java//用于值环境中的绑定Env.java//保存一个值、类型环境和一个错误打印机ExpTy.java//持有翻译和类型检查的结果FunEntry.java//用于函数绑定程序输入流 词法分析程序 GUI 界面句法分析程序 代币 语法树 标记流 错误的语法和类词汇错误Semant.java//主类型检查模块VarEntry.java//用于变量绑定包装符号Symbol.java//使字符串成为独特的符号对象Table.java//用示波器做环境包翻译包类型//描述tiger _ languagetypes(二)词法分析程序这部分工作主要是通过正则表达式的编写,熟悉使用JFLex正确编写正则表达式,并生成相应的词法分析器。
《编译原理》设计方案报告
《编译原理》设计方案报告一、项目概述二、课程目标本课程的主要目标是使学生能够掌握编译器的设计与实现原理,理解编译过程中的各个环节,以及掌握常见的编译器构建工具和技术。
具体目标如下:1.理解编译器的基本原理和工作流程;2.掌握常见的编译器构建工具和技术;3.能够独立设计和实现简单的编译器;4.培养学生的系统设计和问题解决能力。
三、课程内容本课程的主要内容包括:1.编译器的概念和基本原理;2.词法分析器和语法分析器的设计与实现;3.语义分析和中间代码生成;4.优化和目标代码生成;5.编译器构建工具和技术。
四、教学方法本课程采用以学生为中心的教学方法,主要包括以下几种教学手段:1.模块化教学:将课程内容分为多个模块,每个模块进行独立的教学和实践;2.理论与实践相结合:通过理论课、实验课等形式,使学生能够将理论知识应用到实际中;3.项目驱动教学:引入编译器设计与实现的实际项目,让学生能够在实践中巩固所学的知识;4.小组合作学习:将学生分成小组,进行协作学习,增强学生的团队合作能力。
五、评价方式为了评价学生对课程内容的掌握程度,本课程采用以下评价方式:1.平时成绩:包括课堂表现、作业和实验成绩等;2.项目成果:针对编译器设计与实现的项目,评价学生的项目成果和实现质量;3.期末考试:以闭卷考试形式对学生的总体掌握情况进行评价。
六、项目进度安排本课程的项目进度安排如下:1.第1-2周:介绍编译器的概念和基本原理;2.第3-6周:词法分析器和语法分析器的设计与实现;3.第7-9周:语义分析和中间代码生成;4.第10-12周:优化和目标代码生成;5.第13-14周:编译器构建工具和技术;6.第15-16周:项目演示和总结。
七、教学资源支持为了支持本课程的教学,我们将提供以下教学资源:1.教材:选用经典的编译原理教材,如《编译原理》(龙书)等;2.课件:编写详细的课件,包括理论知识和实践案例;3.实验指导:编写实验指导书,引导学生进行编译器设计与实现的实践;4. 实验环境:提供编译器构建工具和开发环境,如Lex/Flex、Yacc/Bison等。
编译课程设计报告
编译课程设计报告一、教学目标本课程的教学目标是使学生掌握编译原理的基本概念、方法和算法,培养学生运用编译原理解决实际问题的能力。
具体目标如下:1.知识目标:(1)了解编译原理的基本概念,如编译器、源语言、目标语言等。
(2)掌握编译过程中的各个阶段,如词法分析、语法分析、语义分析、中间代码生成、目标代码生成等。
(3)熟悉常见编译优化技术,如代码简化、死代码消除、循环优化等。
(4)了解编译器实现的基本方法,如递归下降分析、LL分析、LR分析等。
2.技能目标:(1)能够使用编译原理相关工具,如lex、yacc等。
(2)具备简单的编译器设计与实现能力。
(3)能够分析程序的性能,并应用编译优化技术进行优化。
3.情感态度价值观目标:(1)培养学生对编译原理的兴趣,提高学生自主学习的积极性。
(2)培养学生团队合作精神,提高学生解决实际问题的能力。
二、教学内容本课程的教学内容主要包括以下几个部分:1.编译原理基本概念:介绍编译器、源语言、目标语言等基本概念。
2.编译过程及其各个阶段:讲解词法分析、语法分析、语义分析、中间代码生成、目标代码生成等阶段。
3.编译优化技术:介绍代码简化、死代码消除、循环优化等优化技术。
4.编译器实现方法:讲解递归下降分析、LL分析、LR分析等实现方法。
5.编译器工具使用:介绍lex、yacc等工具的使用方法。
6.编译器设计与实现:讲解编译器的设计与实现过程。
三、教学方法本课程采用讲授法、讨论法、案例分析法和实验法等多种教学方法,以激发学生的学习兴趣和主动性。
1.讲授法:用于讲解编译原理的基本概念、方法和算法。
2.讨论法:学生针对编译原理中的重点、难点问题进行讨论,提高学生的理解能力。
3.案例分析法:通过分析实际案例,使学生更好地掌握编译原理的应用。
4.实验法:让学生亲自动手实现简单的编译器,提高学生的实践能力。
四、教学资源本课程的教学资源包括教材、参考书、多媒体资料和实验设备等。
1.教材:选用《编译原理》等权威教材,为学生提供系统、科学的学习资料。
编译原理课程设计报告C-语言词法与语法分析器的实现
编译原理课程设计报告课题名称:编译原理课程设计C-语言词法与语法分析器的实现C-词法与语法分析器的实现1.课程设计目标(1)题目实用性C-语言拥有一个完整语言的基本属性,通过编写C-语言的词法分析和语法分析,对于理解编译原理的相关理论和知识有很大的作用。
通过编写C-语言词法和语法分析程序,能够对编译原理的相关知识:正则表达式、有限自动机、语法分析等有一个比较清晰的了解和掌握。
(2)C-语言的词法说明①语言的关键字:else if int return void while所有的关键字都是保留字,并且必须是小写。
②专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */③其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter*NUM = digit digit*letter = a|..|z|A|..|Zdigit = 0|..|9注:ID表示标识符,NUM表示数字,letter表示一个字母,digit表示一个数字。
小写和大写字母是有区别的。
④空格由空白、换行符和制表符组成。
空格通常被忽略。
⑤注释用通常的c语言符号/ * . . . * /围起来。
注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。
注释不能嵌套。
(3)程序设计目标能够对一个程序正确的进行词法及语法分析。
2.分析与设计(1)设计思想a.词法分析词法分析的实现主要利用有穷自动机理论。
有穷自动机可用作描述在输入串中识别模式的过程,因此也能用作构造扫描程序。
通过有穷自动机理论能够容易的设计出词法分析器。
b.语法分析语法分析采用递归下降分析。
递归下降法是语法分析中最易懂的一种方法。
它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。
因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。
广工编译原理课程设计报告
课程设计课程名称___编译原理__________题目名称___PL/0编译器的扩充__学生学院___计算机学院_________专业班级_计算机科学与技术13(9)学号学生姓名指导教师___林志毅________________2016年1月2日一、已完成的内容:(1)扩充赋值运算:*=和/=(2)扩充语句(Pascal的FOR语句)FOR<变量>:=<表达式>STEP<表达式>UNTIL<表达式>Do<语句> (3)增加类型:①字符类型;②实数类型。
VARIABLE*/GetSym();if(SYM==BECOMES||SYM==TIMESBECOMES||SYM==SLASHBECOMES||SYM==PLUSBECOMES||SYM==MINUSBECOMES){RELOP=SYM;if(SYM!=BECOMES){TABLE[i].;}GetSym();}elseError(13);EXPRESSION(FSYS,LEV,TX);if(RELOP==TIMESBECOMES){GEN(OPR,0,4);}elseif(RELOP==SLASHBECOMES){GEN(OPR,0,5);}elseif(RELOP==PLUSBECOMES){GEN(OPR,0,2);}elseif(RELOP==MINUSBECOMES){GEN(OPR,0,3);}GEN(STO,LEV-TABLE[i].,TABLE[i].;}(1)运行测试(测试的PL0源码扩充单词的测试并贴运行结果截图)PL0源码:PROGRAMEX01;VARA,B,C,D;BEGINA:=16;A/=2;(2)WRITE(A);运行结果:(3)出现的问题及解决开始时在实现/=和*=操作时,*=的实现很顺利,而/=却一直没有得到理想的结果,通过与同学的讨论得知代码中除号指令的解析中,其实为除余操作,于是将%改为/,但是结果还是错误,经过调试发现是两个相除的数在栈中的位置相反了,正确的状态应该是除数位于次栈顶,而被除数位于栈顶。
编译原理课程设计报告
编译原理课程设计报告编译原理课程设计——简单编译器的设计与实现班级:组长:组员:指导教师:设计时间: 12月摘要....................................... 错误!未定义书签。
1.概述 ..................................... 错误!未定义书签。
2.课程设计任务及要求 ....................... 错误!未定义书签。
2.1 设计任务............................ 错误!未定义书签。
2.2 设计要求............................ 错误!未定义书签。
3.算法及数据结构 ........................... 错误!未定义书签。
3.1算法的总体思想(流程)............... 错误!未定义书签。
3.2词法分析模块......................... 错误!未定义书签。
3.2.1功能........................... 错误!未定义书签。
3.2.2数据结构 ....................... 错误!未定义书签。
3.2.3算法........................... 错误!未定义书签。
3.3语法分析(含语义分析和中间代码生成)模块错误!未定义书签。
3.3.1功能........................... 错误!未定义书签。
3.3.2数据结构 ....................... 错误!未定义书签。
3.3.3算法........................... 错误!未定义书签。
3.4中间代码优化模块..................... 错误!未定义书签。
3.4.1功能........................... 错误!未定义书签。
3.4.2数据结构 ....................... 错误!未定义书签。
编译原理课设实验报告
《编译技术》课程设计报告实验名称编译器设计姓名学号班级本课设的任务是完成一个完整的编译器,处理用户提交的符合所定文法的源程序代码,生成四元式中间代码,进而翻译成等价的X86平台上汇编语言的目标程序。
编译程序的工作过程划分为下列5个过程:词法分析,语法分析,语义分析和中间代码生成,代码优化,目标代码生成。
其中,词法分析阶段的基本任务是从以字符串表示的源程序中识别出具有独立意义的单词符号,并以二元组的形式输出,以作为语法分析阶段的输入。
语法分析阶段的基本任务是将词法分析阶段产生的二元组作为输入,根据语言的语法规则,识别出各种语法成分,并判断该单词符号序列是否是该语言的一个句子。
语义分析的任务是首先对每种语法单位进行静态的语义审查,然后分析其含义,并用另一种语言形式 (本课设采用四元式) 来描述这种语义。
代码优化的任务是对前阶段产生的中间代码进行等价变换或改造,以期获得更为高效即省时间和空间的目标代码。
目标代码生成的任务是将中间代码变换成特定机器上的绝对指令代码或可重定位的指令代码或汇编指令代码(本课设生成汇编指令代码)。
在词法分析阶段,通过DOS环境手动输入字符串序列(以’#’作为结束标志)作为带分析的源程序,调用词法扫描子程序将字符串以二元组的形式输出(若有不属于该语言单词符号出现,则进行出错处理),词法扫描子程序包括了对源程序的预处理(忽略多余空格、回车换行符等空白字符),以及对单词的识别和分类,以形成(单词种别,单词自身的值)形式的二元组,并将用户自定义变量信息存入程序变量信息表。
在语法分析阶段,采用自上而下的递归下降分析法,从文法的开始符号出发,根据文法规则正向推导出给定句子。
根据递归下降分析函数编写规则来编写相应的函数,在各个函数的分析过程中调用词法分析程序中的扫描程序,发出“取下一个单词符号”的命令,以取得下一个单词符号作语法分析。
在语义分析和中间代码生成阶段,采用语法制导翻译法,使用属性文法为工具来描述程序设计语言的语义。
广工编译原理课程设计报告
一、实验目的在分析理解一个教学型编译程序(如PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。
达到进一步了解程序编译过程的基本原理和基本实现方法的目的。
二、实验成要求1.课内实验对PL/0作以下修改扩充:(1)增加单词:保留字ELSE,FOR,TO,DOWNTO,RETURN运算符+=,-=,++,--(2)修改单词:不等号# 改为<>(3)增加条件语句的ELSE子句2. 课程设计基本内容(成绩范围:“中”、“及格”或“不及格”)(1)扩充赋值运算:+= 和-=(2)扩充语句(Pascal的FOR语句):①FOR <变量>:=<表达式> TO <表达式> DO <语句>②FOR <变量>:=<表达式> DOWNTO <表达式> DO <语句>其中,语句①的循环变量的步长为1,语句②的循环变量的步长为-1。
选做内容(成绩评定范围扩大到:“优”和“良”)(1)增加运算:++ 和--。
;(2)增加类型:①字符类型;②实数类型。
(3)扩充函数:①有返回值和返回语句;②有参数函数。
(4)增加一维数组类型(可增加指令)。
(5)其他典型语言设施。
三、实验环境(1)实现平台:WindowsXP,Visual studio 2005(2)教学型编译程序:PL/0 (C语言版)四、设计方案Error()出错处理,打印出错位置和错误编码GetCh()漏掉空格,读取一个字符GetSym()词法分析,读取一个单词GEN()目标代码生成过程,本过程用于把生成的目标代码写入目标代码数组,供后面的解释器解释执行TEST()测试当前单词是否合法过程testENTER()登陆符号表过程enterPOSITION() 在符号表中查找指定符号所在位置的函数position,如果找不到就返回0V ARDECLARATION()变量声明LISTCODE()列出目标代码清单;FACTOR()因子处理过程factorTERM()项处理过程term;EXPRESSION()表达式处理过程CONDITION()条件处理过程STATEMENT()语句处理过程BLOCK()语法分析过程BASE()通过静态链求出数据区基地址的函数,INTERPRET ()对目标代码解释运行过程PL/0语法调用关系图五、主要成分描述1.符号表在编译程序中符号表用来存放语言程序中出现的有关标识符的属性信息,符号表中所登记的信息在编译的不同阶段都要用到。
广东工业大学编译原理实验报告
实验报告课程名称____ 编译原理__________ 题目名称_ PL/0编译程序的修改扩充_ 学生学院______计算机学院__ 专业班级_______ ________ 学号学生姓名______ ________ 指导教师____ _________ __20年月日一、课内实验要求对PL/0作以下修改扩充:增加单词:保留字ELSE,FOR,TO,DOWNTO,RETURN运算符*=,/=,++,--,&,||,!修改单词:不等号# 改为<>增加条件语句的ELSE子句,要求:写出相关文法,语法图,语义规则。
二、实验环境与工具计算机及操作系统:PC机,Windows2000,WindowsXP程序设计语言:C教学型编译程序:PL/0设计方案概述:源、目标语言,实现工具(平台),运行平台源语言:PASCAL目标语言:假想栈式计算机的汇编语言,可称为类PCODE指令代码实现工具:Visual C++ 6.0运行平台:Windows 7三、设计方案1.结构设计说明(1)PL/0 语言编译器PL/0语言可看成是PASCAL语言的子集,它的编译程序是一个编译解释执行系统。
PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关。
(2)PL/0编译程序的语法分析过程BLOCK是整个编译过程的核心。
这里根据编译程序的总体流程图,来弄清BLOCK 过程在整个编译程序中的作用。
总流程图如下图所示:PL/0 的编译程序采用一趟扫描方式,以语法分析程序为核心,词法分析程序和代码生 成程序都作为一个独立的过程,当语法分析需要读单词时就用词法分析程序,而当语法分析 正确需生成相应的目标代码时,则调用代码生成程序。
此外,用表格管理程序建立变量,常 量和过程标识符的说明与引用之间的信息联系。
用出错处理程序对词法和语法分析遇到的错 误给出在源程序中出错的位置和错误性质。
PL/0语法调用关系图2、主要成分描述○1符号表为了组成一条指令,编译程序必须知道其操作码及其参数(数或地址)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计课程名称___编译原理__________题目名称___PL/0编译器的扩充__学生学院___计算机学院_________专业班级_计算机科学与技术13(9)学号学生姓名指导教师___林志毅________________2016年1月2日一、已完成的内容:(1)扩充赋值运算:*=和/=(2)扩充语句(Pascal的FOR语句)FOR<变量>:=<表达式>STEP<表达式>UNTIL<表达式>Do<语句> (3)增加类型:①字符类型;②实数类型。
VARIABLE*/GetSym();if(SYM==BECOMES||SYM==TIMESBECOMES||SYM==SLASHBECOMES||SYM==PLUSBECOMES||SYM==MINUSBECOMES){RELOP=SYM;if(SYM!=BECOMES){TABLE[i].;}GetSym();}elseError(13);EXPRESSION(FSYS,LEV,TX);if(RELOP==TIMESBECOMES){GEN(OPR,0,4);}elseif(RELOP==SLASHBECOMES){GEN(OPR,0,5);}elseif(RELOP==PLUSBECOMES){GEN(OPR,0,2);}elseif(RELOP==MINUSBECOMES){GEN(OPR,0,3);}GEN(STO,LEV-TABLE[i].,TABLE[i].;}(1)运行测试(测试的PL0源码扩充单词的测试并贴运行结果截图)PL0源码:PROGRAMEX01;VARA,B,C,D;BEGINA:=16;A/=2;(2)WRITE(A);运行结果:(3)出现的问题及解决开始时在实现/=和*=操作时,*=的实现很顺利,而/=却一直没有得到理想的结果,通过与同学的讨论得知代码中除号指令的解析中,其实为除余操作,于是将%改为/,但是结果还是错误,经过调试发现是两个相除的数在栈中的位置相反了,正确的状态应该是除数位于次栈顶,而被除数位于栈顶。
解决:在调用EXPRESSION函数解析/=右边表达式前,先将其左边变量的值放入栈中。
1.扩充语句(Pascal的FOR语句)FOR<变量>:=<表达式>STEP<表达式>UNTIL<表达式>Do<语句>(1)语法图(2)修改GetSym()方法(写出修改的代码)此处无修改,FOR、STEP、UNTIL及DO等关键字已放置关键字数组中,通过该数组便可识别。
(3)修改STATEMENT()方法(写出修改的代码)caseFORSYM:GetSym();(4)STATEMENT(SymSetUnion(SymSetNew(STEPSYM),FSYS),LEV,TX);=CX;=CX;运行结果:(5)出现的问题及解决实现FOR循环的前提是理解表达式处理函数及语句处理函数,关键是处理好跳转关系,例如第一次进入FOR循环时,生成FOR后面的表达式后应该有一个直接跳转跳过STEP语句进入UNTIL的条件判断;而调用CONDITION处理UNTIL后的条件语句后,便有一个条件跳转跳到STEP后的表达式代码位置。
由于有了之前IF...ELSE...的参考及大致理解相关函数,因此实现时没出现太大问题。
2.增加类型:①字符类型;②实数类型。
(1)在GetSym中增加字符型及实数型数据的识别elseif(CH=='\''){GetCh();NUM=CH;GetCh();if(CH=='\''){SYM=CHARACTER;GetCh();}elseError(8);}elseif(CH>='0'&&CH<='9'){/*NUMBER*/K=0;NUM=0;SYM=NUMBER;do{NUM=10*NUM+(CH-'0');K++;GetCh();}while(CH>='0'&&CH<='9');if(CH=='.'){IND==CHARTYPE||TABLE[i].KIND==VARIABLE||TABLE[i].KIND==F LOATTYPE){/*ASSIGNMENTTONON-VARIABLE*/if(SYM==BECOMES||SYM==TIMESBECOMES||SYM==SLASHBECOMES ||SYM==PLUSBECOMES||SYM==MINUSBECOMES){RELOP=SYM;if(SYM!=BECOMES){TABLE[i].;}GetSym();}elseError(13);EXPRESSION(FSYS,LEV,TX);if(RELOP==TIMESBECOMES){GEN(OPR,0,4);}elseif(RELOP==SLASHBECOMES){GEN(OPR,0,5);}elseif(RELOP==PLUSBECOMES){GEN(OPR,0,2);}elseif(RELOP==MINUSBECOMES){GEN(OPR,0,3);}GEN(STO,LEV-TABLE[i].,TABLE[i].;}else{Error(12);i=0;}break;caseWRITESYM: IND){caseCHARTYPE:GEN(OPR,0,17);break;caseFLOATTYPE:GEN(OPR,0,18);break;default:{GEN(OPR,0,14);}}}while(SYM==COMMA);if(SYM!=RPAREN)Error(SBNUM);elseGetSym();}GEN(OPR,0,15);break;/*WRITESYM*/(2)修改FACTOR中的方法(包含字符的识别处理)while(SymIn(SYM,FACBEGSYS)){if(SYM==IDENT){i=POSITION(ID,TX);if(i==0)Error(11);elseswitch(TABLE[i].KIND){caseCONSTANT:GEN(LIT,0,TABLE[i].VAL);break;caseVARIABLE:GEN(LOD,LEV-TABLE[i].,TABLE[i].;break;casePROCEDUR:Error(21);break;caseFLOATTYPE:GEN(LOD,LEV-TABLE[i].,TABLE[i].;break;caseCHARTYPE:GEN(LOD,LEV-TABLE[i].,TABLE[i].;break;}GetSym();}elseif(SYM==NUMBER){if(NUM>AMAX){Error(31);NUM=0;}GEN(LIT,0,NUM);GetSym();LEV;TABLE[TX].=DX;DX++;break;caseFLOATTYPE:TABLE[TX].=LEV;TABLE[TX].=DX;DX++;break;(3)在Interpret指令OPR中增加字符输出和实数输出case17:Form1->printcs(S[T]);fprintf(FOUT,"%c\n",S[T]);(4)T--;运行结果:(5)出现的问题及解决字符型的实现主要问题是在赋值、字符表达式的处理及输出三个方面。
赋值刚开始没有思路,之后借鉴VAR型的赋值,才清楚需要使用到栈这个媒介进入赋值:先把字符值放入栈中,在将栈顶值传给字符型变量。
而字符表达式的处理在Factor里进行识别处理。
关于输出则需要在WRITESYM的识别处理中进行类型判断采取不同输出方式,并需新建一条指令专门用于字符输出实数型的实现主要问题为:1、数据获取:小数点后的值的获取需要用到循环帮助实现;2、变量更改:在没有引入实数型前,用来模拟栈的数组类型为int型,而引入后,则需要将其更改为实数型,在程序中与栈值有关的那些变量类型也同样改为实数型。
(1)增加注释;多行注释由/*和*/包含,单行注释为运行结果(2)出现问题及解决刚开始就认为注释功能的实现比较容易,但是在实现过程还是出现不少问题。
我的思路是在getSym方法中使用循环滤去注释的内容,过程不断调用getCh读取下一个字符。
在循环处理注释结束后需要调用自身GetSym,因为上次调用的GetSym方法都用于处理注释了。
然而/**/这种情况却一直有报19号错误,经过查找发现该情况的循环执行完后,当前CH为符号’/’,而不是’/’后的字符,因此需要在调用GetSym前先调用getCh以便获取下一个新字符用于GetSym中的switch判断。
//不存在此情况,其循环结束CH为注释结束的下一字符。
二、心得经过了一周多的奋战,此次课程设计的实现过程让我收获颇多,同时也让我意识到自己在编码过程中的不足。
在没做课程设计之前,我对代码编译的实现过程和对PL0代码的体系结构都很陌生,而当一步一步从实现/=等、for循环、注释及增加类型等功能后,我对代码编译过程有了一个整体而深入的认识。
在实现的过程中,虽然出现很多问题,但是通过自己的思考和请教同学都能得到解决。
在实现的过程中,我发现自己在考虑功能的实现方面不够全面仔细,例如字符型的增加,我只考虑到了字母这一种字符型,而没有考虑其他符号也为字符型,因此先前字符的识别我是通过判别当前SYM是否为ident型且其字符串长度是否为1这两个条件进行识别出来的。
当完成过后才发现该方法存在缺陷,才在GetSym里面另起分支进行识别处理。
这也提醒我以后考虑问题应当尽量周全。
源码下载地址:。