编译原理实验1
编译原理实验一:Chomsky文法类型

编译原理实验报告实验名称Chomsky文法类型判断实验时间2013年10月29日院系计算机科学与电子技术系班级11计算机软件学号JV114001 JV114095 JP114065姓名唐茹韩强强徐思维1.试验目的:1.熟练掌握四种文法类型的概念及区别。
2.设计一个Chomsky文法类型判别器,判断0型、1型、2型和3型文法。
2.实验原理:1.设G=(Vn,Vt,P,S),如果它的每个产生式α->β是这样一种结构:α∈(Vn∪Vt)*且至少含有一个非终结符,而β∈(Vn∪Vt)*,则G 是一个0型文法。
2.设G=(Vn,Vt,P,S)为一文法,若P中的每一个产生式α->β均满足|β|>=|α|,仅仅S->ԑ除外,则文法G是1型或上下文有关的。
3.设G=(Vn,Vt,P,S)为一文法,若P中的每一个产生式α->β均满足:α是一个非终结符,β∈(Vn∪Vt)*,则此文法称为2型的或上下文无关的。
4. 设G=(Vn,Vt,P,S)为一文法,若P中的每一个产生式的形式都是A->aB或A->a,其中A和B都是非终结符,a∈Vt*,则G是3型文法或正规文法。
5.4个文法类的定义是逐渐增加限制的,因此可采用自顶向下的算法。
3.实验内容:1.程序清单如下:#include "stdafx.h"#include<iostream>#include<string>using namespace std;typedef struct CSS //定义一个产生式结构体{string left; //定义产生式的左部string right; //定义产生式的右部}CSS;bool Zero(CSS *p,int n) //判断0型文法{int i,j;for(i=0;i<n;i++) //循环n次,即遍历所有产生式{for(j=0;j<p[i].left.length();j++) //遍历产生式左部每一个字符{if(p[i].left[j]>='A'&&p[i].left[j]<='Z') //判断字符是否是非终结符 break;}if(j==p[i].left.length()){cout<<"该文法不是0型文法"<<endl;return 0;break;}}if(i==n)return 1;//如果每个产生时都能找到非终结符}bool First(CSS *p,int n) //判断1型文法{int i;if(Zero(p,n)) //先判断是否是0型文法{for(i=0;i<n;i++){if((p[i].left.length()>p[i].right.length())&&p[i].right.length()!=NULL) //判断产生式左部长度是否大于右部break;}if(i==n)return 1;else{cout<<"该文法是0型文法"<<endl;return 0;}}elsereturn 0;}bool Second(CSS *p,int n) //判断2型文法{int i;if(First(p,n)) //同上,先判断低级文法是否成立{for(i=0;i<n;i++) //同上,遍历所有文法产生式{if((p[i].left.length()!=1)|| !(p[i].left[0]>='A'&&p[i].left[0]<='Z')) //判断产生式左部长度是否为一,左部第一个是否是非终结符break;}if(i==n)return 1;else{cout<<"该文法是1型文法"<<endl;return 0;}}elsereturn 0;}void Third(CSS *p,int n) //判断3型文法{int i;if(Second(p,n)) //同上,先判断是否是2型文法{for(i=0;i<n;i++) //同上,遍历文法所有的产生式{if((p[i].right.length()==0)||(p[i].right.length()>=3)||(p[i].right[0]>='A'& &p[i].right[0]<='Z')) //判断产生式右部字符个数是否在12之间,判断右部第一个字符是否是非终结符break;}if(i==n){for(i=0;i<n;i++){if(p[i].right.length()==2){if(!(p[i].right[1]>='A'&&p[i].right[1]<='Z'))break;}}if(i==n){cout<<"该文法属于3型文法"<<endl;}elsecout<<"该文法属于2型文法"<<endl;}else cout<<"该文法属于2型文法"<<endl;}elsecout<<"结束"<<endl;}void main( ){int i,j,n;string input;cout<<"请输入文法产生式个数N:";cin>>n;CSS *p=new CSS[n]; // 初始化产生式数组for(i=0;i<n;i++) //输入产生式数组{input.erase(); //清除cin>>input; //输入for(j=0;j<input.length();j++)//改变输入数据的形式{if(input[j]=='-'){p[i].left=input.substr(0,j);p[i].right=input.substr(j+2,input.length());}}}Third(p,n); //调用文法类型判断,自顶向下system("pause");}2.程序运行结果:测试用例1:7S->aSBES->aBEEB->BaB->abbB->bbbE->beeE->ee运行结果:测试用例2:1型文法:7S->aSBES->aBEEB->BEaB->abbB->bbbE->beeE->ee运行结果:测试用例3:2型文法:9S->aABA->bBS->bBB->bBS->aB->bA->aAB->aA->aS运行结果:测试用例4:3型文法:9S->aAA->bBS->bBB->bBS->aB->bA->aAB->aA->aS运行结果见下页:4.实验心得:通过Chomsky文法类型判断实验的实际操作,知道和理解了该理论在计算机中是怎样执行的,对该理论在实践中的应用有深刻的理解。
编译原理实验指导书

编译原理实验指导书计算机学院实验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

实验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.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。
2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。
3.通过完成词法分析程序,了解词法分析的过程。
【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。
【实验流程图】【实验步骤】1.提取pl/0文件中基本字的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE];int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {printf("%s\t",wsym[m]);m=14;n=k+1;} }2.提取pl/0文件中标识符的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE]=" ";int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {m=14;n=k+1;}}if(m==13) for(m=0;a[m]!=NULL;m++) printf("%c ",a[m]);3.提取pl/0文件中常数的源代码while((ch=fgetc(stream))!='.'){while(ch>='0' && ch<='9'){num=10*num+ch-'0';ch=fgetc(stream);}if(num!=0) printf("%d ",num);num=0;}4.提取pl/0文件中运算符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case'+': printf("+ ");break;case'-': printf("- ");break;case'*': printf("* ");break;case'/': printf("/ ");break;case'>': if(fgetc(stream)=='=')printf(">= "); else printf("> ");break;case'<': if(fgetc(stream)=='=')printf("<= "); else printf("< ");break;case':': printf(":= ");break;case'#': printf("# ");break;case'=': printf("= ");break;default: break;}ch=fgetc(stream);5.提取pl/0文件中界符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case',': printf(", ");break;case';': printf("; ");break;case'(': printf("( ");break;case')': printf(") ");break;default: break;}ch=fgetc(stream);}【实验结果】1.pl/0文件(222.txt)内容const a=10;var b,c;procedure p;beginc:=b+a;end;beginread(b);while b#0 dobegincall p;write(2*c);read(b)endend .2.实验运行结果【实验小结】1.了解程序在运行过程中对词法分析,识别一个个字符并组合成相应的单词,是机器能过明白程序,定义各种关键字,界符。
编译原理—实验指导书-1

4.词法分析器的功能和输出格式
词法分析器的功能是输入以字符串表示的源程序,从左向右扫描每行源程序的符号,拼成单词,换成统一的二元式(单词种别码,单词符号的属性值)表示。对给定的程序通过词法分析器识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示,本程序是通过对给定路径的文件的分析后以单词符号和文字提示显示),本实验中,采用单词种别码是一符一种种别码的方式。
(4)var
(5)a,b,c:integer;
(6)x:char;
(7)begin
(8)if(a+c*3>b)and(b>3)thenc:=3;
(9)x:=2+(3*a)-b*c*8;
(10)forx:=1+2to3dob:=100;
(11)whilea>bdoc:=5;
(12)repeata:=10;untila>b;
(124){
(125)printf("%s\t$运算符\n\n",Word);
(126)}
(127)else if(ch=='-')
(128){
(129)printf("%s\t$运算符\n\n",Word); //判断结果为“--”
(2)设计描述Sample语言各类单词结构的状态转换图(即有限自动机FA);
如标识符的状态转换图可以用下图表示
其相应代码科为
(1)recog_id(char ch)
(2){
(3)char state='0';
(4)while(state!='2')
(5){
(6)switch(state)
《编译原理(实验部分)》实验1_程序预处理

《编译原理》(实验部分)实验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置为空白字符。
《编译原理》实验报告

ch2=='e'||ch2=='$' )
zf=1; elsh
zf=0; } if(ch1=='e'){ if(ch2>='0' && ch2<='9' && h<=1||ch2=='+'||ch2=='-')
zf=1; else zf=0; } if(ch1=='+' || ch1=='-'){
if(i==0) break; if(ch2>='0' && ch2<='9'||ch2=='$') zf=1; else zf=0; } if (zf==0) break; else i++; } if(zf==0) printf("Input number are error!\n"); else printf("Input number are right!\n"); }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告学院(系)名称:计算机与通信工程学院
【实验过程记录(源程序、测试用例、测试结果及心得体会等)】
一、程序思路分析:
1、通过void Fun(FILE *file)分析,从file文件中读取一个字符c,否则
判断c是否是运算符,如果是的话,则输出c是运算符,否则
判断c是否为字母,如果是,用while判断判断是否是字母开头的字母数字下划线构成的字符串,如果是,判断这个字符串是否是已列出的保留字,否则是标识符。
判断c是否是数字,如果是,判断以c开头的数字常数
否则c是界符。
2、主函数中:写一个txt的文本文件,打开fp = fopen("e:\zyx.txt", "rw");
判断文本文件是否为空,如果是,输出打开源文件错误,
如果文本文件不为空,用Fun对它进行词法分析,
最后关闭文本文件fclose(fp);
二、源代码:
#include <stdio.h>
#include <string.h>
#define MAX 35
#define KEY 30 //保留字个数
#define OPERATORS 11 //运算符个数
#define BOUNDARY 6 //界符个数
char key[30][MAX]={ //保留字
"if","else","switch","case","break","continue","do","while"
"char","float","int","long","short","double",
"for","goto","default", "enum", "const","void",
"register","return","signed","sizeof","static",
"struct","typedef","union","unsigned","volatile",
};
//运算符
char operators[11][MAX]={"+","-","*","/","%",">","<","=","!=","<=",">="};
//界符
char boundary[6][MAX]={"," , ";" ,"(" ,")", "{" , "}" };
int isLetter(char c) //判断输入的字符是否为字母
{
if(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z')))//参照ASSIC码
return 1;
return 0;
}
int isDigit(char c) //判断输入的字符是否为数字
{
if(c>='0'&&c<='9')
return 1;
return 0;
}
char *concatenation(char *token,char c) //将c和token字符串连接并作为一个新的token { //token:字符数组,存放构成单词符号的字符串
strcat(token,&c);
return token;
}
int isKey(char *token) //判断输入字符是否是关键字
{
int i=0;
for (i = 0; i < KEY; i++)
{
if ( strcmp(token, key[i])==0)
return 1;
}
return 0;
}
int isBoundary(char ch) //判断输入字符是否是界符
{
int i=0;
for (i = 0; i < BOUNDARY; i++)
{
int flag;
if ( 0 == strcmp(&ch, boundary[i]) )
{
flag=i+1;
return flag;
}
}
return 0;
}
//判断是否是运算符,是返回数组下标,不是返回0
int isOperators(char ch)
{
int flag;
int i=0;
for (i = 0; i < OPERATORS; i++)
{
if ( 0 == strcmp(&ch, operators[i]) )
{
flag=i+1;
return flag;
}
}
return 0;
}
void Fun(FILE *file) //词法分析函数
{
char token[MAX];
char c;
while( (c = fgetc(file)) != EOF )
{
//将字符串清空
memset(token, 0, MAX);
if ( (c == '\t') || (c == '\n') || (c == ' ') )
{
}
else if (isOperators(c))
{
printf("%c ----运算符\n",c);
}
else if ( isLetter(c) )
{
//判断是否是字母开头的字母数字下划线构成的字符串
while ( isLetter(c) || isDigit(c)||c=='_' )
{
concatenation(token, c);
c = fgetc(file);
}
fseek(file, -1L, SEEK_CUR); //让文件流指针后退一个字节
if ( isKey(token) ) //判断是否为关键字
{
printf("%s -----关键字\n", token);
}
else
printf("%s ----标识符\n", token);
}
else if ( isDigit(c) )
{
while ( isDigit(c) )
{
concatenation(token, c);
c = fgetc(file);
}
fseek(file, -1L, SEEK_CUR); //让文件流指针后退一个字节
printf("%s ----属性值\n", token);
}
else if (isBoundary(c))
{
printf("%c ----界符\n",c);
}
else
{
// printf("输入错误\n");
}
}
}
int main()
{
FILE *fp;
freopen("e:\jieguo.txt","w",stdout); //将结果输出到指定路径下的文件中fp = fopen("e:\zyx.txt", "rw");
if (fp== NULL)
{
printf("请检查是否有该文件\n");
return 1;
}
Fun(fp);
fclose(fp);
fclose(stdout);
return 0;
}
三、实验结果:
……
结果已经保存在文件中。
四、程序中代码分析:测试用例:
E:\zyx.txt
五、心得体会
通过做这个实验,对词法分析有了更加深刻的理解,但程序中仍存在一些不足之处,在分析常数事,只判断出了一个数是常数,并没有判断出这个常数具体是整数还是小数;还有,对于文本文件中的类似于“#”,“””,“\n”这些都没有做出判断。