编译原理实验4算符优先算法

编译原理实验4算符优先算法
编译原理实验4算符优先算法

一、实验目的与任务

算术表达式和赋值语句的文法可以是(你可以根据需要适当改变):

S→i=E

E→E+E|E-E|E*E|E/E|(E)|i

根据算符优先分析法,将赋值语句进行语法分析,翻译成等价的一组基本操作,每一基本操作用四元式表示。

二、实验涉及的相关知识点

算符的优先顺序。

三、实验内容与过程

如参考C语言的运算符。输入如下表达式(以分号为结束):(1)a = 10;

(2)b = a + 20;

注:此例可以进行优化后输出(不作要求):(+,b,a,20)

(3)c=(1+2)/3+4-(5+6/7);

四、实验结果及分析

(1)输出:(=, a,10,-)

(2)输出:(=,r1,20,-)

(+,r2,a,r1)

(=,b,r2,-)

(3)输出:(+,r1,1,2) (/,r2,r1,3) (/,r3,6,7) (+,r4,5,r3,) (+,r5,r2,4) (-,r6,r5,r4) (=,c,r6,-)

五、实验有关附件(如程序、附图、参考资料,等)

//程序功能:

//根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确。

//文法:E→E+E|E-E|E*E|E/E|(E)|i

// 其中i为无符号整数

//

//例:

//输入:10;

//输出:正确

//输入:1+2;

//输出:正确

//输入:(1+2)/3+4-(5+6/7);

//输出:正确

//输入:((1-2)/3+4;

//输出:错误

//

//输入测试数据保存在同目录的文本文件testin.txt中,保存格式:

// 表达式行;

// 表达式行;

// .....

//预期的输出保存在同目录的文本文件testout.txt中,保存格式:

// 表达式行;

// 正确/错误

// 表达式行;

// 正确/错误

// .....

/////////////////////////////////////////////////////////////////

#include "stdio.h"

#include "stdlib.h"

#define TRUE 1

#define FALSE 0

//文件信息:

#define TESTIN_FILENAME "testin.txt"

#define TESTOUT_FILENAME "testout.txt"

FILE * fTestIn;

FILE * fTestOut; //打开文件后的柄

//运算符定义:

#define O_NUMBER 8 //运算符个数,+-*/()i# #define O_PLUS 0 // 加+

#define O_MINUS 1 // 减-

#define O_TIMES 2 // 乘*

#define O_SLASH 3 // 除/

#define O_L_PAREN 4 //左括号(parenthesis)

#define O_R_PAREN 5 //右括号

#define O_IDENT 6 //标识符

#define O_NUL 7 //语法界符#

//表达式缓冲区:由专门函数操作(ReadFormula(),GetChar())#define BUFFER_SIZE 1000 //表达式缓冲区大小

char Buffer[BUFFER_SIZE]; //表达式缓冲区,以'\0'表示结束int ipBuffer = 0; //表达式缓冲区当前位置序号

//算符优先关系表:

char O_Table[O_NUMBER][O_NUMBER] = {

{'>','>','<','<','<','>','<','>'},

{'>','>','<','<','<','>','<','>'},

{'>','>','>','>','<','>','<','>'},

{'>','>','>','>','<','>','<','>'},

{'<','<','<','<','<','=','<','-'},

{'>','>','>','>','-','>','-','>'},

{'>','>','>','>','-','>','-','>'},

{'<','<','<','<','<','-','<','='}

}; //优先关系表:八个字符分别是+-*/()i#,其中'-'表示出错

//文法:

#define OG_NUMBER 6 //文法个数

char OG[OG_NUMBER][4] = {"E+E","E-E","E*E","E/E","(E)","i"}; //文法右部

//单词序列存放格式定义:

#define TOKEN_MAX_LENTH 100 //最大的单词长度+1

typedef struct

{

char ch; //存放字符:+-*/()i#E

int No; //存放算符优先关系表中的序号

//double Value; //当ch==i时,且为数值时,存放值的大小} SToken;

#define MAX_TOKEN_NUMBER 1000 //在一个表达式中允许最大的单词个数SToken Token[MAX_TOKEN_NUMBER]; //单词序列,最后一个以“#”结束

int TokenNumber = 0; //单词序列中包含的单词个数

int ipToken = 0; //进行“移进-规约”时的位置指示

//堆栈:由专门的函数操作(PopUp(),Push(),…)

#define STACK_MAX_SIZE 1000 //堆栈最大存储量

SToken Stack[STACK_MAX_SIZE]; //堆栈

int ipStack = 0; //堆栈指针,指向栈顶(下一个空位置)

//词法分析专用全局变量:

char ch; //存放取得的一个字符

//char AToken[TOKEN_MAX_LENTH]; //存放组成的单词,存放时以\0为结束

//int ipAToken; //用于读字符时,指向下一个AToken[]的位置,便于组成单词

//错误信息:

char * ErrMsg; //出错信息

//函数声明:

bool Judge(); //利用算符优先关系表判断单词序列是否正确

int GuiYue(); //规约,并判断是否完成

bool IsOK(); //判断规约是否全部完成

bool GuiYueN(int n); //将堆栈中0~n单词规约

int FindPriorOp(int Begin); //在堆栈中,从Begin开始,查找前一个终结符位置

int MoveIn(); //移进,并判断是否需要规约

void JudgeInit(); //(利用算符优先关系表判断单词序列是否正确)判断前的初始化SToken Peek(int n); //窥视堆栈

bool PopUp(int n); //弹出堆栈

void PushToken(char ch, int O_No); //压栈(以字符形式)

void Push(SToken Token); //压栈

bool Init(); //全局初始化

void End(); //程序退出前作善后处理

void OutPut(char * Formula, char * Result); //将结果输出到文件

bool ReadFormula(); //从文件中读出一个表达式存于表达式缓冲区Buffer[]中,以'\0'结束,并置ipBuffer=0;

bool ChangeToTokens(); //将表达式分割成单词序列

char GetFirstChar(); //从表达式缓冲区中取到下面第一个非空字符

char GetChar(); //从表达式缓冲区取一个字符,返回该字符的同时将它存于全局变量ch中

bool MakeErr(char * ErrMassage); //生成错误信息,错误信息存于全局变量ErrMsg 中

///////////////////////////////////////

void main()

{

if(! Init()) //初始化

{

printf("初始化失败!程序不能继续。错误信息如下:

\n%s\n",ErrMsg);

exit(0);

}

while(ReadFormula()) //从文件中读表达式成功

{

if(ChangeToTokens()) //将表达式分割成单词序列

{

if(Judge()) //利用算符优先关系表判断表达式(单词序列)是否正确

OutPut(Buffer,"正确!");

else

OutPut(Buffer,ErrMsg); //输出错误信息

}

else //出错

{

OutPut(Buffer,ErrMsg); //输出错误信息

}

}

End(); //程序退出前作善后处理

}

//利用算符优先关系表判断单词序列是否正确

//返回:TRUE正确;FALSE错误,且错误信息存于ErrMsg

//本函数的实现思路:

// 将单词序列进行“移进-规约”操作,最后判断是否能全部完成

// 使用到:堆栈(SToken Stack[])、文法(char OG[][])、算符优先关系表(char O_Table[][])等

bool Judge()

{

JudgeInit();

PushToken('#',O_NUL); //将“#”号置栈底

while(TRUE) //进行“移进-规约”操作

{

switch(MoveIn())

{

case 1: //需要规约

switch(GuiYue())//规约

{

case 1: //这一步规约成功

break;

case 2: //规约全部完成

return TRUE;

default: //出错

ErrMsg = "规约错误。";

return FALSE;

}

break;

case 2: //需要继续移进

break;

default: //出错

return FALSE;

}

}

}

//规约,并判断是否完成

//返回:-1出错,1这一步规约成功,2规约全部完成

int GuiYue()

{

int n0,n;

char r; //存优先关系

n = FindPriorOp(-1); //取得堆栈中第一个终结符

if(Peek(n).ch == '#') //出错或全部结束

{

if(IsOK())

return 2;

else

return -1;

}

while(TRUE)

{

n0 = n;

n = FindPriorOp(n0); //前一个终结符的堆栈位置

if(n - n0 > 2) //出错(多个非终结符相邻)

return -1;

r = O_Table[Peek(n).No][Peek(n0).No];

if(r == '<') //寻找结束

{

if(! GuiYueN(n - 1)) //规约(从前一个后的字符开始)规约失败

return -1;

else //规约成功,还要判断是否全部完成

{

if(IsOK())

return 2; //规约全部完成

else

return 1; //这一步规约成功

}

}

else if(r == '=') //继续向前找

{

continue;

}

else //出错(r为>或没有关系)

return -1;

}

}

//判断规约是否全部完成

//返回:TRUE全部完成;FALSE没有完成

bool IsOK()

{

//if(Peek(1) == NULL) return FALSE;

if(Peek(0).ch == 'E'&& Peek(1).ch == '#' && Token[ipToken].ch == '#') return TRUE;

else

return FALSE;

}

//返回:TRUE成功,FALSE失败

bool GuiYueN(int n) //将堆栈中0~n单词规约

{

int i,j;

bool k;

for(i=0;i

{

for(j=n,k=FALSE;j>=0;j--)

{

if(OG[i][n-j] != Peek(j).ch)

{

k = TRUE; //TRUE表示规约串和文法右部不符,

break;

}

}

if(k) continue;

//k==FALSE表示规约串判断完成

if(OG[i][n+1]=='\0') //文法也判断完成,匹配成功

{

PopUp(n + 1); //弹出规约串

PushToken('E',O_IDENT); //压入左部“E”

return TRUE;

}

}

return FALSE;

}

//在堆栈中,从Begin开始,查找前一个终结符位置

//如果从开始找,让 Begin = -1

int FindPriorOp(int Begin)

{

int n;

n = Begin + 1;

while(Peek(n).ch == 'E')

{

n ++;

}

return n;

}

//移进,并判断是否需要规约

//返回:-1出错,1需要规约,2可继续移进

// 1.单词结束(遇到“#”号),无法移进,需要规约,返回:1

// 2.单词没有结束,需判断是否可以移进

// 2-1.堆栈单词<=单词:移进后返回:2

// 2-2.堆栈单词>单词:不能移进,需要规约,返回:1

// 2-3.两单词没有优先关系:出错,返回:-1

int MoveIn()

{

SToken s,t; //分别存堆栈顶单词和单词序列的第一个单词

char r; //存放优先关系

s = Peek(FindPriorOp(-1)); //取得堆栈中第一个终结符位置

t = Token[ipToken];

r = O_Table[s.No][t.No];

if(t.ch == '#') //单词结束,无法移进,需要规约

return 1;

else //单词没有结束,需判断是否可以移进

{

if(r == '<' || r == '=') //需要移进

{

Push(t);

ipToken ++;

return 2;

}

else if(r == '>') //不能移进,需要规约

return 1;

else //没有优先关系,出错

{

MakeErr("移进时出现两个没有优先关系的相邻单词。");

return -1;

}

}

}

//(利用算符优先关系表判断单词序列是否正确)判断前的初始化

//由于多个表达式需要依次判断,因此对每个表达式判断前都需要初始化

void JudgeInit()

{

ipStack = 0; //堆栈初始化(如果有专门的StackClear()函数则更好)

ipToken = 0; //指向首个单词

}

//窥视堆栈

//参数:n相对栈顶的位置(0开始)

//成功返回:返回单词

//不成功返回:NULL

SToken Peek(int n)

{

SToken Token;

if(n > 0 || n < ipStack)

Token = Stack[ipStack - n - 1];

else if(n < 0)

Token = Stack[ipStack - 1];

else

Token = Stack[0];

return Token;

}

//弹出堆栈

//参数:n弹出单词个数(不能全部弹空,即保留#号)

//不成功返回:FALSE

//成功返回:TRUE

bool PopUp(int n)

{

if(ipStack < 2) return FALSE; //只剩0个或1个

if(n > ipStack - 1) n = ipStack - 1;

ipStack -= n;

return TRUE;

}

//压栈(以字符形式)

//参数:ch是要压栈的字符(+-*/()i#E 之一),O_No运算符序号//调用:Push()

void PushToken(char ch, int O_No)

{

SToken Token;

Token.ch = ch;

Token.No = O_No;

Push(Token);

}

//压栈

//参数:Token是要压栈的SToken结构体类型的单词

//缺点:没有判断堆栈是否满

void Push(SToken Token)

{

Stack[ipStack ++] = Token;

}

//全局初始化

//成功:返回TRUE;失败:返回FALSE

bool Init()

{

//if((fTestIn = fopen(TESTIN_FILENAME, "r")) = NULL) return ! MakeErr("不能打开测试文件!");

//if((fTestOut = fopen(TESTOUT_FILENAME, "w")) = NULL) return ! MakeErr("不能打开结果输出文件!");

fTestIn = fopen(TESTIN_FILENAME, "r");

fTestOut = fopen(TESTOUT_FILENAME, "w");

return TRUE;

}

//程序退出前作善后处理

//主要是关闭文件等

void End()

{

fclose(fTestIn);

fclose(fTestOut);

}

//将结果输出到文件

//要求文件事先以追加方式打开,文件指针为fTestOut

//参数:Formula表达式内容,Result判断结果

void OutPut(char * Formula, char * Result)

{

fprintf(fTestOut,"%s\n%s\n",Formula,Result);

}

//从文件中读出一个表达式存于表达式缓冲区Buffer[]中,以'\0'结束,并置

ipBuffer=0;

//需要先打开文件,文件指针存于fTestIn

//读出非空表达式:返回 TRUE;文件结束:返回 FALSE

bool ReadFormula()

{

int n = 0;

bool k = FALSE; //当 k==TRUE 时表示文件结束,否则文件没有结束

while(TRUE)

{

if((Buffer[n] = fgetc(fTestIn)) != EOF) //读出一个字符成功

{

if(Buffer[n] == ';') break;

n ++;

}

else //文件结束

{

k = TRUE;

break;

}

}

Buffer[n] = '\0'; //最后一个字符用结束标记'\0'代替

ipBuffer = 0; //初始化缓冲区指针

if(n > 0) //读出的数据非空,返回成功

return TRUE;

else //读出的数据为空,需要判断文件结束,还是只有';'的空表达式

{

if(k) //文件结束

return FALSE;

else //空表达式,文件没有结束,让它继续读下一个表达式

return ReadFormula();

}

}

//将表达式分割成单词序列

//结果:单词序列存于SToken Token[]中,单词个数存于TokenNumber中

//这是一个大模块,其中要调用一些子函数

//本函数只识别:运算符+-*/、括号()、无符号整数i,并在末尾添加#号

// 遇到其它任何字符都返回错误信息

//返回:TRUE表示成功;FALSE表示失败,同时将错误信息存于全局变量ErrMsg中

//使用到的其他全局变量:ch(取一个字符)、AToken[](取到的单词)

bool ChangeToTokens()

{

TokenNumber = 0;

if(GetFirstChar() == '\0') return ! MakeErr("表达式为空。");

while(TRUE) //对缓冲区进行循环读

{

if(ch <= 32 && ch > 0) GetFirstChar(); //滤去空格

switch(ch) //对单词的第一个进行判断,在下面一次处理整个单词

{

case '\0':

Token[TokenNumber].ch = '#';

Token[TokenNumber].No = O_NUL;

return TRUE; //处理结束

case '+':

Token[TokenNumber].ch = '+';

Token[TokenNumber].No = O_PLUS;

GetChar();

break;

case '-':

Token[TokenNumber].ch = '-';

Token[TokenNumber].No = O_MINUS;

GetChar();

break;

case '*':

Token[TokenNumber].ch = '*';

Token[TokenNumber].No = O_TIMES;

GetChar();

break;

case '/':

Token[TokenNumber].ch = '/';

Token[TokenNumber].No = O_SLASH;

GetChar();

break;

case '(':

Token[TokenNumber].ch = '(';

Token[TokenNumber].No = O_L_PAREN;

GetChar();

break;

case ')':

Token[TokenNumber].ch = ')';

Token[TokenNumber].No = O_R_PAREN;

GetChar();

break;

default:

if(ch >= '0' && ch <= '9') //整数

{

while(GetChar()>0)

{

if(ch < '0' || ch > '9') break;

}

Token[TokenNumber].ch = 'i';

Token[TokenNumber].No = O_IDENT;

}

else

{

return ! MakeErr("表达式中含有非法字符。");

}

break;

}

TokenNumber ++;

}

}

//从表达式缓冲区中取到下面第一个非空字符

//成功:返回字符;不成功:返回'\0'

char GetFirstChar()

{

while(GetChar() != '\0')

{

if(ch>32) return ch;

}

return '\0';

}

//从表达式缓冲区取一个字符,返回该字符的同时将它存于全局变量ch中//成功:返回字符;不成功:返回'\0'

char GetChar()

{

if((ch = Buffer[ipBuffer]) != '\0')

ipBuffer ++;

return ch;

}

//生成错误信息

//错误信息存于全局变量ErrMsg中

//返回:TRUE

bool MakeErr(char * ErrMassage)

{

ErrMsg = ErrMassage;

return TRUE;

}

编译原理实验报告四

编译原理实验报告 题目表达式语法分析程序的构造学院 专业 班级 学号 学生姓名 指导教师 西安思源学院教务处制 二〇一年

实验四表达式语法分析程序的构造 一、实验目的 1 掌握C++语言编译的语法分析程序 2 分别掌握LL(1)、算符优先、LR等语法分析方法的构造。 二、实验环境 Microsoft Visual C++ 6.0 三、实验内容 给定某一文法,试构造其简单优先矩阵(或LL(1)矩阵),并编制程序。给出相应句子的语法分析过程,判其正确性。 例如:给定文法G: E→T E1 E1→+TE1/ε T→FT1 T1→*F/ε F→id/(E) (1)先构造其SELECT集合,判定其是否为LL(1)文法 (2)是则构造其分析表 (3)给出句子id+id*id$的语法分析过程 四、设计说明 LL(1): #include #include typedef int datatype; char a[N3]={'$','E'}; char c[N4]={'$','z','*','z','+','z'}; char *B[N1][N2]={ " ", "z ", "+ " , "*" , "(" , ")", "$ ", "E " , "xT", " " , " ", "xT", " ", " ", "x ", " ", "xT+", " ", " ", "", "", "T ", "yF", " ", " ", "yF ", " ", " ", "y ", " ", "", "yF*", " ", "" , "", "F ", "z", " ", " ", ")E(", " ", " ", }; void FXB() { int i,j; cout<<"分析表为: "<

编译原理课程设计报告_算符优先分析法

编译原理课程设计报告_算符优先分析法 编译原理课程设计报告 选题名称: 算符优先分析法 系(院): 计算机工程学院 专业: 计算机科学与技术 班级: 姓名: 学号: 指导教师: 学年学期: 7>2012 ~ 2013 学年第 1 学期 2012年 12 月 04 日 设计任务书 课题名称算符优先分析法 设计 目的 通过一周的课程设计,对算符优先分析法有深刻的理解,达到巩固理论知识、锻炼实践能力、构建合理知识结构的目的。实验环境Windows2000以上操作系统,Visual C++6.0编译环境 任务要求 1.判断文法是否为算符优先文法,对相应文法字符串进行算符优先分析; 2.编写代码,实现算符优先文法判断和相应文法字符串的算符优先分析; 3.撰写课程设计报告; 4提交报告。工作进度计划序号起止日期工作内容 1 理论辅导,搜集资料 2 ~编写代码,上机调试

3 撰写课程设计报告 4 提交报告 指导教师(签章): 年月日 摘要: 编译原理是计算机专业重要的一门专业基础课程,内容庞大,涉及面广,知识点多。本次课程设计的目的正是基于此,力求为学生提供一个理论联系实际的机会,通过布置一定难度的课题,要求学生独立完成。我们这次课程设计的主要任务是编程实现对输入合法的算符优先文法的相应的字符串进行算符优先分析,并输出算符优先分析的过程。算符优先分析法特别有利于表达式的处理,宜于手工实现。算符优先分析过程是自下而上的归约过程,但这种归约未必是严格的规范归约。而在整个归约过程中,起决定作用的是相继连个终结符之间的优先关系。因此,所谓算符优先分析法就是定义算符之间的某种优先关系,并借助这种关系寻找句型的最左素短语进行归约。通过实践,建立系统设计的整体思想,锻炼编写程序、调试程序的能力,学习文档编写规范,培养独立学习、吸取他人经验、探索前言知识的习惯,树立团队协作精神。同时,课程设计可以充分弥补课堂教学及普通实验中知识深度与广度有限的缺陷。 关键字:编译原理;归约;算符优先分析;最左素短语; 目录 1 课题综述 1 1.1 课题来源 1 1.2课题意义 1 1.3 预期目标 1 1.4 面对的问题 1 2 系统分析 2

编译原理实验词法解析总结器的设计及实现.doc

南华大学 计算机科学与技术学院 实验报告 ( 2018~2019学年度第二学期) 课程名称编译原理 实验名称词法分析器的设计与 实现 姓名学号

专业班级 地点教师 1.实验目的及要求 实验目的 加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。 实验要求 1.对单词的构词规则有明确的定义; 2.编写的分析程序能够正确识别源程序中的单词符号; 3.识别出的单词以 <种别码,值 >的形式保存在符号表中,正确设计和维护 符号表; 4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误 提示,保证顺利完成整个源程序的词法分析; 2.实验步骤 1.词法分析规则 <标识符 >::=< 字母 >|< 标识符 ><字母 >|< 标识符 ><数字 >

<常数 >::=< 数字 >|< 数字序列 ><数字 > <数字序列 >:: =<数字序列 ><数字 >|< 数字 >|<.> <字母 >::=a|b|c|??|x|y|z <数字 >::=0|1|2|3|4|5|6|7|8|9 <运算符 >::=< 关系运算符 >|< 算运算符 >|< 运算符 >|< 位运算符 >|< 运算符 > <算数运算符 >:: =+|-|*|/|...|-- <关系运算符 >:: =<|>|!=|>=|<=|== <运算符 >::=&&| || |! <位运算符 >::=&| | |! <运算符 >::==|+=|-=|/=|*= <分界符 >:: = ,|;|(|)|{|}|:| // |/**/ <保留字 >:: = main|if|else|while|do|for|...|void 2.符号的 符号种符号种 main0>26 if1>=27 else2<28 while3<=29 do4!30 for5!=31

编译原理 实验3 算符优先分析

编译原理实验3 算符优先分析 一、实验目的 通过设计编制调试构造FIRSTVT集、LASTVT集和构造算符优先表、对给定符号串进行分析的程序,了解构造算符优先分析表的步骤,对文法的要求,生成算符优先关系表的算法,对给定的符号串进行分析的方法。 二、实验内容 1. 给定一文法G,输出G的每个非终结符的FIRSTVT集和LASTVT集。 2. 构造算符优先表。 3. 对给定的符号串进行分析,包含符号栈,符号栈栈顶符号和输入串当前符号的优先级,最左素短语和使用的产生式和采取的动作。 三、程序思路 在文法框内输入待判断文法产生式,格式E->a|S,注意左部和右部之间是“->”,每个产生式一行,ENTER键换行。文法结束再输入一行G->#E# 1. 先做文法判断,即可判断文法情况。 2. 若是算符优先文法,则在优先表栏显示优先表。 3. 写入要分析的句子,按回车即可。 4. 在分析过程栏,可以看到整个归约过程情况 四、实验结果 FunctorFirst.h #include #include #include #include usingnamespace std;

#define rightlength 20 #define product_num 20 // 产生式最多个数 #define num_noterminal 26 // 非终结符最多个数 #define num_terminal 26 // 终结符最多个数 struct Production { char Left; char Right[rightlength]; int num; }; struct VT { bool vt[num_noterminal][num_terminal]; }; struct Stack { char P; char a; }; class CMyDlg { public:CMyDlg(); void InputRule(); CString showLastVT(); CString showFirstVT(); CString shownoTerminal(char G[]); CString showTerminal(char g[]); CString showLeftS(char S[], int j, int k); void InitAll(); CString showSentence(CString sen, int start); CString showStack(char S[], int n); void Initarry(char arry[], int n); CString ProdtoCStr(Production prod); int selectProd(int i, int j, char S[]); void preFunctor(CString sen); void insertFirstVT(Stack S[], int&sp, char P, char a); void insertLastVT(Stack S[], int&sp, char P, char a); void ShowPreTable(); void createPreTable();

编译原理实验报告

编译原理实验报告 姓名: 学号: 班级: 学院: 南昌大学信息工程学院计算机系 2014年6月

目录 实验一 (3) 实验二 (8) 实验三 (15)

实验1 词法分析程序的设计 学生姓名:学号:专业班级: 实验类型:□验证□综合□设计□创新实验日期:实验成绩: 一、实验目的 掌握计算机语言的词法分析程序的开发方法。 二、实验内容 编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。 三、实验要求 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)* 运算符和界符+ - * / > < =<= >=( ) ;{ } 关键字main if then else while do int (可根据需要添加) 2、根据状态图,设计词法分析函数int scan( ),完成以下功能: 1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词, 2)以二元式形式输出单词<单词种类,单词属性> 其中单词种类用整数表示: 0:标识符 1:十进制整数 2:八进制整数 3:十六进制整数 运算符和界符,关键字采用一字一符,不编码 其中单词属性表示如下: 标识符,整数由于采用一类一符,属性用单词表示 运算符和界符,关键字采用一字一符,属性为空 3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。 四、实验环境 PC微机 DOS操作系统或Windows 操作系统 Turbo C 程序集成环境或Visual C++ 程序集成环境

编译原理实验题目及报告要求

编译原理上机实验试题 一、实验目的 通过本实验使学生进一步熟悉和掌握程序设计语言的词法分析程序的设计原理及相关的设计技术, 如何针对确定的有限状态自动机进行编程序;熟悉和 掌握程序设计语言的语法分析程序的设计原理、熟悉 和掌握算符优先分析方法。 二、实验要求 本实验要求:①要求能熟练使用程序设计语言编程;②在上机之前要有详细的设计报告(预习报告); ③要编写出完成相应任务的程序并在计算机上准确 地运行;④实验结束后要写出上机实验报告。 三、实验题目 针对下面文法G(S): S→v = E E→E+E│E-E│E*E│E/E│(E)│v │i 其中,v为标识符,i为整型或实型数。要求完成 ①使用自动机技术实现一个词法分析程序; ②使用算符优先分析方法实现其语法分析程序,在 语法分析过程中同时完成常量表达式的计算。

1、题目(见“编译原理---实验题目.doc,“实验题目”中的第一项) 2、目的与要求(见“编译原理---实验题目.doc”) 3、设计原理: (1)单词分类:标识符,保留字,常数,运算符,分隔符等等 (2)单词类型编码 (3)自动机 4、程序流程框图 5、函数原型(参数,返回值) 6、关键代码(可打印,只打印关键代码) 7、调试: (1)调试过程中遇到的错误,如何改进的; (2)需要准备测试用例(至少3个,包含输入和输出)——(可打印) 8、思考: (1)你编写的程序有哪些要求是没有完成的,你觉得该采用什么方法去完成; (2)或者是你觉得程序有哪些地方可以进一步完善,简述你的完善方案。

1、题目(见“编译原理---实验题目.doc,“实验题目”中的第二项) 2、目的与要求(见“编译原理---实验题目.doc”) 3、设计原理:构造出算法优先关系表 4、程序流程框图 5、函数原型(参数,返回值) 6、关键代码(可打印,只打印关键代码) 7、调试: (1)调试过程中遇到的错误,如何改进的; (2)需要准备测试用例(至少3个,包含输入和输出)——(可打印) 8、思考: (1)你编写的程序有哪些要求是没有完成的,你觉得该采用什么方法去完成; (2)或者是你觉得程序有哪些地方可以进一步完善,简述你的完善方案。

编译原理实验4算符优先算法

一、实验目的与任务 算术表达式和赋值语句的文法可以是(你可以根据需要适当改变): S→i=E E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将赋值语句进行语法分析,翻译成等价的一组基本操作,每一基本操作用四元式表示。 二、实验涉及的相关知识点 算符的优先顺序。 三、实验内容与过程 如参考C语言的运算符。输入如下表达式(以分号为结束):(1)a = 10; (2)b = a + 20; 注:此例可以进行优化后输出(不作要求):(+,b,a,20) (3)c=(1+2)/3+4-(5+6/7); 四、实验结果及分析 (1)输出:(=, a,10,-) (2)输出:(=,r1,20,-)

(+,r2,a,r1) (=,b,r2,-) (3)输出:(+,r1,1,2) (/,r2,r1,3) (/,r3,6,7) (+,r4,5,r3,) (+,r5,r2,4) (-,r6,r5,r4) (=,c,r6,-) 五、实验有关附件(如程序、附图、参考资料,等) ... ... h == '#') o][Peek(n0).No]; if(r == '<') h == 'E'&& Peek(1).ch == '#' && Token[ipToken].ch == '#') return TRUE; else return FALSE; } h) { k = TRUE; h == 'E') { n ++; } return n; } 词结束(遇到“#”号),无法移进,需要规约,返回:1 词没有结束,需判断是否可以移进 栈单词<=单词:移进后返回:2 栈单词>单词:不能移进,需要规约,返回:1 单词没有优先关系:出错,返回:-1 int MoveIn() { SToken s,t; h = '#';

编译原理实验 中间代码生成

实验四中间代码生成 一.实验目的: 掌握中间代码的四种形式(逆波兰式、语法树、三元式、四元式)。 二.实验内容: 1、逆波兰式定义:将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表 达式也称做后缀式。 2、抽象(语法)树:运算对象作为叶子结点,运算符作为内部结点。 3、三元式:形式序号:(op,arg1,arg2) 4、四元式:形式(op,arg1,arg2,result) 三、以逆波兰式为例的实验设计思想及算法 (1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。 (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。 (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。 (4)如果不是数字,该字符则是运算符,此时需比较优先关系。 做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。 (5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。 四、程序代码: //这是一个由中缀式生成后缀式的程序 #include<> #include<> #include<> #include<> #define maxbuffer 64 void main() { char display_out(char out_ch[maxbuffer], char ch[32]); //int caculate_array(char out_ch[32]); static int i=0; static int j=0; char ch[maxbuffer],s[maxbuffer],out[maxbuffer]; cout<<"请输入中缀表达式: ";

编译原理第六章答案

第6 章自底向上优先分析 第1 题 已知文法G[S]为: S→a|∧|(T) T→T,S|S (1) 计算G[S]的FIRSTVT 和LASTVT。 (2) 构造G[S]的算符优先关系表并说明G[S]是否为算符优先文法。 (3) 计算G[S]的优先函数。 (4) 给出输入串(a,a)#和(a,(a,a))#的算符优先分析过程。 答案: 文法展开为: S→a S→∧ S→(T) T→T,S T→S (1) FIRSTVT - LASTVT 表: 表中无多重人口所以是算符优先(OPG)文法。 友情提示:记得增加拓广文法 S`→#S#,所以# FIRSTVT(S),LASTVT(S) #。 (3)对应的算符优先函数为:

Success! 对输入串(a,(a,a))# 的算符优先分析过程为: Success! 第2 题 已知文法G[S]为: S→a|∧|(T) T→T,S|S

(1) 给出(a,(a,a))和(a,a)的最右推导,和规范归约过程。 (2) 将(1)和题1 中的(4)进行比较给出算符优先归约和规范归约的区别。答案:

(2)算符优先文法在归约过程中只考虑终结符之间的优先关系从而确定可归约串,而与 非终结符无关,只需知道把当前可归约串归约为某一个非终结符,不必知道该非终结符的名字是什么,因此去掉了单非终结符的归约。 规范归约的可归约串是句柄,并且必须准确写出可归约串归约为哪个非终结符。 第3题:

有文法G[S]: S V V T|ViT T F|T+F F )V*|( (1) 给出(+(i(的规范推导。 (2) 指出句型F+Fi(的短语,句柄,素短语。 (3) G[S]是否为OPG?若是,给出(1)中句子的分析过程。 因为该文法是OP,同时任意两个终结符的优先关系唯一,所以该文法为OPG。(+(i(的分析过程

编译原理实验二

编译原理二 -------词法分析器一.问题描述 词法分析程序的功能: 输入源程序,输出单词符号,如图所示: 单词符号 处理过程:在扫描源程序字符串时,一旦识别出关键字、分隔符、标识符、无符号常数中之一,即以单词形式(各类单词均采用相同的结构,即二元式编码形式)输出。每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直至整个源程序全部扫描完毕,并形成相应的单词串形式的源程序。 二.需求分析 1.对给定的程序通过词法分析器能够识别一个个单词符号,并以二元式(单词类型,单词符号)显示; 2.可以将要分析的程序保存到文件中进行读取; 3.删除无用的空白字符、回车符、及其它非实质性符号。 三.程序设计 本程序规定: (1)关键字"begin","end","if","then","else","while","write","read", "do", "call","const","char","until","procedure","repeat"

(2)运算符:"+","-","*","/","=" (3)界符:"{","}","[","]",";",",",".","(",")",":" (4)其他标记如字符串,表示以字母开头的标识符。 (5)空格、回车、换行符跳过。 对于一段可能的输入代码,其结果在屏幕上显示如下: ( 1 , 无符号整数) ( begin , 关键字) ( if , 关键字) ( +, 运算符) ( ;, 界符) ( a , 普通标识符) 关键字或标识符的判断:读入一串字符,将ASCII码在字母范围的字符存入数组中,将该数组与设置好的关键字比较,如果相等则输出是关键字,否则继续读入直至下一字符既非数字也非字母,输出为标识符; 数字的判断:若跟在字母后面则一起输出为标识符,否则输出为数字; 界符、运算符的判断:直接判断其ASCII码 运行过程为: 1.预处理:把源文件一个字符一个字符的读入词法分析程序设置的输入字符结构体数组中(输入缓冲区),读入过程要删除多余的空格; 2.源程序字符数组中获得单词, 编码为二元式.:二元式采用结构体数组存储, 把单词类型和词元记录下来。

编译原理作业集-第五章-修订(精选.)

第五章语法分析—自下而上分析 本章要点 1. 自下而上语法分析法的基本概念: 2. 算符优先分析法; 3. LR分析法分析过程; 4. 语法分析器自动产生工具Y ACC; 5. LR分析过程中的出错处理。 本章目标 掌握和理解自下而上分析的基本问题、算符优先分析、LR分析法及语法分析器的自动产生工具YACC等内容。 本章重点 1.自下而上语法分析的基本概念:归约、句柄、最左素短语; 2.算符优先分析方法:FirstVT, LastVT集的计算,算符优先表的构造,工作原理;3.LR分析器: (1)LR(0)项目集族,LR(1)项目集簇; (2)LR(0)、SLR、LR(1)和LALR(1)分析表的构造; (3)LR分析的基本原理,分析过程; 4.LR方法如何用于二义文法; 本章难点 1. 句柄的概念; 2. 算符优先分析法; 3. LR分析器基本; 作业题 一、单项选择题: 1. LR语法分析栈中存放的状态是识别________的DFA状态。 a. 前缀; b. 可归前缀; c. 项目; d. 句柄; 2. 算符优先分析法每次都是对________进行归约: (a)句柄(b)最左素短语(c)素短语(d)简单短语

3. 有文法G=({S},{a},{S→SaS,S→ε},S),该文法是________。 a. LL(1)文法; b.二义性文法; c.算符优先文法; d.SLR(1)文法; 4. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类,和LL(1)分析法属于自顶向下分析; a. 深度分析法 b. 宽度优先分析法 c. 算符优先分析法 d. 递归下降子程序分析法 5. 自底向上语法分析采用分析法,常用的是自底向上语法分析有算符优先分析法和LR分析法。 a. 递归 b. 回溯 c. 枚举 d. 移进-归约 6. 一个LR(k)文法,无论k取多大,。 a. 都是无二义性的; b. 都是二义性的; c. 一部分是二义性的; d. 无法判定二义性; 7. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类,和LR分析法属于自底向上分析。 a. 深度分析法 b. 宽度优先分析法 c. 算符优先分析法 d. 递归下降子程序分析法 8. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类,自顶向下分析试图为输入符号串构造一个; a. 语法树 b. 有向无环图 c. 最左推导 d. 最右推导 9. 在编译程序中,语法分析分为自顶向下分析和自底向上分析两类,自底向上分析试图为输入符号串构造一个。 a. 语法树 b. 有向无环图 c. 最左推导 d. 最右推导 10. 采用自顶向下分析方法时,要求文法中不含有。 a. 右递归 b. 左递归 c. 直接右递归 d. 直接左递归 11. LR分析是寻找右句型的;而算符优先分析是寻找右句型的。 a. 短语; b. 素短语; c. 最左素短语; d. 句柄 12. LR分析法中分析能力最强的是;分析能力最弱的是。 a. SLR(1); b. LR(0); c. LR(1); d. LALR(1) 13. 设有文法G: T->T*F | F F->F↑P | P P->(T) | a 该文法句型T*P↑(T*F)的最左直接短语是下列符号串________。 a. (T*F), b. T*F, c. P, d. P↑(T*F) 14. 在通常的语法分析方法中,()特别适用于表达式的分析。 a.算符优先分析法b.LR分析法c.递归下降分析法d.LL(1)分析法 15. .运算符的优先数之间有几种关系。 a.3种 b. 2种 c. 4种 d. 1种 16. 算符优先法属于() a.自上而下分析法 b.LR分析法 c.SLR分析法 d.自下而上分析法 17. 在LR分析法中,分析栈中存放的状态是识别规范句型的DFA状态。 a.句柄 b. 前缀 c. 活前缀 d. LR(0)项目 一.答案: 1. b; 2. b; 3. b; 4. d; 5. d; 6. a; 7. c; 8. c; 9. d;10. b;11. d,c;12. c,b;13. a;14. a 15. a;16. d;17. c;

编译原理实验报告

学生学号0120810680316 实验课成绩 武汉理工大学 学生实验报告书 实验课程名称《编译原理》 开课学院计算机科学与技术学院 指导老师姓名何九周 学生姓名刘洋 学生专业班级软件工程0803 2010 —2011 学年第二学期

实验课程名称:编译原理 实验项目名称单词的词法分析程序设计实验成绩实验者刘洋专业班级软件0803 组别 同组者实验日期 2011 年 5 月 17日 第一部分:实验分析与设计(可加页) 一、实验内容描述(问题域描述) 实验目的: 设计,编制并调试一个词法分析程序,加深对词法分析原理的理解。 实验要求: 在上机前应认真做好各种准备工作,熟悉机器的操作系统和语言的集成环境,独立完成算法编制和程序代码的编写;上机时应随带有关的高级语言教材或参考书;要学会程序调试与纠错;每次实验后要交实验报告。 实验题目: 对于给定的源程序(如C语言或Pascal等),要求从组成源程序的字符行中寻找出单词,并给出它们的种别和属性——输出二元组序列。以便提供给语法分析的时候使用。要求能识别所有的关键字,标志符等,并且能够对出先的一些词法规则的错误进行必要的处理。 二、实验基本原理与设计(包括实验方案设计,实验手段的确定,试验步骤等,用硬件逻辑或 者算法描述) 实验原理: 由于这是一个用高级语言编写一个词法分析器,使之能识别输入串,并把分析结果(单词符号,标识符,关键字等等)输出.输入源程序,输入单词符号,本词法分析器可以辨别关键字,标识符,常数,运算符号和某些界符,运用了文件读入来获取源程序代码,再对该源程序代码进行词法分析,这就是词法分析器的基本功能.当词法分析器调用预处理子程序处理出一串输入字符放进扫描缓冲区之后,分析器就从此缓冲区中逐一识别单词符号.当缓冲区里的字符串被处理完之后,它又调用预处理子程序来处理新串. 编写的时候,使用了文件的输入和输出,以便于词法分析的通用型,同时在文件输出时,并保存在输出文件output文件中。 从左到右扫描程序,通过初始化:1为关键字;2为标志符; 3为常数;4为运算符或界符。 三、主要仪器设备及耗材 计算机

编译原理实验指导

编译原理实验指导书 主编:徐静李娜 信息与电气工程学院 2010年3月

概述 一、本课程实验的目的和任务 编译原理是一门实践性很强的课程,只有通过实践,才能真正掌握。实际的编译程序是十分复杂的,有时由多达十几万条指令组成。为此,编译原理的实践教学,采用简化编译过程的办法,选择最关键的3个环节──词法分析、语法分析(包括语义处理、产生无优化的目标指令)、连接调试,进行编程和调试训练。每个环节作为一个实践课题。先分别编程调试,再连接在一起总调。 二、实验方法 任何一个实用的高级语言,其语法都比较复杂,如选其作为源语言,很难实践全过程。故本实验将定义一个简化的语言── C语言的一个子集作为源语言,设计调试出它的编译程序。前后贯穿这一条主线进行实践。每次都可利用课余时间编程,利用上机时间进行输入和调试。 三、实验报告的规范和要求 每个实验完成后写出实验报告。实验报告的内容包括如下内容: 一、实验目的 二、程序设计时采用的算法和方法 三、输入的源程序 四、词法分析程序清单和输出结果。 五、心得体会

实验一词法分析 一、实验目的: (1)通过设计编制调试一个具体的词法分析程序,理解词法分析在编译程序中的作用。 (2)加深对有穷自动机模型的理解。 (3)掌握词法分析程序的实现方法和技术。 (4)用C语言对一个简单语言的子集编制一个一遍扫描的程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示)。 二、实验预习提示 1. 词法分析器的功能和输出格式 词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。本实验中,采用的是一类符号一种别码的方式。 2. 单词的BNF表示 <标识符>→ <字母><字母数字串> <字母数字串>→<字母><字母数字串>|<数字> <字母数字串>| <下划线><字母数字串>|ε <无符号整数>→<数字> <数字串> <数字串>→<数字><数字串>|ε <加法运算符>→+ <减法运算符>→- <大于关系运算符>→> <大于等于关系运算符>→>= 3. “超前搜索”方法

编译原理简答

1、给出算符优先文法的定义,算符优先表是否都存在对应的优先函数给出优先函数的定义。 设有一不含ε产生式的算符文法G,如果对任意两个终结符对a,b之间至多只有、和h三种关系的一种成立,则称G一个算符优先文法。 算符优先关系表不一定存在对应的优先函数 优先函数为文法字汇表中 2、考虑文法G[T]: T→T*F|F F→F↑P|P P→(T)|i 证明T*P↑(T*F)是该文法的一个句型,并指出直接短语和句柄。 首先构造T*P↑(T*F)的语法树如图所示。 句型T*P↑(T*F)的语法树 由图可知,T*P↑(T*F)是文法G[T]的一个句型。 直接短语有两个,即P和T*F;句柄为P。

3、文法G[S]为: S→SdT | T T→T

4、目标代码有哪几种形式生成目标代码时通常应考虑哪几个问题 三种形式:可立刻执行的机器语言代码;汇编语言程序;待装配的机器语言代码模块 考虑的问题包括: 每一个语法成分的语义; 目标代码中需要哪些信息,怎样截取这些信息。 5、符号表的作用是什么符号表的查找的整理技术有哪几种 作用:登记源程序中出现的各种名字及其信息,以及编译各阶段的进展状况。主要技术:线性表,对折查找与二叉树,杂凑技术。 1、实现高级语言程序的途径有哪几种它们之间的区别 计算机执行用于高级语言编写的程序主要有两种途径:解释和编译。 在解释方式下,翻译程序并不对高级语言进行彻底的翻译,而是读入一条语句,就解释其含义并执行,然后再读入下一条语句,再执行。 在编译方式下,翻译程序先对高级语言进行彻底的翻译并生成目标代码,然后再对目标代码进行优化,即对源程序的处理是先翻译后执行。 从速度上看,编译方式下,源程序的执行比解释方式下快,但在解释方式下,有

编译原理实验三

编译原理实验报告实验三语义分析 班级: 学号: 姓名: 任课教师: 计算机科学与工程系 2016年 6 月20 日

一、实验目的 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。 二、实验要求 实验的输入和输出: 输入是语法分析后提供的正确的单词串,输出为三地址指令形式的四元式序列。 例如:对于语句串 begin a:=2+3*4;x:=(a+b)/c end# 输出的三地址指令如下: (1) t1=3* 4 (4) t3=a+b (2) t2=2+t1 (5) t4=t3/c (3) a=t2 (6) x=t4 三、实验内容 采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 四、算法设计和源程序 #include "stdio.h" #include "string.h" #include "stdlib.h" char prog[100],token[8],ch; char *rwtab[6]={"begin","if","then","while","do","end"}; int syn,p,m,n,sum,q; int kk; struct { char result1[8]; char ag11[8]; char op1[8]; char ag21[8]; } quad[20]; char *factor(); char *expression(); int yucu(); char *term(); int statement(); int lrparser(); char *newtemp(); scaner(); emit(char *result,char *ag1,char *op,char *ag2); main()

编译原理 六章 算符优先分析法

第六章算符优先分析法 课前索引 【课前思考】 ◇什么是自下而上语法分析的策略? ◇什么是移进-归约分析? ◇移进-归约过程和自顶向下最右推导有何关系? ◇自下而上语法分析成功的标志是什么? ◇什么是可归约串? ◇移进-归约过程的关键问题是什么? ◇如何确定可归约串? ◇如何决定什么时候移进,什么时候归约? ◇什么是算符文法?什么是算符优先文法? ◇算符优先分析是如何识别可归约串的? ◇算符优先分析法的优缺点和局限性有哪些? 【学习目标】 算符优先分析法是自下而上(自底向上)语法分析的一种,尤其适应于表达式的语法分析,由于它的算法简单直观易于理解,因此,也是学习其它自下而上语法分析的基础。通过本章学习学员应掌握: ◇对给定的文法能够判断该文法是否是算符文法 ◇对给定的算符文法能够判断该文法是否是算符优先文法 ◇对给定的算符文法能构造算符优先关系表,并能利用算符优先关系表判断该文法是否是算符优先文法。 ◇能应用算符优先分析算法对给定的输入串进行移进-归约分析,在分析的每一步能确定当前应移进还是归约,并能判断所给的输入串是否是该文法的句子。 ◇了解算符优先分析法的优缺点和实际应用中的局限性。 【学习指南】 算符优先分析法是自下而上语法分析的一种,它的算法简单、直观、易于理解,所以通常作为学习其它自下而上语法分析的基础。为学好本章内容,学员应复习有关语法分析的知识,如:什么是语言、文法、句子、句型、短语、简单短语、句柄、最右推导、规范归约基本概念。 【难重点】 ◇通过本章学习后,学员应该能知道算符文法的形式。 ◇对一个给定的算符文法能构造算符优先关系分析表,并能判别所给文法是否为算符优先文法。 ◇分清规范句型的句柄和最左素短语的区别,进而分清算符优先归约和规范归约的区别。 ◇算符优先分析的可归约串是句型的最左素短语,在分析过程中如何寻找可归约串是算符优先分析的关键问题。对一个给定的输入串能应用算符优先关系分析表给出分析(归约)步骤,并最终判断所给输入串是否为该文法的句子。 ◇深入理解算符优先分析法的优缺点和实际应用中的局限性。 【知识点】

编译原理实验报告

《编译原理》实验报告软件131 陈万全132852

一、需求分析 通过对一个常用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处理模块的设计、开发,掌握实际编译系统的核心结构、工作流程及其实现技术,获得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。 通过开源编译器分析、编译过程可视化等扩展实验,促进学生增强复杂系统分析、设计和实现能力,鼓励学生创新意识和能力。 1、词法分析程序设计与实现 假定一种高级程序设计语言中的单词主要包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符,试构造能识别这些单词的词法分析程序。 输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序文件。 输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形式输出,并将结果放到某个文件中。对于标识符和无符号常数,CLASS字段为相应的类别码的助记符;VALUE字段则是该标识符、常数的具体值;对于关键字和运算符,采用一词一类的编码形式,仅需在二元式的CLASS字段上放置相应单词的类别码的助记符,VALUE字段则为“空”。 2、语法分析程序设计与实现 选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的

一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。 G2[<算术表达式>]: <算术表达式>→<项> | <算术表达式>+<项> | <算术表达式>-<项> <项>→<因式>|<项>*<因式>|<项>/<因式> <因式>→<运算对象> | (<算术表达式>) 若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F和i 代表,则G2可写成: G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E) 输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。 3、语义分析程序设计与实现 对文法G2[<算术表达式>]中的产生式添加语义处理子程序,完成运算对象是简单变量(标识符)和无符号数的四则运算的计值处理,将输入的四则运算转换为四元式形式的中间代码。 输入:包含测试用例(由标识符、无符号数和+、?、*、/、(、)构成的算术表达式)的源程序文件。 输出:将源程序转换为中间代码形式表示,并将中间代码序列输出到文件中。 若源程序中有错误,应指出错误信息 二、设计思路 1、词法分析程序设计与实现 1)单词分类 为了编程的实现。我们假定要编译的语言中,全部关键字都是保留字,程序员不得将它们作为源程序中的标识符;作了这些限制以后,就可以把关键字和标识符的识别统一进行处理。即每当开始识别一个单词时,若扫视到的第一个字符为字母,则把后续输入的字母或数字字符依次进行拼接,直至扫视到非字母、数字字符为止,以期获得一个尽可能长的字母数字字符串,然后以此字符串查所谓保留字表(此保留字表要事先造好),若查到此字符串,则取出相应的类别码;反之,则表明该字符串应为一标识符。

编译原理-语法分析-算符优先文法分析器

编译原理实验报告 实验名称:编写语法分析分析器实验类型: 指导教师: 专业班级: 学号: 电子邮件: 实验地点: 实验成绩:

一、实验目的 通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。 1、选择最有代表性的语法分析方法,如LL(1) 语法分析程序、算符优先分析程序和LR分析分析程序,至少选一题。 2、选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。 二、实验过程 编写算符优先分析器。要求: (a)根据算符优先分析算法,编写一个分析对象的语法分析程序。读者可根据自己的能力选择以下三项(由易到难)之一作为分析算法中的输入: Ⅰ:通过构造算符优先关系表,设计编制并调试一个算法优先分析程序Ⅱ:输入FIRSTVT,LASTVT集合,由程序自动生成该文法的算符优先关系矩阵。 Ⅲ:输入已知文法,由程序自动生成该文法的算符优先关系矩阵。(b)程序具有通用性,即所编制的语法分析程序能够使用于不同文法以及各种输入单词串,并能判断该文法是否为算符文法和算符优先文法。 (c)有运行实例。对于输入的一个文法和一个单词串,所编制的语法分析程序应能正确地判断,此单词串是否为该文法的句子,并要求输出分析过程。 三、实验结果 算符优先分析器: 测试数据:E->E+T|T T->T*F|F F->(E)|i 实验结果:(输入串为i+i*i+i)

四、讨论与分析 自下而上分析技术-算符优先分析法: 算符文法:一个上下无关文法G,如果没有且没有P→..QR...(P ,Q ,R属于非终结符),则G是一个算符文法。 FIRSTVT集构造 1、若有产生式P →a...或P →Qa...,则a∈FIRSTVT(P)。 2、若有产生式P→...,则FIRSTVT(R)包含在FIRSTVT(P)中。由优先性低于的定义和firstVT集合的定义可以得出:若存在某个产生式:…P…,则对所有:b∈firstVT(P)都有:a≦b。 构造优先关系表: 1、如果每个非终结符的FIRSTVT和LASTVT集均已知,则可构造优先关系表。 2、若产生式右部有...aP...的形式,则对于每个b∈FIRSTVT(P)都有

编译原理实验四:正规式到正规文法的转换

实验四:正规式到正规文法的转换一:要求 输入任意的正规式,输出相应的正规文法 二:实验目的 1.熟练掌握正规式到正规文法的转换规则 2.理解正规文法和正规式的等价性 三:实验原理 1.一个正规语言可以由正规文法定义,也可以由正规式定义,对任意一个正规文法,存在一个定义同一个语言的正规式,反之,对每个正规式,存在生成同一个语言的正规文法 2正规文法与正规式的转换规则: 1. A-〉xB,B->y则:A=xy 2.A-〉xA,A->y 则:A-〉x*y 3.A-〉x,A-〉y 则:A=x|y

四:数据结构与算法 struct Chomsky { string left; string right; }; void apart(Chomsky *p,int i)

eft=(0,j);

p[i].right=(j+1,()-j); } } void VNVT(Chomsky *p);j++) { if((p[i].left[j]>='A'&&p[i].left[j]<='Z'))eft[j])>100) noend+=p[i].left[j]; } else { if(p[i].left[j])>100) end+=p[i].left[j];

} } for(j=0;j<(int)p[i].();j++) { if(!(p[i].right[j]>='A'&&p[i].right[j]<='Z'))ight[j])>10 0) end+=p[i].right[j]; } else { if(p[i].right[j])>100) noend+=p[i].right[j]; } } }

相关文档
最新文档