广工编译原理实验报告(参考格式)
- 格式:pdf
- 大小:669.13 KB
- 文档页数:16
编译原理实验报告一、实验目的和要求本次实验旨在对PL_0语言进行功能扩充,添加新的语法特性,进一步提高编译器的功能和实用性。
具体要求如下:1.扩展PL_0语言的语法规则,添加新的语法特性;2.实现对新语法的词法分析和语法分析功能;3.对扩展语法规则进行语义分析,并生成中间代码;4.验证扩展功能的正确性。
二、实验内容1.扩展语法规则本次实验选择扩展PL_0语言的语句部分,添加新的控制语句,switch语句。
其语法规则如下:<switch_stmt> -> SWITCH <expression> CASE <case_list><default_stmt> ENDSWITCH<case_list> -> <case_stmt> , <case_stmt> <case_list><case_stmt> -> CASE <constant> : <statement><default_stmt> -> DEFAULT : <statement> ,ε2.词法分析和语法分析根据扩展的语法规则,需要对新的关键字和符号进行词法分析,识别出符号类型和记号类型。
然后进行语法分析,建立语法树。
3.语义分析在语义分析阶段,首先对switch语句的表达式进行求值,判断其类型是否为整型。
然后对case语句和default语句中的常量进行求值,判断是否与表达式的值相等。
最后将语句部分生成中间代码。
4.中间代码生成根据语法树和语义分析的结果,生成对应的中间代码。
例如,生成switch语句的跳转表,根据表达式的值选择相应的跳转目标。
5.验证功能的正确性设计一些测试用例,验证新语法的正确性和扩展功能的实用性。
三、实验步骤与结果1.扩展语法规则,更新PL_0语法分析器的词法规则和语法规则。
课程设计课程名称___编译原理__________题目名称___PL/0编译器的扩充 __ 学生学院___计算机学院_________专业班级_计算机科学与技术13(9)学号学生姓名指导教师___林志毅________________ 2016 年1 月2 日一、 已完成的内容:(1) 扩充赋值运算:*= 和 /=(2) 扩充语句(Pascal 的FOR 语句)FOR <变量>:=<表达式>STEP<表达式>UNTIL<表达式>Do<语句>(3) 增加类型:①字符类型;②实数类型。
(4) 增加注释; 多行注释由/*和*/包含,单行注释为//二、 实验环境与工具(1)计算机及操作系统:PC 机,Windows7(2)程序设计语言:C++(3)使用软件Borland C++ Builder 6.0(4)教学型编译程序:PL/0三、 具体实现:1. 扩充赋值运算:*= 和 /=(1) 语法树(2) 修改GetSym()方法(写出修改的代码)else if(CH=='*') {GetCh();if(CH=='=') { SYM=TIMESBECOMES; GetCh(); }else SYM=TIMES;} else if(CH=='/') {GetCh();if(CH=='=') { SYM=SLASHBECOMES; GetCh(); }(3) 修改STATEMENT ()方法(写出修改的代码)case IDENT:i=POSITION(ID,TX); if (i==0) Error(11);else if (TABLE[i].KIND==VARIABLE || TABLE[i].KIND==FLOATTYPE) { /*ASSIGNMENT TO NON-VARIABLE*/GetSym();if (SYM==BECOMES|| SYM==TIMESBECOMES || SYM==SLASHBECOMES||SYM==PLUSBECOMES||SYM==MINUSBECOMES) {RELOP=SYM;if(SYM!=BECOMES) { //若为除等于(或其他类似符号)则先把符号左边的变量值放入栈中GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);}GetSym();} else Error(13);EXPRESSION(FSYS,LEV,TX);if(RELOP==TIMESBECOMES) {GEN(OPR,0,4);} else if(RELOP==SLASHBECOMES) {GEN(OPR,0,5);} else if(RELOP==PLUSBECOMES) {GEN(OPR,0,2);} else if(RELOP==MINUSBECOMES) {GEN(OPR,0,3);}GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);}(4)运行测试(测试的PL0源码扩充单词的测试并贴运行结果截图)PL0源码:PROGRAM EX01;VAR A,B,C,D;BEGINA:=16;A/=2;WRITE(A); //结果为8B:=4;B*=2;WRITE(B); //结果为8C:=6;C+=2;WRITE(C); //结果为8D:=10;D-=2;WRITE(D); //结果为8END.(5)运行结果:(6)出现的问题及解决开始时在实现/=和*=操作时,*=的实现很顺利,而/=却一直没有得到理想的结果,通过与同学的讨论得知代码中除号指令的解析中,其实为除余操作,于是将%改为/,但是结果还是错误,经过调试发现是两个相除的数在栈中的位置相反了,正确的状态应该是除数位于次栈顶,而被除数位于栈顶。
编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
实验报告课程名称编译原理题目名称 PL/0编译器的扩充学生学院计算机学院专业班级计算机科学与技术12(4)学号 3112005901学生姓名柏石先指导教师李杨程序功能完成情况测试用例全面程度学生对所编程序熟悉程度报告格式是否与要求相符报告内容是否准确、全面2014 年 12 月 20日一、实验目的与要求对PL/0作以下修改扩充:(1)增加单词:保留字 ELSE,FOR,STEP,UNTIL,DO,RETURN运算符 *=,/=,&,||,!(2)修改单词:不等号# 改为 <>(3)增加条件语句的ELSE子句,要求:写出相关文法,语法描述图,语义描述图。
二、实验环境与工具1、源语言:PL/0语言,PL/0语言是PASCAL语言的子集,它的编译程序是一个编译解析执行系统,后缀名为.PL0;2、目标语言:生成文件后缀为*.COD的目标代码3、实现平台:Borland C++Builder 64、运行平台:Windows 8.1三、结构流程1、结构设计说明(1)PL/0 语言编译器PL/0语言可看成是PASCAL语言的子集,它的编译程序是一个编译解释执行系统。
PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关。
2、词法分析程序的设计四、开发过程(一)增加单词:保留字 ELSE,FOR,STEP,UNTIL,DO , RETURN运算符 *=,/=,&,||,!新增6个保留字和5个运算符,合计11个单词。
其中保留字ELSE,FOR,STEP,UNTIL,DO, RETURN分别对应ELSESYM,FORSYM, STEPSYM, UNTILSYM,DOSYM,RETURNSYM;运算符 *= ,/= ,& ,|| ,!分别对应TIMESBECOMES, SLASHBECOMES, ANDSYM, ORSYM, NOTSYM。
注:要求只做词法分析部分,不做语义分析处理,实验的结果只是识别新增的保留字和运算1.首先考虑需要增加保留字的个数,以及如何命名,再将新增的保留字添加对应的保留字的集合中。
课程设计课程名称编译原理题目名称PL/0编译器的扩充学生学院计算机学院专业班级计算机科学与技术12(4) 学号学生姓名柏石先指导教师李杨2014 年12 月28日一、实验目的与要求基本内容(成绩范围:“中”、“及格”或“不及格”)(1)扩充赋值运算:*= 和 /=(2)扩充语句(Pascal的FOR语句):FOR <变量>:=<表达式>STEP<表达式> UNTIL<表达式>Do<语句>选做内容(成绩评定范围扩大到:“优”和“良”)(1)增加类型:①字符类型;②实数类型。
(2)增加注释; 注释由/*和*/包含;(3)扩充函数:①有返回值和返回语句;②有参数函数。
(4)增加一维数组类型(可增加指令)。
(5)其他典型语言设施。
二、实验环境与工具1、源语言:PL/0语言,PL/0语言是PASCAL语言的子集,它的编译程序是一个编译解析执行系统,后缀名为.PL0;2、目标语言:生成文件后缀为*.COD的目标代码3、实现平台:Borland C++Builder 64、运行平台:Windows 8.1三、设计概述1、结构设计说明(1)PL/0编译系统的结构框架源语言:源语言是基于C语言写的PL/0编译程序——PL0语言(可以看成Pascal 语言的子集)目标语言:假想的栈式计算机计算语言,即类PCODE指令代码。
指令格式如下:其中f代表功能码,l表示层次差,a的含意对不同的指令有所区别。
具体的指令功能表:(一)扩充赋值运算:*= 和/=*= 和/=的语法描述图:(二)扩充语句(Pascal的FOR语句)因为在Pascal中的FOR语句描述为:FOR <变量>:=<表达式> STEP <表达式> UNTIL <表达式> DO <语句> 所以增加FOR,STEP,UNTIL,DOFOR语句语法描述图为:1)增加所需要的保留字和运算符,实现*=和/=,以及FOR语句,应该增加TIMESBECOMES,SLASHBECOMES,FOR,STEP,UNTIL,DO。
编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
一、实习背景与目的随着计算机技术的飞速发展,编译原理作为计算机科学的重要基础理论之一,其研究与应用越来越受到重视。
为了更好地理解和掌握编译原理的基本原理和方法,提高自己的编程能力和设计能力,我参加了编译原理的实习课程。
本次实习旨在通过设计和实现一个简单的编译程序,加深对编译原理的理解,掌握编译程序的设计与实现方法,提高自己的编程能力,并培养自己的计算思维。
二、实习内容本次实习主要分为以下几个部分:1. 词法分析:识别源程序中的单词,将其转换为对应的词法单元。
2. 语法分析:根据文法规则,分析源程序的语法结构,生成抽象语法树(AST)。
3. 语义分析:检查AST的语义正确性,进行类型检查等。
4. 中间代码生成:将AST转换为中间代码。
5. 代码优化:对中间代码进行优化,提高程序性能。
6. 目标代码生成:将优化后的中间代码转换为特定平台的目标代码。
三、实习过程1. 词法分析:- 首先,分析源程序的文法规则,确定需要识别的单词种类和对应的正则表达式。
- 然后,设计状态转换图,实现词法分析器。
- 最后,编写测试用例,验证词法分析器的正确性。
2. 语法分析:- 分析文法规则,确定语法结构,设计抽象语法树(AST)。
- 选择合适的语法分析方法,如递归下降分析、LL分析、LR分析等。
- 实现语法分析器,将词法分析器生成的词法单元转换为AST。
3. 语义分析:- 根据AST,检查语义正确性,如类型检查、作用域分析等。
- 实现语义分析器,处理语义错误,并给出错误信息。
4. 中间代码生成:- 根据AST,生成中间代码,如三地址代码、四元式等。
- 实现中间代码生成器,将AST转换为中间代码。
5. 代码优化:- 分析中间代码,找出可优化的部分。
- 实现代码优化器,优化中间代码,提高程序性能。
6. 目标代码生成:- 根据目标平台的指令集,生成目标代码。
- 实现目标代码生成器,将优化后的中间代码转换为目标代码。
四、实习成果通过本次实习,我成功地设计和实现了一个简单的编译程序,实现了词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等功能。
<<编译原理>>课内实验报告项目名称 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()里增加对<>的识别(在<或<=基础上修改)。
课程设计课程名称编译原理题目名称PL/0编译器的扩充学生学院计算机学院专业班级计算机科学与技术12(4)学号3112005901学生姓名柏石先指导教师李杨程序功能完成情况测试用例全面程度学生对所编程序熟悉程度报告格式是否与要求相符报告内容是否准确、全面2014 年12 月28日一、实验目的与要求基本内容(成绩范围:“中”、“及格”或“不及格”)(1)扩充赋值运算:*= 和 /=(2)扩充语句(Pascal的FOR语句):FOR <变量>:=<表达式>STEP<表达式> UNTIL<表达式>Do<语句>选做内容(成绩评定范围扩大到:“优”和“良”)(1)增加类型:①字符类型;②实数类型。
(2)增加注释; 注释由/*和*/包含;(3)扩充函数:①有返回值和返回语句;②有参数函数。
(4)增加一维数组类型(可增加指令)。
(5)其他典型语言设施。
二、实验环境与工具1、源语言:PL/0语言,PL/0语言是PASCAL语言的子集,它的编译程序是一个编译解析执行系统,后缀名为.PL0;2、目标语言:生成文件后缀为*.COD的目标代码3、实现平台:Borland C++Builder 64、运行平台:Windows 8.1三、设计概述1、结构设计说明(1)PL/0编译系统的结构框架源语言:源语言是基于C语言写的PL/0编译程序——PL0语言(可以看成Pascal 语言的子集)目标语言:假想的栈式计算机计算语言,即类PCODE指令代码。
指令格式如下:其中f代表功能码,l表示层次差,a的含意对不同的指令有所区别。
具体的指令功能表:(一)扩充赋值运算:*= 和/=需要增加2个运算符*= 和/=,用下面表格定义的SYM代替运算符*= /=SYM表示TIMESBECOMES SLASHBECOMES *= 和/=的语法描述图:(二)扩充语句(Pascal的FOR语句)因为在Pascal中的FOR语句描述为:FOR <变量>:=<表达式> STEP <表达式> UNTIL <表达式> DO <语句>所以增加FOR,STEP,UNTIL,DOFOR语句语法描述图为:1)增加所需要的保留字和运算符,实现*=和/=,以及FOR语句,应该增加TIMESBECOMES,SLASHBECOMES,FOR,STEP,UNTIL,DO。
计算机硬件实验室实验报告根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对预测分析LL(1)分析法的理解。
二、实验要求:对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i输出的格式如下:(1)LL(1)分析程序,编制人:姓名,学号,班级(2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串(3)输出过程如下:步骤分析栈剩余输入串所用产生式1 E i+i*i# E->TG(4)输入符号串为非法符号串(或者为合法符号串)备注:(1)在“所用产生式”一列中如果对应有推导则写出所用产生式;如果为匹配终结符则写明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。
(2) 在此位置输入符号串为用户自行输入的符号串。
(3)上述描述的输出过程只是其中一部分的。
注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);三、实验过程:1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。
2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。
3.程序编写(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
四、实验结果:(1)写出程序流程图(2)给出运行结果示例程序:注意:本示例只要修改分析的句子即可,不要改写文法/*LL(1)分析法源程序,只能在VC++中运行*/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','-','*','/','(',')','#'};/*终结符*/char v2[20]={'E','G','T','S','F'};/*非终结符*/int j=0,b=0,top=0,l;/*L为输入串长度*/typedef struct type/*产生式类型定义*/{char origin;/*大写字符*/char array[5];/*产生式右边字符*/int length;/*字符个数*/}type;type e,t,g,g1,g2,s,s2,s1,f,f1;/*结构体变量*/type C[10][10];/*预测分析表*/void print()/*输出分析栈*/{int a;/*指针*/for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';strcpy(g1.array,"-TG");g1.length=3;g2.origin='G';g2.array[0]='^';g2.length=1;/////////////////////////////////////////////s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';strcpy(s1.array,"/FS");s1.length=3;s2.origin='S';s2.array[0]='^';s2.length=1;////////////////////////////////f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*//*填充分析表*///char v1[20]={'i','+','-','*','/','(',')','#'};/*终结符*///char v2[20]={'E','G','T','S','F'};/*非终结符*/C[0][0]=e;C[0][5]=e;C[1][1]=g;C[1][2]=g1;C[1][3]=C[1][4]=C[1][7]=g2;C[2][0]=t;C[2][3]=t;C[2][5]=t;C[3][1]=C[3][2]=s2;C[3][3]=s;C[3][4]=s1;C[3][6]=C[3][7]=s2;C[4][0]=f1; C[4][5]=f;printf("LL(1)分析程序,编制人:武普泉,20号,1020562班\n");printf("输入一以#结束的符号串(包括+ - * / () i #):");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+') &&(ch!='-')&&(ch!='*')&&(ch!='/')&&(ch!='(')&&(ch!=')')&&(ch!='#')) {printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈\t\t剩余字符\t\t所用产生式\n");do{x=A[top--];/*x为当前栈顶字符*/printf("%d",k++);printf("\t\t");for(j=0;j<=7;j++)/*判断是否为终结符*/if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/printf("acc!\n");/*接受*/getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(1);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*行号*/break;}for(j=0;j<=7;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c->",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j>=0;j--)/*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(1);}/*else*/}/*else*/}while(finish==0);}/*main*。
实验2 词法分析程序的设计一、实验目的掌握计算机语言的词法分析程序的开发方法。
二、实验内容编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。
三、实验要求1、根据以下的正规式,编制正规文法,画出状态图;标识符<字母>(<字母>|<数字字符>)*十进制整数0 | ((1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*)八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*运算符和界符+ - * / > < = ( ) ;关键字if then else while do2、根据状态图,设计词法分析函数int scan( ),完成以下功能:1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词,2)以二元式形式输出单词<单词种类,单词属性>其中单词种类用整数表示:0:标识符1:十进制整数2:八进制整数3:十六进制整数运算符和界符,关键字采用一字一符,不编码其中单词属性表示如下:标识符,整数由于采用一类一符,属性用单词表示运算符和界符,关键字采用一字一符,属性为空3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。
四、实验环境PC微机DOS操作系统或Windows 操作系统Turbo C 程序集成环境或Visual C++ 程序集成环境五、实验步骤1、根据正规式,画出状态转换图;2、根据状态图,设计词法分析算法;观察状态图,其中状态2、4、7、10(右上角打了星号)需要回调一个字符。
声明一些变量和函数:ch: 字符变量,存放最新读进的源程序字符。
strToken: 字符串变量,存放构成单词符号的字符串。
实验名称:编译原理实验实验时间:2023年X月X日实验地点:实验室实验指导老师:XXX一、实验目的1. 理解编译原理的基本概念和流程。
2. 掌握词法分析和语法分析的基本方法。
3. 学习编译器生成中间代码和目标代码的过程。
4. 培养编程能力和问题解决能力。
二、实验内容本次实验主要包括以下内容:1. 词法分析:编写一个简单的词法分析器,将源代码输入转换为抽象语法树(AST)。
2. 语法分析:实现一个简单的递归下降解析器,对词法分析器输出的AST进行语法分析。
3. 中间代码生成:根据AST生成三地址代码(Three-Address Code)。
4. 代码优化:对生成的三地址代码进行优化。
5. 目标代码生成:将优化后的三地址代码转换为机器代码。
三、实验步骤1. 设计词法分析器首先,我们需要设计一个能够识别源代码中各种单词的词法分析器。
在本实验中,我们定义了以下几种单词:- 关键字:如if、else、while、int、float等。
- 标识符:由字母、数字和下划线组成,不能以数字开头。
- 常量:包括整型常量和浮点型常量。
- 运算符:如+、-、、/、==、<=等。
- 分隔符:如(、)、;、,等。
根据以上定义,我们可以编写一个词法分析器,它将输入的源代码字符串逐个字符地读取,并根据定义的规则识别出相应的单词。
2. 语法分析词法分析器生成的AST是一个树形结构,其中每个节点代表源代码中的一个单词或符号。
为了进一步分析AST的结构,我们需要实现一个递归下降解析器,它能够根据语法规则对AST进行解析。
在本实验中,我们以一个简单的算术表达式为例,实现了一个递归下降解析器。
解析器从AST的根节点开始,按照语法规则递归地解析每个子节点,直到整个表达式被解析完毕。
3. 中间代码生成在完成语法分析后,我们需要将AST转换为中间代码。
在本实验中,我们选择了三地址代码作为中间代码的形式。
三地址代码是一种表示赋值、条件判断和循环等操作的方式,它使用三个操作数和两个操作符来表示一个操作。
《编译原理》课程实验报告《编译原理》课程实验报告《编译原理》课程实验报告题目:词法分析器实验专业:计算机科学与技术班级:1班学号:* * * ***** 姓名:* * * 一、实验目的通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。
二、实验内容及要求用VC++/VB/JAVA语言实现对C语言子集的源程序进行词法分析。
通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。
以下是实现词法分析设计的主要工作:(1)从源程序文件中读入字符。
(2)统计行数和列数用于错误单词的定位。
(3)删除空格类字符,包括回车、制表符空格。
(4)按拼写单词,并用(内码,属性)二元式表示。
(属性值——token的机内表示) (5)如果发现错误则报告出错(6)根据需要是否填写标识符表供以后各阶段使用。
单词的基本分类:u 关键字:由程序语言定义的具有固定意义的标识符。
也称为保留字例如if、for、while、printf ;单词种别码为1。
u 标识符:用以表示各种名字,如变量名、数组名、函数名;u 常数:任何数值常数。
如125, 1,0.5,3.1416;u 运算符:+、-、*、/;u 关系运算符:、=、= 、、=、;u 分界符:;、,、(、)、[、];三、实验程序设计说明1.实验方案设计1、主程序设计考虑:u 程序的说明部分为各种表格和变量安排空间。
在具体实现时,将各类单词设计成结构和长度均相同的形式,较短的关键字后面补空。
k数组------关键字表,每个数组元素存放一个关键字(事先构造好关键字表)。
s 数组------存放分界符表(可事先构造好分界符表)。
为了简单起见,分界符、算术运算符和关系运算符都放在s表中(编程时,应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。
实验报告课程名称____ 编译原理__________ 题目名称_ 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,识别出并输出简单语言的基本字。
标示符。
无符号整数.运算符.和界符。
三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号.2、程序流程图(1)主程序(2)扫描子程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符.字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。
2 实验词法分析器源程序:#include 〈stdio.h〉#include <math.h>#include <string。
h>int i,j,k;char c,s,a[20],token[20]={’0’};int letter(char s){if((s〉=97)&&(s〈=122)) return(1);else return(0);}int digit(char s){if((s〉=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else”)==0) return(3);else if(strcmp(token,"switch”)==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf(”please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':case ’p':case ’q’:case 'r’:case 's’:case 't’:case ’u’:case ’v’:case ’w’:case ’x':case ’y':case ’z’:while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。