编译实验报告
编译原理预测分析法实验报告
编译原理实验预测分析法姓名**学号**班级**完成日期**1.实验目的加深对语法分析器工作过程的理解;加强对预测分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
2.实验要求1.对语法规则有明确的定义;2.编写的分析程序能够对实验一的结果进行正确的语法分析;3. 3.对于遇到的语法错误, 能够做出简单的错误处理, 给出简单的错误提示, 保证顺利完成语法分析过程;4. 4.实验报告要求用文法的形式对语法定义做出详细说明, 说明语法分析程序的工作过程, 说明错误处理的实现。
5.实验原理对文法G进行语法分析, 文法G如下所示:*0. S→a */*1. S→.*2. S→(T)*3. T→SW **4..W→,S.*5. W→ε;6.软件设计与编程#include <stdio.h>#include <stdlib.h>#include <string.h>char str[100]; //存储待分析的句子const char T[ ] = "a^(),#"; //终结符, 分析表的列符const char NT[ ] = "STW"; //非终结符, 分析表的行符/*指向产生式右部符号串*/const char *p[] = {/*0. S→a */ "a",/*1.. S→. *. "^",/*2. S→(T) */ "(T)",/*3. T→SW */ "SW",/*4.. W→,S. */ ",SW",/*5. W→ε; */ ""};//设M[i][j]=x, 通过p[M[i][j]]=p[x]获取右部符号串。
const int M[][6] = {/* a ^ ( ) , # *//*S*/ { 0, 1, 2, -1, -1, -1 },/*T*/ { 3, 3, 3, -1, -1, -1 },/*W*/ { -1, -1,-1, 5, 4, -1 }};void init()//输入待分析的句子{printf("请输入待分析的句子(以$结束): \n");scanf("%s",str);}int lin(char c);//非终结符转换为行号int col(char c);//终结转换为列号bool isNT(char c);//isNT判断是否是非终结符bool isT(char c);//isT判断是否是终结符。
编译原理实验报告
编译原理实验报告一、实验概述本次实验旨在设计并实现一个简单的词法分析器,即实现编译器的第一个阶段,词法分析。
词法分析器将一段源程序代码作为输入,将其划分为一个个的词法单元,并将其作为输出。
二、实验过程1.设计词法规则根据编程语言的规范和所需实现的功能,设计词法规则,以明确规定如何将源程序代码分解为一系列的词法单元。
2.实现词法分析器采用合适的编程语言,根据所设计的词法规则,实现词法分析器。
词法分析器的主要任务是读入源程序代码,并将其根据词法规则进行分解,生成对应的词法单元。
3.测试词法分析器设计测试用例,用于检验词法分析器的正确性和性能。
测试用例应包含各种情况下的源程序代码。
4.分析和修正错误根据测试过程中发现的问题,分析产生错误的原因,并进行修正。
重复测试和修正的过程,直到词法分析器能够正确处理所有测试用例。
三、实验结果我们设计了一个简单的词法分析器,并进行了测试。
测试用例涵盖了各种情况下的源程序代码,包括正确的代码和错误的代码。
经过测试,词法分析器能够正确处理所有的测试用例。
词法分析器将源程序代码分解为一系列的词法单元,每个词法单元包含了单词的种类和对应的值。
通过对词法单元的分析,可以进一步进行语法分析和语义分析,从而完成编译过程。
四、实验总结通过本次实验,我深入了解了编译原理的词法分析阶段。
词法分析是编译器的第一个重要阶段,它将源程序代码分解为一个个的词法单元,为后续的语法分析和语义分析提供基础。
在实现词法分析器的过程中,我学会了如何根据词法规则设计词法分析器的算法,并使用编程语言实现词法分析器。
通过测试和修正,我掌握了调试和错误修复的技巧。
本次实验的经验对我今后的编程工作有很大帮助。
编译原理是计算机科学与技术专业的核心课程之一,通过实践能够更好地理解和掌握其中的概念和技术。
我相信通过进一步的学习和实践,我能够在编译原理领域取得更大的成果。
编译原理实验报告
编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
编译实习报告
编译实习报告篇一:篇一:编译原理实习报告实习报告【实习目的】1.了解编译器的工作原理2.掌握并加深本学期所学的编译原理的理论知识3.加强自己的动手能力【实习内容】1.编译并运行老师所给的编译器参考代码2.在第一步的基础上进一步改进编译器,增加输入输出功能【开发平台】window系统,free pascal编译器【实习过程】本次实习过程根据实习内容共分两大部分,第一部分,编译运行参考代码;第二部分,进一步改进编译器。
本人在上面的基础上又增加了第三部分的额外修改。
下面便总结这三部分的实习过程:一、增加读写语句前pl0编译程序由于最原始的pl0编译程序所用的pascal版本较老,有些和当前使用版本不兼容。
必须作相应修改,具体是:“object”和“procedure”为pascal的保留字,现分别改成“obj”和“proc”。
此外,原始程序中的“≠”、“≤”和“≥”,不能用ascii 码表示出来,现将其替换成“”、“=”。
作为一个编译程序,支持批量处理和永久保存是其应具备的基本功能。
为此,本程序加入了文件读写功能,即从文件读入pl0源程序,在将中间代码和运行结果写入文件。
由于源程序和原始差别很小,为节省篇幅,不将其打印出来。
二、增加读写语句前pl0调试程序下面是增加读写语句前的pl0程序,包含了乘、除法和寻找两个自然数的最大公因数的过程和主过程,很好的说明了增加读写语句前的pl0语言的使用方法。
constvarx,y,z,q,r; procedure multiply; var a,b; a:=x; begin m=7,n=85;procedure divide; var end; b:=y; z:=0; while b>0 do begin end if odd b then z:=z+a; a:=2*a; b:=b/2;w;beginr:=x;q:=0;w:=y;while wy dobegin q:=2*q; w:=w/2;if wg dobeginif f0 do 13begin13 if odd b then z:=z+a; 20 a:=2*a;24 b:=b/2; 28end28 end;2 int 0 53 lod 1 34 sto 0 35 lod 1 46 sto 0 47 lit 0 08 sto 1 59 lod 0 410 lit 0 011 opr 01212 jpc 02913 lod 0 414 opr 0 615 jpc 02016 lod 1 517 lod 0 318 opr 0 219 sto 1 520 lit 0 221 lod 0 322 opr 0 423 sto 0 324 lod 0 425 lit 0 226 opr 0 527 sto 0 428 jmp 0 929 opr 0 03030 procedure divide;30 var31w;31 begin32r:=x;34q:=0;36w:=y;38while wy do51begin q:=2*q; w:=w/2;59 if w篇二:编译原理实习报告实习报告【实习目的】1.了解编译器的工作原理2.掌握并加深本学期所学的编译原理的理论知识3.加强自己的动手能力【实习内容】1.编译并运行老师所给的编译器参考代码2.在第一步的基础上进一步改进编译器,增加输入输出功能【开发平台】Window系统,Free Pascal编译器【实习过程】本次实习过程根据实习内容共分两大部分,第一部分,编译运行参考代码;第二部分。
编译方法实验报告(中间代码生成器)
编译方法实验报告2011年10月一、实验目的熟悉算术表达式的语法分析与中间代码生成原理。
二、实验内容(1)设计语法制导翻译生成表达式的四元式的算法;(2)编写代码并上机调试运行通过。
输入——算术表达式;输出——语法分析结果;相应的四元式序列。
(3)设计LL(1)分析法或LR(0)分析法的属性翻译文法, 并根据这些属性翻译文法, 使用扩展的语法分析器实现语法制导翻译。
三、实验原理及基本步骤●算术表达式文法:G(E): E ( E ω0 T | TT →T ω1 F | FF → i | (E)●文法变换:G’(E) E →T {ω0 T}T →F {ω1 F}F → i | (E)●属性翻译文法:E →T {ω0“push(SYN, w)” T “QUAT”}T →F {ω1“push(SYN, w)” F “QUAT”}F →i “push(SEM, entry(w))” | (E)其中:push(SYN, w) —当前单词w入算符栈SYN;push(SEM, entry(w)) —当前w在符号表中的入口值压入语义栈SEM;QUAT —生成四元式函数i. T = newtemp;ii. QT[j] =( SYN[k], SEM[s-1], SEM[s], T);j++;iii. pop( SYN, _ ); pop( SEM, _ ); pop( SEM, _ );push( SEM, T );●递归下降子程序:数据结构: SYN —算符栈;SEM —语义栈;四、数据结构设计使用递归的结构进行四元式的设计, 同时, 运用堆栈结构将四元式的输出序列打印出来while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)T();quat();}while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)F();quat();}void quat(){strcpy(qt[j],"(, , , )"); //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp; //push(SEM,temp);temp++;}五、关键代码分析(带注释)及运行结果#include <iostream>#include "string.h"#include "stdio.h"using namespace std;char syn[10]; //文法符号栈int i_syn;char sem[10]; //运算对象栈int i_sem;char exp[50]; //算术表达式区int i;char qt[30][15]; //四元式区int j=0;char temp='q'; //临时变量, 取值为r--zint E();int T();int F();void quat(); //生成四元式函数int main(int argc, char* argv[]){printf("please input your expression:");scanf("%s",exp); //输入四元式i=0; //read(w)E();if (exp[i]=='\0')for (i=0;i<j;i++) //输出四元式序列printf("%s\n",qt[i]);elseprintf("err");return 0;}int E(){T();while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)T();quat();}return 1;}int T(){F();while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)F();quat();}return 1;}int F(){if ( exp[i]=='('){i++; //read(w)E();if ( exp[i]!=')'){printf("err");return 0;}}else if ((exp[i]>='a' && exp[i]<='p')||(exp[i]>='0' && exp[i]<='9')){ sem[++i_sem]=exp[i]; } //push(SEM,w) else{printf("err");return 0;}i++; //read(w)return 1;}void quat(){strcpy(qt[j],"( , , , )"); //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp; //push(SEM,temp);temp++;}六、总结与分析我们知道, 定义一种语言除了要求定义语法外, 还要求定义语义, 即对语言的各种语法单位赋予具体的意义。
论文编译实习报告
一、实习背景随着我国国际地位的不断提高,对外交流日益频繁,翻译人才的需求也在不断增加。
为了提高自己的翻译水平,拓宽视野,我选择了在一家翻译公司进行论文编译实习。
此次实习让我深刻体会到论文编译工作的艰辛与乐趣,以下是我对实习期间的学习和收获的总结。
二、实习单位简介实习单位是一家专注于为客户提供专业翻译服务的翻译公司,拥有丰富的行业经验和专业的翻译团队。
公司主要业务包括论文翻译、技术文档翻译、商务文件翻译等。
此次实习,我有幸参与到论文编译工作中,为我国学术界贡献自己的力量。
三、实习内容1. 熟悉论文编译流程在实习期间,我首先学习了论文编译的流程。
一般来说,论文编译包括以下几个步骤:审阅原文、翻译、校对、润色、排版、校对。
通过了解这些步骤,我明白了论文编译工作的重要性,以及各个环节的紧密联系。
2. 翻译实践在实习过程中,我主要负责翻译英文论文。
首先,我仔细阅读原文,了解论文的主题、结构、观点等。
然后,根据翻译要求,将英文论文翻译成中文。
在翻译过程中,我注重保持原文的风格和语气,力求使译文准确、流畅。
3. 校对与润色在完成翻译后,我对照原文对译文进行校对,确保翻译的准确性。
此外,我还对译文进行了润色,使文章更加通顺、易读。
4. 排版与校对在完成翻译和润色后,我将译文进行排版,包括字体、字号、行距等。
最后,再次对照原文对排版后的译文进行校对,确保排版无误。
四、实习收获1. 提高了翻译水平通过实习,我对论文编译工作有了更深入的了解,翻译水平得到了很大提高。
在翻译过程中,我学会了如何处理专业术语、长难句等,使译文更加准确、流畅。
2. 增强了团队合作能力在实习过程中,我与团队成员密切配合,共同完成翻译任务。
这使我认识到团队合作的重要性,学会了如何与他人沟通、协作。
3. 拓宽了国际视野实习期间,我翻译了大量英文论文,了解了不同领域的学术研究动态。
这使我拓宽了国际视野,为今后从事相关工作打下了基础。
4. 培养了严谨的工作态度论文编译工作要求严谨、细致,我深刻体会到这一点。
编译器_实验报告
一、实验目的1. 理解编译器的基本原理和设计方法。
2. 掌握编译器各个阶段的功能和实现方法。
3. 通过实际编程,加深对编译器原理的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C/C++3. 开发工具:Visual Studio 2019三、实验内容本次实验主要完成一个简单的编译器,该编译器包含词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等阶段。
四、实验步骤1. 词法分析:- 定义单词类型,如标识符、关键字、运算符、常数等。
- 实现词法分析器,读取源代码,将其分解为一个个单词。
2. 语法分析:- 定义语法规则,构建语法分析器。
- 实现语法分析器,对单词序列进行语法分析,生成抽象语法树(AST)。
3. 语义分析:- 遍历AST,进行语义检查,如类型检查、作用域检查等。
- 生成中间代码,如三地址代码。
4. 代码优化:- 对中间代码进行优化,提高代码执行效率。
- 优化策略包括:常数折叠、循环优化、死代码消除等。
5. 目标代码生成:- 将优化后的中间代码转换为机器代码。
- 生成目标程序,如汇编代码。
五、实验结果1. 词法分析:- 成功识别出标识符、关键字、运算符、常数等单词类型。
- 输出单词序列,供语法分析器使用。
2. 语法分析:- 成功生成抽象语法树(AST)。
- AST结构清晰,便于后续处理。
3. 语义分析:- 成功进行语义检查,如类型检查、作用域检查等。
- 生成中间代码,供代码优化和目标代码生成使用。
4. 代码优化:- 对中间代码进行优化,提高代码执行效率。
- 优化效果明显,如减少了循环的次数、消除了死代码等。
5. 目标代码生成:- 成功生成汇编代码。
- 汇编代码结构清晰,便于后续翻译成机器代码。
六、实验总结1. 通过本次实验,我们深入了解了编译器的基本原理和设计方法。
2. 实验过程中,我们掌握了编译器各个阶段的功能和实现方法。
3. 实验成果表明,所编写的编译器能够对源代码进行词法分析、语法分析、语义分析、代码优化和目标代码生成等处理。
编译实习报告
编译实习报告一、实习背景随着计算机技术的不断发展,编译技术在软件开发和计算机科学领域中起着至关重要的作用。
为了更好地了解编译原理在实际应用中的具体实现,提高自己的实际动手能力,我参加了为期三个月的编译实习项目。
在实习期间,我深入学习了编译原理的基本知识,并参与了编译器的开发与优化过程。
二、实习内容1. 编译原理学习在实习的第一阶段,我系统地学习了编译原理的基本知识,包括文法、语法分析、中间代码生成、代码优化和目标代码生成等。
通过学习,我掌握了编译器的基本组成部分及其工作原理,为后续的实践操作打下了坚实的基础。
2. 编译器开发在实习的第二阶段,我参与了编译器的开发过程。
首先,我使用C语言编写了一个简单的编译器前端,实现了源代码的词法分析和语法分析。
在此基础上,我进一步实现了中间代码的生成和代码优化模块。
最后,我完成了目标代码的生成和运行。
整个过程中,我深刻体会到了编译原理在实际应用中的重要性。
3. 编译器优化在实习的第三阶段,我主要负责编译器的优化工作。
通过对中间代码的分析和调整,我实现了常数折叠、死代码消除和循环优化等优化策略。
经过优化,编译器生成的目标代码在运行效率和内存占用方面都有了显著的提升。
三、实习收获1. 知识运用通过实习,我将所学的编译原理知识运用到了实际项目中,提高了自己的实际动手能力。
同时,实习过程中遇到的问题也促使我不断深入学习相关知识,提高了自己的理论水平。
2. 团队协作在实习过程中,我与团队成员密切配合,共同解决问题。
这使我更加明白了团队协作的重要性,也锻炼了我的沟通与协作能力。
3. 工程实践实习过程中,我独立完成了编译器的开发与优化任务,掌握了工程实践的基本方法。
这对我今后从事软件开发工作具有很大的帮助。
四、实习总结通过这次编译实习,我对编译原理有了更深入的了解,并在实际项目中积累了宝贵的经验。
同时,实习过程中的挑战和困难也让我明白了自身存在的不足,为我今后的学习和工作指明了方向。
编译链接执行实验报告(3篇)
第1篇一、实验目的1. 理解编译、链接和执行的基本概念和过程。
2. 掌握使用编译器、链接器和执行器完成程序编译、链接和执行的基本操作。
3. 学习调试程序,解决编译、链接和执行过程中出现的问题。
二、实验环境1. 操作系统:Windows 102. 编译器:Microsoft Visual Studio 20193. 链接器:Microsoft Visual Studio 20194. 执行器:Windows 10自带三、实验内容1. 编译程序2. 链接程序3. 执行程序4. 调试程序四、实验步骤1. 编译程序(1)创建一个名为“HelloWorld.c”的源文件,内容如下:```cinclude <stdio.h>int main() {printf("Hello, World!\n");return 0;}```(2)打开Microsoft Visual Studio 2019,创建一个控制台应用程序项目。
(3)将“HelloWorld.c”文件添加到项目中。
(4)在项目属性中设置编译器选项,选择C/C++ -> General -> Additional Include Directories,添加源文件所在的目录。
(5)点击“生成”按钮,编译程序。
2. 链接程序(1)在Microsoft Visual Studio 2019中,点击“生成”按钮,生成可执行文件。
(2)查看生成的可执行文件,路径通常在项目目录下的“Debug”或“Release”文件夹中。
3. 执行程序(1)双击生成的可执行文件,或在命令行中运行。
(2)查看输出结果,应为“Hello, World!”。
4. 调试程序(1)在Microsoft Visual Studio 2019中,点击“调试”按钮。
(2)程序进入调试模式,可以设置断点、观察变量等。
(3)运行程序,观察程序执行过程,分析问题原因。
实验报告编译实验
一、实验目的1. 理解编译原理的基本概念和过程。
2. 掌握编译器的基本组成和编译流程。
3. 学会使用编译器对源代码进行编译,并分析编译结果。
二、实验环境1. 操作系统:Windows 102. 编译器:GCC (GNU Compiler Collection)3. 开发工具:Visual Studio Code三、实验内容1. 编译器的基本组成和编译流程2. 编译器的使用3. 编译结果分析四、实验步骤1. 编译器的基本组成和编译流程(1)词法分析:将源代码分解成一个个的单词,如标识符、关键字、运算符等。
(2)语法分析:将单词序列转换成语法树,验证源代码是否符合语法规则。
(3)语义分析:检查语法树,确保源代码在语义上是正确的。
(4)中间代码生成:将语法树转换成中间代码,如三地址代码。
(5)代码优化:对中间代码进行优化,提高程序运行效率。
(6)目标代码生成:将优化后的中间代码转换成目标代码,如汇编代码。
(7)代码生成:将目标代码转换成可执行文件。
2. 编译器的使用(1)编写源代码:使用Visual Studio Code编写C语言源代码。
(2)编译源代码:在命令行中输入gcc -o 程序名源文件名.c,编译源代码。
(3)运行程序:在命令行中输入程序名,运行编译后的程序。
3. 编译结果分析(1)词法分析:编译器将源代码中的单词进行分解,如以下代码:```cint main() {int a = 1;return a;}```编译器将分解为以下单词:- int- main- (- )- {- int- a- =- 1- ;- return- a- ;- }- }(2)语法分析:编译器将单词序列转换成语法树,验证源代码是否符合语法规则。
(3)语义分析:编译器检查语法树,确保源代码在语义上是正确的。
(4)中间代码生成:编译器将语法树转换成中间代码,如以下三地址代码:```t1 = 1a = t1t2 = areturn t2```(5)代码优化:编译器对中间代码进行优化,如以下优化后的三地址代码:```a = 1return a```(6)目标代码生成:编译器将优化后的中间代码转换成汇编代码。
编译原理实验报告小结
一、实验背景编译原理是计算机科学的一个重要分支,主要研究如何将高级语言源代码转换为计算机可以执行的机器代码。
本实验旨在通过实践操作,加深对编译原理基本概念和算法的理解,提高编程能力和解决问题的能力。
二、实验目的1. 理解编译原理的基本概念和流程;2. 掌握词法分析和语法分析的基本方法;3. 熟悉编译过程中的中间代码生成和代码优化;4. 培养编程能力和团队协作精神。
三、实验内容1. 词法分析词法分析是编译过程的第一步,其主要任务是将源代码中的字符序列转换成一个个有意义的符号(单词)。
本实验中,我们实现了词法分析器,能够识别出标识符、关键字、运算符、常量等单词。
2. 语法分析语法分析是编译过程的核心,其主要任务是将词法分析器生成的单词序列按照一定的语法规则进行组织,形成语法树。
本实验中,我们实现了递归下降解析法,对表达式、赋值语句、函数定义等语法结构进行了分析。
3. 中间代码生成中间代码生成是编译过程中的一个重要环节,其主要任务是将语法树转换为一种抽象的、与具体机器无关的中间代码。
本实验中,我们实现了三地址代码生成,将语法树转换为三地址代码。
4. 代码优化代码优化是编译过程中的一个关键步骤,其主要任务是在保证程序正确性的前提下,提高程序的性能。
本实验中,我们实现了简单的代码优化,如常数传播、变量替换等。
四、实验结果与分析1. 实验结果通过实验,我们成功实现了词法分析、语法分析、中间代码生成和代码优化等功能。
以一个简单的C语言程序为例,我们能够将其转换为三地址代码,并进行简单的优化。
2. 实验分析(1)词法分析:本实验中,我们通过定义状态转换表和动作表,实现了对C语言源代码的词法分析。
实验结果表明,词法分析器能够准确地识别出标识符、关键字、运算符、常量等单词。
(2)语法分析:递归下降解析法是一种较为直观的语法分析方法。
本实验中,我们实现了递归下降解析法,对表达式、赋值语句、函数定义等语法结构进行了分析。
编译系统设计实验报告
实验名称:编译系统设计实验时间:2023年X月X日实验地点:XX大学计算机学院实验室实验人数:XX人实验指导老师:XX教授一、实验目的1. 理解编译系统的基本概念和原理。
2. 掌握编译器各个阶段的设计和实现方法。
3. 提高编程能力和系统设计能力。
二、实验内容本次实验主要分为以下几个阶段:1. 词法分析阶段:将源代码中的字符序列转换为一个个词法符号。
2. 语法分析阶段:根据词法符号生成抽象语法树(AST)。
3. 语义分析阶段:对AST进行语义检查,确保程序的语义正确性。
4. 中间代码生成阶段:将AST转换为中间代码。
5. 代码优化阶段:对中间代码进行优化,提高程序运行效率。
6. 目标代码生成阶段:将优化后的中间代码转换为特定机器语言的目标代码。
7. 符号表管理阶段:在整个编译过程中,对符号进行管理。
三、实验步骤1. 设计词法分析器(1)定义词法符号集合:根据源代码的特点,定义词法符号集合,如标识符、关键字、运算符等。
(2)编写词法分析器代码:使用正则表达式或有限状态自动机实现词法分析器。
2. 设计语法分析器(1)定义语法规则:根据源代码的语法规则,定义语法规则。
(2)编写语法分析器代码:使用递归下降分析法或LL(1)分析算法实现语法分析器。
3. 设计语义分析器(1)定义语义规则:根据源代码的语义要求,定义语义规则。
(2)编写语义分析器代码:对AST进行遍历,检查语义正确性。
4. 设计中间代码生成器(1)定义中间代码格式:根据源代码的特点,定义中间代码格式。
(2)编写中间代码生成器代码:将AST转换为中间代码。
5. 设计代码优化器(1)选择优化策略:根据中间代码的特点,选择合适的优化策略。
(2)编写代码优化器代码:对中间代码进行优化。
6. 设计目标代码生成器(1)定义目标代码格式:根据目标机器的特点,定义目标代码格式。
(2)编写目标代码生成器代码:将优化后的中间代码转换为目标代码。
7. 设计符号表管理器(1)定义符号表结构:根据源代码的特点,定义符号表结构。
编译原理实验 编译器 综合报告(附源代码)
编译原理编译器综合实验---------------工程精品神刀公子一.实验背景编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序。
一个现代编译器的主要工作流程:源代码(source code) →预处理器(preprocessor) →编译器 (compiler) →目标代码(object code) →链接器(Linker) → 可执行程序 (executables)高级计算机语言便于人编写,阅读交流,维护。
机器语言是计算机能直接解读、运行的。
编译器将汇编或高级计算机语言源程序(Source program)作为输入,翻译成目标语言(Target language)机器代码的等价程序。
源代码一般为高级语言(High-level language),如Pascal、C、C++、Java、汉语编程等或汇编语言,而目标则是机器语言的目标代码(Object code),有时也称作机器代码(Machine code)。
对于C#、VB等高级语言而言,此时编译器完成的功能是把源码(SourceCode)编译成通用中间语言(MSIL/CIL)的字节码(ByteCode)。
最后运行的时候通过通用语言运行库的转换,编程最终可以被CPU直接计算的机器码(NativeCode)。
二.算法设计典型的编译器输出是由包含入口点的名字和地址,以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。
一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的EXE,词法分析程序→语法分析程序→语义分析程序→编译器。
不断完善,不断改进。
渐变的过程。
函数。
void scanner(); //扫描void lrparser();void staBlock(int *nChain); //语句块void staString(int *nChain); //语句串void sta(int *nChain); //语句void fuzhi(); //赋值语句void tiaojian(int *nChain); //条件语句void xunhuan(); //循环语句char* E(); //Expresiion表达式char* T(); //Term项char* F(); //Factor因子char *newTemp(); //自动生成临时变量void backpatch(int p,int t); //回填int merge(int p1,int p2); //合并p1和p2void emit(char *res,char *num1,char *op,char *num2); //生成四元式截图说明:综合输入:(赋值,循环,条件。
编译实习报告
篇一:编译原理实习报告实习报告【实习目的】1.了解编译器的工作原理2.掌握并加深本学期所学的编译原理的理论知识3.加强自己的动手能力【实习内容】1.编译并运行老师所给的编译器参考代码2.在第一步的基础上进一步改进编译器,增加输入输出功能【开发平台】window系统,free pascal编译器【实习过程】本次实习过程根据实习内容共分两大部分,第一部分,编译运行参考代码;第二部分,进一步改进编译器。
本人在上面的基础上又增加了第三部分的额外修改。
下面便总结这三部分的实习过程:一、增加读写语句前pl0编译程序由于最原始的pl0编译程序所用的pascal版本较老,有些和当前使用版本不兼容,必须作相应修改,具体是:“object”和“procedure”为pascal的保留字,现分别改成“obj”和“proc”。
此外,原始程序中的“≠”、“≤”和“≥”,不能用ascii码表示出来,现将其替换成“<>”、“<=”和“>=”。
作为一个编译程序,支持批量处理和永久保存是其应具备的基本功能。
为此,本程序加入了文件读写功能,即从文件读入pl0源程序,在将中间代码和运行结果写入文件。
由于源程序和原始差别很小,为节省篇幅,不将其打印出来。
二、增加读写语句前pl0调试程序下面是增加读写语句前的pl0程序,包含了乘、除法和寻找两个自然数的最大公因数的过程和主过程,很好的说明了增加读写语句前的pl0语言的使用方法。
constvarx,y,z,q,r; procedure multiply; var a,b; a:=x; begin m=7,n=85;procedure divide; var end; b:=y; z:=0; while b>0 do begin end if odd b then z:=z+a; a:=2*a; b:=b/2;w;beginr:=x;q:=0;w:=y;while w<=r do w:=2*w;while w>y dobegin q:=2*q; w:=w/2;if w<=r thenbeginr:=r-w;q:=q+1endendend;procedure gcd;varf,g;beginf:=x;g:=y;while f<>g dobeginif f<g then g:=g-f;if g<f then f:=f-g;end;z:=fend;beginx:=m;y:=n;call multiply;y:=3;call divide;x:=84;y:=36;call gcd;end.三、增加读写语句前pl0编译程序生成的中间代码下面所给清单是用(一)中增加读写语句前pl0编译程序对(二)中的pl0程序编译生成的中间代码。
编译原理教程实验报告
一、实验目的本次实验旨在使学生通过编译原理的学习,了解编译程序的设计原理及实现技术,掌握编译程序的各个阶段,并能将所学知识应用于实际编程中。
二、实验内容1. 词法分析2. 语法分析3. 语义分析4. 中间代码生成5. 代码优化6. 目标代码生成三、实验步骤1. 词法分析(1)设计词法分析器,识别输入源代码中的各种词法单元;(2)使用C语言实现词法分析器,并进行测试。
2. 语法分析(1)根据文法规则设计语法分析器,识别输入源代码的语法结构;(2)使用C语言实现语法分析器,并进行测试。
3. 语义分析(1)设计语义分析器,检查语法分析后的语法树,确保语义正确;(2)使用C语言实现语义分析器,并进行测试。
4. 中间代码生成(1)设计中间代码生成器,将语义分析后的语法树转换为中间代码;(2)使用C语言实现中间代码生成器,并进行测试。
5. 代码优化(1)设计代码优化器,对中间代码进行优化,提高程序性能;(2)使用C语言实现代码优化器,并进行测试。
6. 目标代码生成(1)设计目标代码生成器,将优化后的中间代码转换为特定目标机的汇编语言;(2)使用C语言实现目标代码生成器,并进行测试。
四、实验结果与分析1. 词法分析实验结果:成功识别输入源代码中的各种词法单元,包括标识符、关键字、运算符、常量等。
2. 语法分析实验结果:成功识别输入源代码的语法结构,包括表达式、语句、程序等。
3. 语义分析实验结果:成功检查语法分析后的语法树,确保语义正确。
4. 中间代码生成实验结果:成功将语义分析后的语法树转换为中间代码,为后续优化和目标代码生成提供基础。
5. 代码优化实验结果:成功对中间代码进行优化,提高程序性能。
6. 目标代码生成实验结果:成功将优化后的中间代码转换为特定目标机的汇编语言,为程序在目标机上运行做准备。
五、实验心得1. 编译原理是一门理论与实践相结合的课程,通过本次实验,我对编译程序的设计原理及实现技术有了更深入的了解。
【精品文档】编译器实验报告-word范文 (8页)
本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除!== 本文为word格式,下载后可方便编辑和修改! ==编译器实验报告篇一:编译器实验报告甘肃政法学院本科学生实验报告姓名学院专业班级试验时间 201X 年 12 月 20日指导教师及职称实验成绩开课时间 201X-201X 学年 1学期实验课程名称编译原理甘肃政法学院实验管理中心印制篇二:编译器测试实验报告深圳大学实验报告课程名称:实验项目名称:学院:计算机与软件学院班级:实验时间:实验报告提交时间:教务处制2342、教师批改学生实验报告时间应在学生提交实验报告时间后10日内。
5篇三:哈弗曼编译器实验报告实习报告题目:哈弗曼编译码器班级:电信系通信工程0902班完成日期:201X.11一、需求分析1、编写哈弗曼编译码器,其主要功能有(1)I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树。
(2)E:编码(Encoding)。
利用已建好的哈夫曼树),对从终端输入的正文进行编码,然后从终端输出。
(3)D:译码(Decoding )。
利用已建好的哈夫曼树将从终端输入的代码进行译码,结果从终端输出。
(4)P:印哈夫曼树(Print)。
将已编码的的哈夫曼树显示在终端上,同时将此字符形式的哈夫曼树。
2、测试数据:输入的字符={a, b, c, d, e}其对应的权值={5,29,7,8,14}二、概要设计1、二哈弗曼树的抽象数据类型定义为:ADT HuffmanTree{数据对象D:D是具有相同性质的数据元素的集合数据关系R:若D=Φ,则R= Φ,哈弗曼树为空若D≠Φ,则R= {H},H是如下二元关系:(1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱(2)若D-{root}≠Φ,则存在D-{root}={Dl,Dr}。
且Dl∩Dr=Φ(3)若Dl≠Φ,则Dl中存在唯一的数据元素Xl,<root, Xl>属于H,且存在Dl上的关系H1属于H。
编译词法分析实验报告
一、实验目的1. 理解词法分析的基本概念和原理。
2. 掌握词法分析器的实现方法。
3. 熟悉C语言在词法分析中的应用。
4. 提高编程能力和问题解决能力。
二、实验环境1. 操作系统:Windows 102. 编程语言:C3. 开发环境:Visual Studio 2019三、实验内容1. 设计词法分析器,实现对源代码的词法分析。
2. 将源代码分解为单词序列。
3. 输出单词序列及对应的词法类型。
四、实验步骤1. 分析源代码中的词法单位,确定词法类型。
2. 设计词法分析器的状态转换表。
3. 编写词法分析器代码。
4. 测试词法分析器,验证其正确性。
五、实验过程1. 分析源代码中的词法单位在C语言中,词法单位包括标识符、关键字、运算符、分隔符、常量等。
本实验以C语言为例,分析源代码中的词法单位,确定词法类型。
2. 设计词法分析器的状态转换表根据词法单位,设计词法分析器的状态转换表。
状态转换表包括当前状态、输入字符、下一状态、输出词法类型和对应动作。
3. 编写词法分析器代码根据状态转换表,编写词法分析器代码。
以下为词法分析器的主要功能模块:(1)初始化:设置初始状态、词法类型和单词长度。
(2)读取字符:从源代码中读取字符,并判断字符类型。
(3)状态转换:根据状态转换表,更新当前状态、输出词法类型和单词长度。
(4)输出结果:将单词序列及对应的词法类型输出到屏幕。
4. 测试词法分析器编写测试用例,验证词法分析器的正确性。
测试用例包括以下几种情况:(1)包含各种词法单位的源代码。
(2)包含注释的源代码。
(3)包含错误标识符的源代码。
六、实验结果与分析1. 实验结果通过测试,词法分析器能够正确识别源代码中的各种词法单位,并将单词序列及对应的词法类型输出到屏幕。
以下为部分测试结果:```int a = 10; // 输出:int, 标识符if (a > 0) // 输出:if, 关键字{// 输出:{, 分隔符// ...// 输出:}, 分隔符}// 输出://, 注释开始注释内容// 输出://, 注释结束```2. 实验分析(1)实验过程中,通过对词法分析原理的学习,加深了对编译原理的理解。
论文编译实习报告
随着我国经济的快速发展,对外交流与合作日益增多,论文编译工作在学术交流、文化传播等领域发挥着重要作用。
为了提高自身的编译能力,我于XX年XX月至XX年XX月在XX出版社进行了为期一个月的论文编译实习。
二、实习内容1. 编译实践在实习期间,我主要负责对英文论文进行编译。
具体工作包括:(1)阅读论文原文,了解论文的研究背景、研究目的、研究方法、研究结果等。
(2)根据论文内容,对专业术语进行翻译,确保翻译的准确性。
(3)调整论文结构,使其符合中文写作规范。
(4)对翻译后的论文进行校对,确保无语法错误和错别字。
2. 编译技巧学习在实习过程中,我积极向经验丰富的编译员请教,学习了一些编译技巧:(1)了解并掌握常用的翻译软件和工具,提高翻译效率。
(2)注重培养自己的语言表达能力,提高翻译质量。
(3)关注学术动态,了解相关领域的最新研究成果,提高翻译的准确性。
三、实习收获1. 编译能力得到提高通过实习,我对论文编译工作有了更深入的了解,掌握了编译的基本技巧和方法。
在编译实践中,我不断提高自己的翻译水平,使编译质量得到了显著提升。
2. 学术素养得到提升在编译过程中,我不断学习专业知识,了解相关领域的最新研究成果。
这使我具备了较高的学术素养,为今后的学术研究奠定了基础。
3. 团队协作能力得到锻炼在实习过程中,我与同事相互学习、共同进步,锻炼了自己的团队协作能力。
通过这次论文编译实习,我深刻认识到论文编译工作的重要性。
在今后的学习和工作中,我将继续努力提高自己的编译能力,为学术交流和文化传播贡献自己的力量。
以下是我在实习期间的一些体会:1. 编译工作需要严谨的态度和扎实的专业知识。
2. 编译过程中,要注意与原文作者的沟通,确保翻译的准确性。
3. 提高自己的语言表达能力,有利于提高翻译质量。
4. 团队协作是完成编译任务的关键。
总之,这次实习让我受益匪浅,为我今后的职业发展奠定了基础。
在今后的学习和工作中,我将继续努力,不断提高自己的综合素质。
编译软件实验报告
一、实验目的本次实验旨在通过编译软件的学习和实践,使学生掌握编译软件的基本原理和实现方法,提高学生编程能力和软件设计能力。
通过本次实验,学生应能够:1. 理解编译软件的基本概念和作用;2. 掌握编译软件的基本结构和工作流程;3. 学会使用编译软件进行程序编译;4. 了解编译软件的优化方法和性能评估;5. 培养团队合作精神和实践创新能力。
二、实验环境1. 操作系统:Windows 102. 编译软件:GCC(GNU Compiler Collection)3. 编程语言:C/C++4. 开发工具:Visual Studio Code三、实验内容1. 编译软件的基本概念和作用编译软件是将高级语言程序转换为机器语言程序的软件。
它主要包括词法分析、语法分析、语义分析、代码生成和优化等阶段。
编译软件的作用是将程序员编写的高级语言程序转换为计算机能够理解和执行的机器语言程序,从而实现程序的执行。
2. 编译软件的基本结构和工作流程编译软件的基本结构包括词法分析器、语法分析器、语义分析器、中间代码生成器、代码优化器和目标代码生成器等模块。
工作流程如下:(1)词法分析:将源代码中的字符序列转换为单词序列;(2)语法分析:根据语法规则对单词序列进行语法分析,生成抽象语法树(AST);(3)语义分析:对AST进行语义检查,确定变量的作用域、类型等;(4)中间代码生成:将AST转换为中间代码;(5)代码优化:对中间代码进行优化,提高程序执行效率;(6)目标代码生成:将优化后的中间代码转换为机器语言程序。
3. 编译软件的使用(1)编写C/C++程序:使用Visual Studio Code编写C/C++程序,保存为`.c`或`.cpp`文件。
(2)编译程序:在命令行中使用GCC编译器编译程序。
例如,编译名为`main.c`的程序,可以使用以下命令:```gcc -o main main.c```编译成功后,会在当前目录下生成名为`main`的可执行文件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计报告( 2013 -- 2014年度第 1 学期)名称:编译技术课程设计B题目:词法分析器设计算符优先分析程序设计基于算符优先分析方法的语法制导翻译程序设计院系:计算机系班级:计科1102班学号:学生姓名:指导教师:设计周数:1周成绩:日期:2014 年 1 月 3 日一、课程设计的目的与要求1.词法分析器设计的目的与要求1.1 词法分析器设计的实验目的本实验是为计算机科学与技术专业、网络工程专业、信息安全专业的学生在学习《编译技术》课程后,为加深对课堂教学内容的理解,培养解决实际问题能力而设置的实践环节。
通过这个实验,使学生应用编译程序设计的原理和技术设计出词法分析器,了解扫描器的组成结构,不同种类单词的识别方法。
能使得学生在设计和调试编译程序的能力方面有所提高。
为将来设计、分析编译程序打下良好的基础。
1.2 词法分析器设计的实验要求设计一个扫描器,该扫描器是一个子程序,其输入是源程序字符串,每调用一次识别并输出一个单词符号。
为了避免超前搜索,提高运行效率,简化扫描器的设计,假设该程序设计语言中,基本字(也称关键词)不能做一般标识符用,如果基本字、标识符和常数之间没有确定的运算符或界符作间隔,则用空白作间隔。
单词符号及其内部表示如表1-1所示,单词符号中标识符由一个字母后跟多个字母、数字组成,常数由多个十进制数字组成。
单词符号的内部表示,即单词的输出形式为二元式:(种别编码,单词的属性值)。
表1-1 单词符号及其内部表示2.算符优先分析程序设计的目的和要求 2.1 算符优先分析程序设计的实验目的本实验是为计算机科学与技术等专业的学生在学习《编译技术》课程后,为加深对课堂教学内容的理解,培养解决实际问题能力而设置的实践环节。
通过这个实验,使学生应用编译程序设计的原理和技术, 设计、编写和调试算符优先分析程序,了解算符优先分析程序的组成结构,掌握实现通用算符优先分析算法的方法。
能使得学生在设计和调试编译程序的能力方面有所提高。
为将来设计、分析编译程序打下良好的基础。
2.2 算符优先分析程序设计的实验要求算符优先分析属于自下而上的分析方法,该语法分析程序的输入是终结符号串(即单词符号串,以一个“#”结尾),如果输入串是句子则输出“YES ”,否则输出“NO ”和错误信息。
算符优先分析过程与非终结符号无关,当由文法产生了优先关系之后文法也就失去了作用,本题目给出文法的目的是为了便于对语法分析结果进行验证。
(1)文法 设算符优先文法G 为:T T E E |+→F F T T |*→P F P F |↑→i E P |)(→说明:i 为整型常数或者为标识符表示整型变量;使用中↑用**表示。
(2)优先关系表 设优先关系表如表1-2所示。
表1-2 优先关系表3.基于算符优先分析方法的语法制导翻译程序设计的目的和要求3.1基于算符优先分析方法的语法制导翻译程序设计的实验目的本实验是为计算机科学与技术等专业的学生在学习《编译技术》课程后,为加深对课堂教学内容的理解,培养解决实际问题能力而设置的实践环节。
通过这个实验,使学生应用编译程序设计的原理和技术, 通过设计、编写和调试语法制导翻译程序,掌握从一种语句的语法和语义出发,构造相应的语义子程序,实现基于算符优先分析方法的语法制导翻译的方法。
能使得学生在设计和调试编译程序的能力方面有所提高。
为将来设计、分析编译程序打下良好的基础。
3.2 基于算符优先分析方法的语法制导翻译程序设计的实验要求算符优先分析方法是通过反复把输入符号移进分析栈,使用优先关系表在分析栈顶寻找最左素短语,将其归约为一个非终结符号而实现的。
这个分析过程与非终结符号无关,当由文法产生了优先关系之后文法也就失去了作用(所以本题目无需给出文法)。
基于算符优先分析方法的语法制导翻译是在算符优先语法分析的基础上进行翻译工作(即语义分析),每当将一个最左素短语归约为一个非终结符号时,就调用对应产生式的语义子程序,去完成相应的语义翻译工作,这步归约使用的产生式对非终结符号不加区分(即将所有的非终结符号用一个通用的非终结符号表示)。
语法制导翻译程序的输入是终结符号串(即单词符号串,以一个“#”结尾),如果输入符号串是句子,则按照其语义进行翻译,输出等价的四元式序列(作为练习应显示输出)。
二、课程设计正文1.词法分析器设计1.1以键盘输入的方式输入句子。
(1) 标识符和常数的属性值(a)标识符和常数的属性值为该单词在名次表或常数表中登记项的相对地址;(b)当识别出一个标识符或常数时,要查名字表或常数表,若表中有其登记项,则把得到的登记项地址作为其属性值;(c)若表中没有其登记项,则建立一个新登记项,该记录项地址作为其属性值,此处的地址为在表中的下标。
1.2实验分析实验分析:对于输入的句子,使用cin.get函数转换为数组。
分析过程首先要进行对空格、回车、Tab的判断,若为之一则指针向后移动。
如果是字母,继续判断后面的是否为字母或者数字,如果是,则加入arr中,继续判断arr是否为关键字,对于已经存入的关键字,需要通过查表操作来完成;若不是关键字,则构成标识符,将其存入地址记录表。
如果开始是数字,则判断它后边紧接着的是否为数字或者小数点加数字,若满足之一,则为实数,将其存入地址记录表;若两条均不满足,则表明为常数的单词已经结束,进行下一步单词的分析。
对于界符和运算符的的分析,只需判断单个字符即可,对于双目运算符,要在当前位置的基础上指针后移,再进行判断。
算法简要概述:关键字表、输出串用string数组存储。
采用一个字符串arr来存储分析的单词,若未分析完,则将正在处理的字符连接到arr后面,若当前单词分析完,则重新对arr进行赋值,直至整个句子全部分析完成。
数组remember[],类型为int,为变量的地址记录表;re为remember 的指针;jjj()函数用于将变量或常量存入地址记录表,iii()函数用于读取输入串中的下一个字符。
2. 算符优先分析程序设计2.1以键盘输入的方式输入句子。
2.2 实验分析实验分析:优先关系表用一个数组chart[]表示,是一个8*8的二维矩阵;分析栈用数组stacks []表示,表示的元素为终结符号、“#”、非终结符N,;数组record [],用于存放输入字符串。
算符优先分析属于自下而上的分析方法,在分析的过程中需要借助于优先关系表,在分析过程中通过查找优先关系表和分析栈的共同作用来进行分析。
算法简要概述:算法首先将分析栈压入“#”,然后对字符串进行遍历。
算法使用两个while嵌套循环,外层为当前字符a不为#则继续,内层循环当发现栈顶终结符的优先级的低于或等于正在考察的字符时,字符入栈,执行移入操作;当前字符与其后一个终结符的相对优先关系为大于时,则进行规约,规约的具体方法是从栈顶往栈底方向查,当发现第一个优先级低于栈顶终结符时查找结束,记录当前位置,然后从栈顶到该终结符的上一个位置规约为一个“N”,依次类推,当分析栈最终出现“#N#”,则证明输入串是句子,分析结束。
若分析栈的栈顶元素与当前输入符号没有优先关系,则说明输入串有语法错误,即输入的不是句子,输出错误提示,分析结束。
3.基于算符优先分析方法的语法制导翻译程序的设计3.1 该实验算法是在第二个实验的基础上进行的,在上一个实验中只是简单的将需要规约的部分规约为“N”,而实验三中的规约是在原来的基础上进行数字的改变。
在产生式的产生时,需要判断是使用的那个规约文法,在教材给出的五个产生式中,当采用前三个时才会有产生式生成。
将规约后产生的N变为中间变量Ti,当遇到产生中间变量时,需要输出该四元式。
三、课程设计总结或结论1.词法分析器设计通过词法分析器的设计,、更加加深了对词法分析原理的理解,明确了运算符、界符、标识符、常数的定义,实验需要注意的问题是对空格的过滤,以及对双目运算符的处理。
另外,对小数的处理也要加以注意,注意判断“.”是做为界符还是小数点。
对于关键字的判断,直接使用.compare(ch)函数,可以大大减少代码的行数,更可避免编写逐字比较程序时产生错误。
2.算符优先分析程序设计算符优先分析的设计,主要是把优先关系表和分析栈结合起来,通过优先级的判断来决定进行规约、入栈还是错误判断的操作。
规约时应注意使用哪个产生式进行规约,注意栈内内容的变化。
实验另外需要注意的是对于“i+”一类非句子输入的判断。
通过本次实验更加深刻的理解了优先关系表的相关概念,也体会到了优先关系表对于编译过程的意义。
3.基于算符优先分析方法的语法制导翻译程序的设计在算符优先分析的基础上进行本次实验,我对于基于算符优先分析方法的语法制导翻译我有了更深一步的认识。
处理的难点就是将规约与上面的实验区别开来,在产生式的产生时,需要判断是使用的那个规约文法,将规约后产生的N变为中间变量Ti,当遇到产生中间变量时,需要输出该四元式。
这次实验基本达到了实验目的,由于所学知识不够全面,在试验中也遇到了很多编程上的困难,在很多方面还有待完善,在以后的学习过程中,力争掌握更多知识,在以后学习中要更加努力。
四、参考文献[1] 陈火旺,刘春林. 程序设计语言编译原理. 北京:国防工业出版社,第三版. 2008,9[2] 宋雨,程晓荣,黄志强. 计算机综合实践指导. 北京:清华大学出版社,第一版. 2004附录(设计流程图、程序、运行结果等)1(词法分析)(算符优先分析)(语法制导翻译程序)2、源代码(1)Morphology.cs……………………#region定义机内码private void NewKeyWord(){machineCodes[0] = "";machineCodes[1] = "BEGIN";machineCodes[2] = "IF";machineCodes[3] = "THEN";machineCodes[4] = "ELSE";machineCodes[5] = "END";machineCodes[6] = "标识符";machineCodes[7] = "整形常数";machineCodes[8] = "+";machineCodes[9] = "*";machineCodes[10] = "!";machineCodes[11] = "(";machineCodes[12] = ")";machineCodes[13] = "#";}#endregion#region处理输入的代码public void Dispose(){while (i < input.Length) //只要不超出字符串长度就继续执行 {if (IsAlpha(input[i])){RecogId();}else if (IsDight(input[i])){RecogCons();}else if (input[i] == '\r' && input[i + 1] == '\n'){rowNum++;i++;i++;//跳过去}else if (IsDelimiter(input[i])){RecogSym();}else if (input[i] == ' '){i++;}else{Error e = new Error(rowNum, input[i].ToString(), "(1)非法字符");errors.Add(e);i++;}}}#endregion#region判断是标识符还是关键字并处理private void RecogId(){string str = "";int code;do{str = str + input[i];i++;} while (IsAlpha(input[i]) || IsDight(input[i]));//判断是不是字母或数字,是的话继续执行 code = Reserve(str);//看是否为关键字token t = new token();//存入token文件bel = tokens.Count; = str;if (code == 0){t.Code = 6; //标示符t.Addr = symbles.Count;symble s = new symble();//存入符号表s.Number = t.Addr; = str;s.Type = 6;symbles.Add(s);}else{t.Code = code;t.Addr = -1;}tokens.Add(t);}#endregion#region判断是不是常数并处理private void RecogCons(){string str = input[i].ToString();bool flag = true;bool point = false;while (flag){i++;if (IsDight(input[i])){str += input[i];}else if (IsAlpha(input[i])||input[i]=='.'){Error e = new Error(rowNum, str, "非整数"); errors.Add(e);flag = false;ignore();}else{flag = false;//结束不再查找}}token t = new token();//写入表bel = tokens.Count; = str;t.Code = 7; //整数t.Addr = symbles.Count;symble s = new symble();s.Number = t.Addr; = str;s.Type = 7;symbles.Add(s);tokens.Add(t);}#endregion#region判断是否是符号并处理private void RecogSym(){string str = "" + input[i];for (int j = 8; j <= 13; j++){if (str == machineCodes[j]){token t = new token();bel = tokens.Count; = str;t.Code = j;t.Addr = -1;tokens.Add(t);i++;}}}#endregion#region判断是不是字母private bool IsAlpha(char c){if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){return true;}else{return false;}}#endregion#region判断是不是数字private bool IsDight(char c){if (c >= '0' && c <= '9'){return true;}else{return false;}}#endregion#region判断是不是其他界符private bool IsDelimiter(char c){switch (c){case'(': return true;case')': return true;case'+': return true;case'!': return true;case'*': return true;case'#': return true;default: return false;}}#endregion#region匹配机内码private int Reserve(string str){for (int i = 1; i <= 5; i++){if (str == machineCodes[i]){return i;//返回机内码编号}}return 0;//标识符}#endregion#region忽略多余字符private void ignore(){string str = "";while (input[i] == '.' || IsAlpha(input[i]) || IsDight(input[i])) {str += input[i];i++;}errors.Add(new Error(rowNum, str, "忽略字符"));}#endregion}}(2)OperatorPrecedence.cs……………………static List<List<char>> Precedence = new List<List<char>>{new List<char> (){' ','+','*','!','i','(',')','#'},new List<char> (){'+','>','<','<','<','<','>','>'},new List<char> (){'*','>','>','<','<','<','>','>'},new List<char> (){'!','>','>','<','<','<','>','>'},new List<char> (){'i','>','>','>',' ',' ','>','>'},new List<char> (){'(','<','<','<','<','<','=',' '},new List<char> (){')','>','>','>',' ',' ','>','>'},new List<char> (){'#','<','<','<','<','<',' ','='}};int TCount = 0;Morphology mor;///<summary>///能够使用的运算符///</summary>List<string> OpetatorList = new List<string>() { "+", "*", "!", "i", "(", ")", "#" };public List<FourPart> fourPartResult = new List<FourPart>();……………………public OperatorPrecedence(string s){Soures = "#" + s;mor = new Morphology(Soures);}public void begin(){int a = 1;if (checkAll()){PushToTarget();while (a == 1 || a == 2 || a == 3)//直到规约结束或出错{a = compare1();if (a == 1){if (trans() != 0) {break;}}if (a == 2 || a == 3){if (!PushToTarget()){}}}if (place<mor.tokens.Count - 1) {result = "NO出错了";}}else{result = "NO出错了";}}///<summary>///把左边栈内每一个元素的name写入结果的下一行///</summary>public void writeLeft(){for (int i = 1; i <= LeftList.Count; i++){result += LeftList[LeftList.Count - i].name;}result += "\n";}///<summary>///规约///</summary>public int trans(){int result = 0;try{target toTrans = LeftList.Find( //查找终结符delegate(target t){return t.isTransed == false; //返回非终结符});int num; //非终结符在栈中序号if (toTrans != null){num = LeftList.IndexOf(toTrans);if (toTrans.isSymble){ECount++; = "E" + ECount;toTrans.isTransed = true;LeftList.Insert(num, toTrans);LeftList.RemoveAt(num + 1);writeLeft();}else{if (toTrans.flag == ')'){if (LeftList[num + 1].isSymble && LeftList[num + 2].flag == '('){ECount++;target t = new target("E"+ ECount, 'i', LeftList[num + 1].numInTokens, true, true);LeftList.Insert(num, t);LeftList.RemoveAt(num + 1);LeftList.RemoveAt(num + 1);LeftList.RemoveAt(num + 1);writeLeft();}}else//是其他元素和两边的元素归约{ECount++;TCount++;target t = new target("E" + ECount, 'i', 0 - TCount, true, true);target t1 = new target("T" + TCount, 'i', -1, true, true); //运算结果FourPart fp = new FourPart();fp.Op = toTrans.flag.ToString();if (LeftList[num - 1].numInTokens > -1){fp.StrRight = mor.tokens[LeftList[num - 1].numInTokens].Name;}else{fp.StrRight = OpResult[0 - (LeftList[num - 1].numInTokens + 1)].name;}if (LeftList[num + 1].numInTokens > -1){fp.StrLeft = mor.tokens[LeftList[num + 1].numInTokens].Name;}else{fp.StrLeft = OpResult[0 - (LeftList[num + 1].numInTokens + 1)].name;}fp.JumpNum = "T" + TCount;OpResult.Add(t1);fourPartResult.Add(fp);LeftList.Insert(num - 1, t);LeftList.RemoveAt(num);LeftList.RemoveAt(num);LeftList.RemoveAt(num);writeLeft();}}}return 0;}catch (Exception x) {return 1;}}///<summary>///检测所有词法分析的单词,保证能够被分析///</summary>///<returns>是否通过检测</returns>bool checkAll(){foreach (token t in mor.tokens){if (mor.tokens[place].Addr == -1){if (!OpetatorList.Contains(mor.tokens[place].Name)){return false;}}}if (mor.tokens[mor.tokens.Count - 1].Name != "#") {return false;}return true;}///<summary>///把缓冲区顶部元素压入左边的栈///</summary>///<returns></returns>bool PushToTarget(){if (place < mor.tokens.Count){if (mor.tokens[place].Addr == -1)//是关键字{LeftList.Insert(0, new target(mor.tokens[place].Name, mor.tokens[place].Name[0], place, false, false));if (place == 0 || (mor.tokens[place].Name != "#")){place++;writeLeft();}else{place++;return false;}}else{LeftList.Insert(0, new target(mor.tokens[place].Name, 'i', place, false, true)); writeLeft();place++;}return true;}else{return false;}}///<summary>///求优先级///</summary>///<returns></returns>int compare1(){int result = 0;char rightHead;target leftHead;if (place >= mor.tokens.Count){return result;}#region取缓冲区栈顶代表的算符if (mor.tokens[place].Addr == -1){rightHead = mor.tokens[place].Name[0];}else{rightHead = 'i';}#endregionleftHead = LeftList.Find(delegate(target t)//查找体,找到左边栈内第一个非终结符{return t.isTransed == false;});if (leftHead == null){return 2;}else{foreach (List<char> list in Precedence)//遍历优先级信息表中的每一个行元素{if (list[0] == leftHead.flag){int n = Precedence[0].IndexOf(rightHead);//非终结符和右面的第一个元素比较查表switch (list[n]){case'>':result = 1;//后边进行归约操作break;case'<':result = 2;//后边进行入栈操作break;case'=':result = 3;//后边进行入栈操作break;case' ':result = 4;//出错break;…………………………(3)Semantic.cs…………………………namespace bianyi{public class Semantic{public List<FourPart> fps = new List<FourPart>();public List<E> es = new List<E>();List<token> tokens;public List<symble> symbles=new List<symble>();public string error = "";int i = 0;int ti = 1;string tt = "";public Semantic(Morphology m){tokens = m.tokens;symbles = m.symbles;Dispose();}private void Next(){if (i < tokens.Count - 1){i++;}}private void Before(){if (i > 0){i--;}}#region创建临时变量private string NewTemp(){string temp = "T" + ti.ToString();ti++;symble s=new symble();=temp;symbles.Add(s);return temp;}#endregion#region回填函数private void BackPatch(int addr, int addr2){fps[addr].JumpNum = addr2.ToString();}#endregion#region产生四元式private void Emit(string op, string strLeft, string strRight, string jumpNum) {FourPart fp = new FourPart(op, strLeft, strRight, jumpNum);fps.Add(fp);}#endregion#region主要函数private void Dispose(){if (tokens[i].Code == 12)//含有program{Next();if (tokens[i].Code == 18)//是标识符{Emit("program", tokens[i].Name, "_", "_");//执行程序体Next();ProBody();}else{error = "该程序program缺少方法名";}}else{error = "该程序缺少关键字:program";}}#endregion#region程序体private void ProBody(){if (tokens[i].Code == 16){Next();VarDef();}else if (tokens[i].Code == 2){Next();ComSent();}else{error = "程序体缺少var或begin";}}#endregion#region变量定义private void VarDef(){if (IsIdlist()){Next();if (tokens[i].Code == 29)//:{Next();if(tokens[i].Code == 9 || tokens[i].Code == 3 || tokens[i].Code == 13)//integer,bool,real{int j = i;j = j - 2;symbles[tokens[j].Addr].Type = tokens[i].Code;j--;while (tokens[j].Code == 28){j--;symbles[tokens[j].Addr].Type = tokens[i].Code;}Next();if (tokens[i].Code == 30){Next();if (tokens[i].Code == 2){Next();ComSent();}else{VarDef();}}else{error = "变量定义后面缺少;";}}else{error = "变量定义缺少类型或类型定义错误";return;}}else{error = "var后面缺少冒号";}}else{error = "变量定义标识符出错";}}#endregion#region判断是不是标识符表private bool IsIdlist(){if (tokens[i].Code == 18){Next();if (tokens[i].Code == 28)//,{Next();return IsIdlist();}else{Before();return true;}}else{return false;}}#endregion#region复合句private void ComSent(){SentList();if (error == ""){if (tokens[i].Code == 6){Emit("sys", "_", "_", "_");}else{error = "复合句末尾缺少end";}}}#endregion#region语句表private void SentList(){S s = new S();ExecSent(ref s);if (error == ""){Next();if (tokens[i].Code == 30){Next();SentList();}}}#endregion#region执行句private void ExecSent(ref S s){if (tokens[i].Code == 18){Next();AssiSent();}else if (tokens[i].Code == 2 || tokens[i].Code == 8 || tokens[i].Code == 17) {StructSent(ref s);}else{Before();}}#endregion#region赋值句private void AssiSent(){if (tokens[i].Code == 31)//:={string temp = tokens[i - 1].Name;Next();Expression();Emit(":=", tt, "_", temp);}else{error = "赋值句变量后缺少:=";}}#endregion#region表达式private void Expression(){if(tokens[i].Code == 7 || tokens[i].Code == 15 || (tokens[i].Addr != -1 && symbles[tokens[i].Addr].Type == 3)){E e = new E();BoolExp(ref e);}else{AritExp();}}#endregion#region布尔表达式private void BoolExp(ref E e){E e1 = new E();BoolItem(ref e1);if (error == ""){Next();if (tokens[i].Code == 11){int m = fps.Count;E e2 = new E();Next();BoolExp(ref e2);e.t.Concat(e1.t);e.t.Concat(e2.t);e.f = e2.f;foreach (int k in e.t){BackPatch(k, m);}}else{e = e1;Before();}}else{e = e1;}}#endregion#region布尔项private void BoolItem(ref E e){E e1 = new E();BoolFactor(ref e1);if (error == ""){Next();if (tokens[i].Code == 1){Next();int m = fps.Count;E e2 = new E();BoolItem(ref e2);e.t = e2.t;e.f.Concat(e1.f);e.f.Concat(e2.f);foreach (int k in e.t){BackPatch(k, m);}}else{e = e1;Before();}}}#endregion#region布尔因子private void BoolFactor(ref E e){if (tokens[i].Code == 10){Next();E e1 = new E();BoolFactor(ref e1);e.t = e1.f;e.f = e1.t;}else{E e1 = new E();BoolValue(ref e1);e = e1;}}#endregion#region布尔量private void BoolValue(ref E e){if (tokens[i].Code == 15 || tokens[i].Code == 7){e.t.Add(fps.Count);e.f.Add(fps.Count + 1);tt = tokens[i].Name;}else if (tokens[i].Code == 18){Next();if (tokens[i].Code == 34 || tokens[i].Code == 33 || tokens[i].Code == 32 || tokens[i].Code == 37 || tokens[i].Code == 36 || tokens[i].Code == 35){Next();if (tokens[i].Code == 18){e.t.Add(fps.Count);e.f.Add(fps.Count + 1);Emit("j", "_", "_", "-1");}else{Before();}}else{Before();e.t.Add(fps.Count);e.f.Add(fps.Count + 1);Emit("jnz", tokens[i].Name, "_", "-1");Emit("j", "_", "_", "-1");Next();}}else if (tokens[i].Code == 21){E e1 = new E();BoolExp(ref e1);e.t = e1.t;e.f = e1.f;if (tokens[i].Code == 22){return;}}}#endregion#region算数表达式private void AritExp(){Item();if (error == ""){Next();if (tokens[i].Code == 23 || tokens[i].Code == 24){string[] temp = { tokens[i - 1].Name, tokens[i].Name };if (tokens[i - 1].Code == 22){temp[0] = tt;}Next();AritExp();Emit(temp[1], temp[0], tt, NewTemp());tt = "T" + (ti - 1).ToString();}else{Before();return;}}else{return;}}#endregion#region项private void Item()Factor();if (error == ""){Next();if (tokens[i].Code == 25 || tokens[i].Code == 26){string[] temp = { tokens[i - 1].Name, tokens[i].Name };if (tokens[i - 1].Code == 22){temp[0] = tt;}Next();Item();Emit(temp[1], temp[0], tt, NewTemp());tt = "T" + (ti - 1).ToString();}else{Before();}}else{}}#endregion#region因子private void Factor(){if (tokens[i].Code == 21){Next();AritExp();Next();if (tokens[i].Code == 22){}else{error = "因子中算数表达式缺少)";}}else{CalQua();}}#endregion#region算数量private void CalQua(){if (tokens[i].Code == 18 || tokens[i].Code == 19 || tokens[i].Code == 20) {tt = tokens[i].Name;}else{error = "算数量出错";}}#endregion#region结构句private void StructSent(ref S s)if (tokens[i].Code == 2){Next();ComSent();}else if (tokens[i].Code == 8){Next();IfSent(ref s);}else if (tokens[i].Code == 17){Next();WhileSent(ref s);}}#endregion#region if语句private void IfSent(ref S s){E e = new E();BoolExp(ref e);if (error == ""){Next();if (tokens[i].Code == 14){int m1 = fps.Count;S s1 = new S();Next();ExecSent(ref s1);Next();if (tokens[i].Code == 5){S n = new S();n.next.Add(fps.Count);Emit("j", "_", "_", "-1");S s2 = new S();int m2 = fps.Count;Next();ExecSent(ref s2);s.next=s1.next;s.next.Concat(n.next);s.next.Concat(s2.next);foreach (int k in e.t){BackPatch(k, m1);}foreach (int k in e.f){BackPatch(k, m2);}}else{s.next=e.f;s.next.Concat(s1.next);foreach (int k in e.t){BackPatch(k, m1);}Before();}}{error = "if...then语句缺少then"; }}else{error = "if语句布尔表达式出错";}}#endregion#region while语句private void WhileSent(ref S s){int m1 = fps.Count;E e = new E();BoolExp(ref e);Next();if (tokens[i].Code == 4){int m2 = fps.Count;S s1 = new S();Next();ExecSent(ref s1);s.next = e.f;Emit("j", "_", "_", m1.ToString());foreach (int k in e.t){BackPatch(k, m2);}foreach (int k in s1.next){BackPatch(k, m1);…………………………3、运行结果。