编译原理实验1
- 格式:doc
- 大小:150.54 KB
- 文档页数:12
实验1简单的词法分析子程序【实验目的】●理解词法分析在编译程序中的作用●初步了解和掌握词法分析程序的实现方法和技术【实验内容】1. 编写程序,输入一串字符,判断该字符串是否为合法标识符或合法整型常量。
2. 无符号数的算术四则运算中的各类单词的识别。
输入:由无符号数、+、-、*、/、(、)构成的算术表达式。
输出:对识别出的每一单词均单行输出。
如,输入:8*2.5-1.0e2则,输出:8*2.5-1.0e2描述无符号数的确定的、最小化的状态转换图如图1所示。
其中编号1,2和6为终态,分别代表整数、小数和科学计数的识别结束状态。
图1 文法G[<无符号数>]的状态转换图实验2词法分析程序设计【实验目的】●理解词法分析中的正规式和自动机●掌握词法分析程序的实现方法和技术【实验内容】某一高级程序设计语言的部分语言子集定义如下:(1)关键字:for if then else while do(所有关键字都是小写)(2)运算符和分隔符:+ - * / : = <><= <>>= == ; ( ) #(3)其他标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter|digit)*NUM=digit·digit*(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM、运算符、分隔符和关键字,词法分析阶段通常被忽略。
各种词法单元对应的词法记号如下:编写程序,实现词法分析功能。
输入:源程序输出:二元组(词法记号,属性值/其在符号表中的位置)构成的序列。
例如:输入源程序x=5;if (x>0)thenx=2*x+1/3;elsex=2/x;#(# 表示输入结束)经词法分析后输出如下序列:(10,x)(18,=)(11,5)(26,;)(2,if)(27,()…说明:关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符,查关键字表。
编译原理实验指导书计算机学院实验1 词法分析程序一、实验目的构造simple语言的词法分析程序,程序要求能对输入的字符串流进行词法分析。
在实验的过程中,学会应用单词分析的方法——NFA(非确定有穷自动机)和DFA(确定有穷自动机),加深对词法分析原理的理解。
二、实验内容编写为任一正则文法(见实验参考(一)simple惯用的词法)构造非确定有穷自动机NFA并转换成确定有穷自动机DFA,并对任给的一个输入串(见实验参考(二)测试用输入串)进行词法分析的程序,程序的输出为单词的序列(见实验参考(三)程序输出形式)。
三、实验参考(一)simple 惯用的词法1. 下面是语言的关键字:Begin if then while do end所有的关键字都是保留字,并且必须是小写。
2. 下面是专用符号::= + * / < <= <> > >= = ; ( ) #3. 其他单词是标识符(ID)和整型常数(NUM),通过下列正规式定义:ID = letter(letter| digit)*NUM = digit digit*letter = a |…| z | A |…| Zdigit = 0 |…| 9小写和大写字母是有区别的。
思考:构造实数的正规表达式,力争实现对实数的识别及表示。
4. 空格由空白、换行符和制表符组成。
空格一般用来分隔ID、NUM、运算符和关键字,词法分析阶段通常被忽略。
5. 各种单词符号对应的种别码如下表所示:(二)词法分析程序的功能1. 输入为所给文法的源程序字符串。
2. 程序的输出形式为单词串的输出形式。
所输出的每一单词,均按形如(syn,token和sum)的二元式编码。
其中,syn 为单词种别码;token为存放的单词自身字符串;sum为整型常数。
3.测试源程序片断:begin x:=9; if x>0 then x:=2*x+1/3;end #。
实验1《词法分析程序设计与实现》实验学时: 2 实验地点:实验日期:一、实验目的加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。
二、实验内容自定义一种程序设计语言,或者选择已有的一种高级语言,编制它的词法分析程序。
词法分析程序的实现可以采用任何一种编程语言和编程工具。
从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符、界符。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)三、实验方法算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
主程序初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
四、实验步骤1.定义目标语言的可用符号表和构词规则;2.依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束;3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中;4.对不正确的单词,做出错误处理。
五、实验结果输入begin x:=9: if x>9 then x:=2*x+1/3; end #显示结果如下:六、实验结论该词法分析器可以进行输入、预处理;关键字的识别;标识符的识别、常数的识别、算符和界符的识别等。
《编译原理》(实验部分)实验1_程序预处理一、实验目的明确预处理子程序的任务,构造一个简单的预处理子程序,对源程序进行相应的预处理。
二、实验设备1、PC 兼容机一台;操作系统为WindowsWindowsXP。
2、Visual C++ 6.0 或以上版本, Windows 2000 或以上版本,汇编工具(在Software 子目录下)。
三、实验原理定义模拟的简单语言的词法构成,编制读入源程序和进行预处理的程序,要求将源程序读入到文件或存入数组中,再从文件或数组中逐个读取字符进行预处理,包括去掉注释、Tab、Enter和续行符等操作,并显示预处理后的程序。
四、实验步骤1、从键盘读入源程序存放到输入缓冲区中。
2、对源程序进行预处理,预处理后的程序存放到扫描缓冲区中。
3、显示预处理后的程序。
参考源程序(C++语言编写)//源程序的输入及预处理#include <fstream.h>#include <iostream.h>void pro_process(char *);void main( ) //测试驱动程序{//定义扫描缓冲区char buf[4048]={'\0'}; //缓冲区清0//调用预处理程序pro_process(buf); //在屏幕上显示扫描缓冲区的内容cout<<buf<<endl;}void pro_process(char *buf) //预处理程序{ifstream cinf("source.txt",ios::in);int i=0; //计数器char old_c='\0',cur_c; //前一个字符,当前字符。
bool in_comment=false; //false表示当前字符未处于注释中。
while(cinf.read(&cur_c,sizeof(char))){ //从文件读一个字符switch(in_comment){case false:if(old_c=='/' && cur_c=='*'){ //进入注释i--; //去除已存入扫描缓冲区的字符'/'in_comment=true;}else {if(old_c=='\\' && cur_c=='\n') //发现续行i--; //去除已存入扫描缓冲区的字符'\'else {if(cur_c>='A' && cur_c<='Z') //大写变小写cur_c+=32;if(cur_c =='\t' || cur_c =='\n')//空格取代TAB换行cur_c=' ';buf[i++]=cur_c ;}}break;case true:if(old_c=='*' && cur_c=='/') //离开注释in_comment=false;}//end of switchold_c= cur_c; //保留前一个字符}//end of whilebuf[i++]='#'; //在源程序尾部添加字符'#' }。
编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。
该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。
二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。
四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。
int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。
void GetChar(char *ch); //将下一个输入字符读到ch中。
void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。
void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。
int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。
void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。
编译原理实验报告实验一词法分析设计一、实验功能:1、对输入的txt文件内的内容进行词法分析:2、由文件流输入test.txt中的内容,对文件中的各类字符进行词法分析3、打印出分析后的结果;二、程序结构描述:(源代码见附录)1、分别利用k[],s1[],s2[],s3[]构造关键字表,分界符表,算术运算符表和关系运算符表。
2、bool isletter(){} 用来判断其是否为字母,是则返回true,否则返回false;bool isdigit(){} 用来判断其是否为数字,是则返回true,否则返回false;bool iscalcu(){} 用来判断是否为算术运算符,是则返回true,否则返回false;bool reserve(string a[]){} 用来判断某字符是否在上述四个表中,是则返回true,否则返回false;void concat(){} 用来连接字符串;void getn(){} 用来读取字符;void getb(){} 用来对空格进行处理;void retract(){}某些必要的退格处理;int analysis(){} 对一个单词的单词种别进行具体判断;在主函数中用switch决定输出。
三、实验结果四、实验总结词法分析器一眼看上去很复杂,但深入的去做就会发现并没有一开始想象的那么困难。
对于一个字符的种别和类型可以用bool函数来判断,对于关键字和标示符的识别(尤其是3b)则费了一番功夫,最后对于常数的小数点问题处理更是麻烦。
另外,这个实验要设定好时候退格,否则将会导致字符漏读甚至造成字符重复读取。
我认为,这个实验在程序实现上大体不算困难,但在细节的处理上则需要好好地下功夫去想,否则最后的程序很可能会出现看上去没有问题,但实际上漏洞百出的状况。
将学过的知识应用到实际中并不简单,只有自己不断尝试将知识转化成程序才能避免眼高手低,对于知识的理解也必将更加深刻。
实验二LL(1)分析法一、实验原理:1、写出LL(1)分析法的思想:当一个文法满足LL(1)条件时,我们就可以为它构造一个不带回溯的自上而下的分析程序,这个分析程序是有一组递归过程组成的,每个过程对应文法的一个非终结符。
编译原理实验报告某某:班级:学号:自评:中实验一词法分析程序实现一、实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。
二、实验内容根据教学要求并结合学生自己的兴趣和具体情况,从具有代表性的高级程序设计语言的各类典型单词中,选取一个适当大小的子集。
例如,可以完成无符号常数这一类典型单词的识别后,再完成一个尽可能兼顾到各种常数、关键字、标识符和各种运算符的扫描器的设计和实现。
输入:由符合或不符合所规定的单词类别结构的各类单词组成的源程序。
输出:把单词的字符形式的表示翻译成编译器的内部表示,即确定单词串的输出形式。
例如,所输出的每一单词均按形如(CLASS,V ALUE)的二元式编码。
对于变量和常数,CLASS字段为相应的类别码;V ALUE字段则是该标识符、常数的具体值或在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串;常数表登记项中则存放该常数的二进制形式)。
对于关键字和运算符,采用一词一类的编码形式;由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,V ALUE字段则为“空”。
另外,为便于查看由词法分析程序所输出的单词串,要求在CLASS字段上放置单词类别的助记符。
三、实现方法与环境词法分析是编译程序的第一个处理阶段,本次试验用手工的方式(C语言)构造词法分析程序。
根据文法和状态转换图直接编写词法分析程序。
四、基本实验题目1)题目1:试用手工编码方式构造识别以下给定单词的某一语言的词法分析程序。
语言中具有的单词包括五个有代表性的关键字begin、end、if、then、else;标识符;整型常数;六种关系运算符;一个赋值符和四个算术运算符。
参考实现方法简述如下。
单词的分类:构造上述语言中的各类单词符号及其分类码表。
表I 语言中的各类单词符号及其分类码表+ 15 PL- 16 MI* 17 MU/ 18 DI处理过程:在一个程序设计语言中,一般都含有若干类单词符号,为此首先为每类单词建立一X状态转换图,然后将这些状态转换图合并成一X统一的状态图,即得到了一个有限自动机,再进行必要的确定化和状态数最小化处理,最后据此构造词法分析程序。
03091337 李璐 03091339 宗婷婷一、上机题目:实现一个简单语言(CPL)的编译器(解释器)二、功能要求:接收以CPL编写的程序,对其进行词法分析、语法分析、语法制导翻译等,然后能够正确的执行程序。
三、试验目的1.加深编译原理基础知识的理解:词法分析、语法分析、语法制导翻译等2.加深相关基础知识的理解:数据结构、操作系统等3.提高编程能力4.锻炼独立思考和解决问题的能力四、题目说明1.数据类型:整型变量(常量),布尔变量(常量)取值范围{…, -2, -1, 0, 1, 2, …}, {true, false}2、运算表达式:简单的代数运算,布尔运算3、程序语句:赋值表达式,顺序语句,if-else语句,while语句五、环境配置1.安装Parser Generator、Visual C++;2.分别配置Parser Generator、Visual C++;3.使用Parser Generator创建一个工程编写l文件mylexer.l;编译mylexer.l,生成mylexer.h与mylexer.c;4.使用VC++创建Win32 Console Application工程并配置该项目;加入mylexer.h与mylexer.c,编译工程;执行标识符数字识别器;注意:每次修改l文件后,需要重新编译l文件,再重新编译VC工程六、设计思路及过程设计流程:词法分析LEX的此法分析部分主要利用有限状态机进行单词的识别,在分析该部分之前,首先应该对YACC的预定义文法进行解释。
在YACC中用%union扩充了yystype的内容,使其可以处理char型,int型,node型,其中Node即为定义的树形结点,其定义如下:typedef enum { TYPE_CONTENT, TYPE_INDEX, TYPE_OP } NodeEnum;/* 操作符 */typedef struct {int name; /* 操作符名称 */int num; /* 操作元个数 */struct NodeTag * node[1]; /* 操作元地址可扩展 */} OpNode;typedef struct NodeTag {NodeEnum type; /* 树结点类型 *//* Union 必须是最后一个成员 */union {int content; /* 内容 */int index; /* 索引 */OpNode op; /* 操作符对象 */};} Node;extern int Var[26];结点可以是三种类型(CONTENT,INDEX,OP)。
大学学生实验报告开课学院及实验室:年月日实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
针对表达各类词语的一组正规表达式,设计一个确定化的最简的有限自动机,对输入的符号串进行单词划分及词类识别。
实验容将词法分析器分解为以下几个部分:1.正规表达式的解析:将正规表达式中的符号分解为常量字符、正规表达式标识符和正规表达式运算符,然后基于正规表达式运算将正规表达式分解为更小的正规表达式(通过正规表达式运算符进行串接)。
2.正规表达式到NFA的转换:根据转换规则,基于正规表达式运算,将正规表达式转换为非确定有限自动机,并确定各类词的终止状态。
3.NFA的确定化:通过计算各状态的传递闭包,将NFA确定化,并确定各类词的终止状态。
4.最小化:通过子集法,求得最简的确定有限自动机,并确定各类词的终止状态。
例如:分析C语言子集的词法1)关键字main if else int return void while (都是小写)2)专用符号= + —* / < <= < >= = = != ;:,{ } [ ] ( )3)其他模式(正规表达式)STRING::=" [^"]*ID::=letter(letter|digit)*INT::=digit digit*letter::= a|…|z|A|…|Zdigit::= 0|…|94)空格由空白、制表符和换行符组成空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。
部分单词符号对应的种别码词法分析程序的功能输入:所给文法的源程序字符串输出:二元组(syn, token或sum)构成的序列。
其中syn 为单词种别码;token 为存放的单词自身字符串;sum为整型常量(作为常量的值)。
实现时,可将单词的二元组用结构进行处理代码:#include<iostream>#include<string.h>using namespace std;int main(){int i=0,j,k=0; //k判断是保留字还是idchar a[7][10] = {"main","if","else","int","return","void","while"};//保留字数组char s;char token[40] = {"\0"};cout<<"请输入字符"<<endl;s=getchar();while(s!=EOF){ //不是结束字符if(s==' '||s=='\n'||s=='\t'){ //过滤空格,换行s=getchar();}else if((s>='a'&&s<='z')||(s>='A'&&s<='Z')){//判断是id还是保留字token[i++]=s;s=getchar();while((s>='a'&&s<='z')||(s>='A'&&s<='Z')||(s>='0'&&s<='9')){//取接下来字符token[i++]=s;s=getchar();}for(j=0;j<7;j++){//判断是否为保留字if(strcmp(token,a[j])==0){cout<<j+1<<","<<token<<endl;k=1;break;}}if(k==0){//为idcout<<"10,"<<token<<endl;}memset(token,0,sizeof(token));//获取数组清零i=0;k=0;}else if(s>='0'&&s<='9'){//判断INTint flag=1;while(flag){token[i++]=s;s=getchar();if(!(s>='0'&&s<='9')){//不是数字flag=0;cout<<"20,"<<token<<endl;memset(token,0,sizeof(token));i=0;}}}else if(s=='='){//判断=s=getchar();if(s=='='){cout<<"39,=="<<endl;s=getchar();} else{cout<<"21,="<<endl;}}else if(s=='+'){//判断+cout<<"22,"<<s<<endl;s=getchar();}else if(s=='-'){//判断-cout<<"23,"<<s<<endl;s=getchar();}else if(s=='*'){//判断*cout<<"24,"<<s<<endl;s=getchar();}else if(s=='/'){//判断/cout<<"25,"<<s<<endl;s=getchar();}else if(s=='('){//判断(cout<<"26,"<<s<<endl;s=getchar();}else if(s==')'){//判断)cout<<"27,"<<s<<endl;s=getchar();}else if(s=='['){//判断[cout<<"28,"<<s<<endl;s=getchar();}else if(s==']'){//判断]cout<<"29,"<<s<<endl;s=getchar();}else if(s=='{'){//判断{cout<<"30,"<<s<<endl;s=getchar();}else if(s=='}'){//判断}cout<<"31,"<<s<<endl;s=getchar();}else if(s==','){//判断,cout<<"32,"<<s<<endl;s=getchar();}else if(s==':'){//判断:cout<<"33,"<<s<<endl;s=getchar();}else if(s==';'){//判断;cout<<"34,"<<s<<endl;s=getchar();}else if(s=='>'){//判断>或>=s=getchar();if(s=='='){cout<<"37,>="<<endl;s=getchar();} else{cout<<"35,>"<<endl;} }else if(s=='<'){//判断<或<=s=getchar();if(s=='='){cout<<"38,<="<<endl;s=getchar();} else{cout<<"36,<"<<endl;} }else if(s=='!'){s=getchar();if(s=='='){cout<<"40,!="<<endl;s=getchar();}}}}试验结果:。