语义分析及中间代码生成程序设计原理与实现技术--实验报告及源代码 北京交通大学

语义分析及中间代码生成程序设计原理与实现技术--实验报告及源代码 北京交通大学
语义分析及中间代码生成程序设计原理与实现技术--实验报告及源代码 北京交通大学

语义分析及中间代码生成程序设计原理与实现技术

XXX 1028XXX2 计科1XXX班

1.程序功能描述

完成以下描述赋值语句和算术表达式文法的语法制导生成中间代码四元式的过程。

G[A]:A→V:=E

E→E+T∣E-T∣

T→T*F∣T/F∣F

F→(E)∣i

V→i

说明:终结符号i 为用户定义的简单变量,即标识符的定义。

2. 设计要求

(1)给出每一产生式对应的语义动作;(2)设计中间代码四元式的结构(暂不与符号表有关)。(3)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。输出为输入串的四元式序列中间文件。(4)设计两个测试用例(尽可能完备),并给出程序执行结果四元式序列。

3.主要数据结构描述:

本程序采用的是算符优先文法,文法以及算符优先矩阵是根据第四次实验来修改的,所以主要的数据结构也跟第四次差不多,主要为文法的表示,FirstVT集和LastVT 集以及算符优先矩阵:

算符优先矩阵采用二维字符数组表示的:

char mtr[9][9]; //算符优先矩阵

4.程序结构描述:

本程序一共有8功能函数:

void get(); //获取文法

void print(); //打印文法

void fun(); //求FirstVT 和 LastVT

void matrix(); //求算符优先矩阵

void test(); //测试文法

int cmp(char a,char b); 比较两个运算符的优先级 1 0 -1

void out(char now,int avg1,int avg2); //打印四元式

int ope(char op,int a,int b); //定义四元式计算方法

5.实验代码

详见附件

6.程序测试

6.1 功能测试

程序运行显示如下功能菜单:

选择打印文法:

选择构造FirstVt集和LastVT集:

选择构造算符优先矩阵:

6.2 文法测试

测试1:1+2*3

测试2:2+3+4*5+(6/2)

7.学习总结

本次实验完成了语义及中间代码生成的设计原理与实现,所采用的方法为算符优先分析方法,首先根据文法求出此文法的FirstVT集和LastVT集,然后根据他们求出此文法的算符优先矩阵。由于此文法和第四次文法基本相同,只是多了一条赋值语句,所以采用的规则和第四次基本相同。在分析阶段,每当遇到有规约的项目,判断一下,打印出此部运算的四元式,这样一步一步分析,知道输入的算术表达式计算分析完毕。

由于本次实验部分代码和第四次实验的代码比较相似,只需增加一点四元式的分析计算打印过程,就能够顺利完成本次实验。

通过这次实验,我对语义分析以及中间代码部分有了一定的提高,对以后的学习有了一定程度上的帮助。

// lb6.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include

#include

#include

#include

using namespace std;

struct info{

char left;

vector right;

vector first;

vector last;

};

vector lang;

char mtr[9][9]; //算符优先矩阵

stack sta;

void get(); //获取文法

void print(); //打印文法

void fun(); //求FirstVT 和 LastVT

void matrix(); //求算符优先矩阵

void test(); //测试文法

int cmp(char a,char b); //比较两个运算符的优先级 1

0 -1

void out(char now,int avg1,int avg2); //打印四元式

int ope(char op,int a,int b); //定义四元式计算方法

int main(){

int choose;

while(1){

cout << "****************************************" << endl;

cout << " 获取文法请按 1" << endl;

cout << " 打印文法请按 2" << endl;

cout << " 构造FirstVT集和LastVT集请按 3" << endl;

cout << " 构造优先关系矩阵请按 4" << endl;

cout << " 文法测试请按 5" << endl;

cout << " 结束请按 0" << endl;

cout << "****************************************" << endl;

cout << endl;

cin >> choose;

if(choose == 0)

break;

switch(choose){

case 1: get(); break;

case 2: print(); break;

case 3: fun(); break;

case 4: matrix(); break;

case 5: test(); break;

default:break;

}

}

return 0;

}

void get(){

info temp,temp1,temp2;

temp.left = 'E';

temp.right.push_back("E+T");

temp.right.push_back("E-T");

temp.right.push_back("T");

temp.right.push_back("i");

temp1.left = 'T';

temp1.right.push_back("T*F");

temp1.right.push_back("T/F");

temp1.right.push_back("F");

temp2.left = 'F';

temp2.right.push_back("(E)");

temp2.right.push_back("i");

lang.push_back(temp);

lang.push_back(temp1);

lang.push_back(temp2);

cout << "****************************************" << endl; cout << " 文法获取完成" << endl; cout << "****************************************" << endl; cout << endl;

}

void print(){

cout << "****************************************" << endl;

for(int i = 0;i < lang.size();i ++){

for(int j = 0;j < lang[i].right.size();j ++){

cout << lang[i].left << " --> ";

cout << lang[i].right[j] << endl;

}

}

cout << "****************************************" << endl;

cout << endl;

}

void fun(){

int i,j,sign = 0,sign1 = 0;

for(i = 0;i < lang.size();i ++){

for(j = 0;j < lang[i].right.size();j ++){

string temp = lang[i].right[j]; //获取右部

if(temp[0] > 'Z' || temp[0] < 'A'){ //终结符

lang[i].first.push_back(temp[0]);

}

else if(temp.length() >= 2){ //终结符

if(temp[1] > 'Z' || temp[1] < 'A'){

lang[i].first.push_back(temp[1]);

}

}

}

}

for(i = 0;i < lang.size();i ++){

for(j = 0;j < lang[i].right.size();j ++){

string temp = lang[i].right[j]; //获取右部

if((temp[0] > 'Z' || temp[0] < 'A') && temp.length() == 1){ //

终结符

lang[i].last.push_back(temp[0]);

}

else if(temp.length() >= 3){ //终结符

if(temp[1] > 'Z' || temp[1] < 'A')

lang[i].last.push_back(temp[1]);

else if(temp[2] > 'Z' || temp[2] < 'A') //终结符

lang[i].last.push_back(temp[2]);

}

}

}

while(sign == 0){ //迭代FirstVT

sign = 1;

for(i = 0;i < lang.size();i ++){

for(j = 0;j < lang[i].right.size();j ++){

string temp = lang[i].right[j]; //获取右部

if(temp.length() == 1 && (temp[0] <= 'Z' && temp[0] >= 'A')){//可以迭代

for(int k = 0;k < lang.size();k ++){

if(lang[k].left == temp[0]){ //找到了,添加元素

for(int p = 0;p < lang[k].first.size();p ++){

sign1 = 0;

char ch = lang[k].first[p];

for(int q = 0;q < lang[i].first.size();q ++){

if(lang[i].first[q] == ch){ //包含了

sign1 = 1;

}

}

if(sign1 == 0){

lang[i].first.push_back(ch);

sign = 0;

}

}

}

}

}

}

}

}

sign = 0;

while(sign == 0){ //迭代LastVT

sign = 1;

for(i = 0;i < lang.size();i ++){

for(j = 0;j < lang[i].right.size();j ++){

string temp = lang[i].right[j]; //获取右部

if(temp.length() == 1 && (temp[0] <= 'Z' && temp[0] >= 'A')){//可以迭代

for(int k = 0;k < lang.size();k ++){

if(lang[k].left == temp[0]){ //找到了,添加元素

for(int p = 0;p < lang[k].last.size();p ++){

sign1 = 0;

char ch = lang[k].last[p];

for(int q = 0;q < lang[i].last.size();q ++){

if(lang[i].last[q] == ch){ //包含了

sign1 = 1;

}

}

if(sign1 == 0){

lang[i].last.push_back(ch);

sign = 0;

}

}

}

}

}

}

}

}

cout << "****************************************" << endl; cout << "FirstVT:" << endl;

for(i = 0;i < lang.size();i ++){

cout << lang[i].left << " : ";

for(j = 0;j < lang[i].first.size();j ++){

cout << lang[i].first[j] << " ";

}

cout << endl;

}

cout << endl;

cout << "LasttVT:" << endl;

for(i = 0;i < lang.size();i ++){

cout << lang[i].left << " : ";

for(j = 0;j < lang[i].last.size();j ++){

cout << lang[i].last[j] << " ";

}

cout << endl;

}

cout << "****************************************" << endl;

cout << endl;

}

void matrix(){

int i,j;

for(i = 0;i < 9;i ++){ //初始化

for(j = 0;j < 9;j ++){

mtr[i][j] = 'n';

}

}

string temp = "+-*/()i#";

for(i = 1;i < 9;i ++){

mtr[i][0] = temp[i - 1];

mtr[0][i] = temp[i - 1];

}

vector str;

for(i = 0;i < lang.size();i ++){ //aU a < FirstVT(U) for(j = 0;j < lang[i].right.size();j ++){

string ss = lang[i].right[j];

string ok = "";

if(ss.length() > 2){

if((ss[0] > 'Z' || ss[0] < 'A') && (ss[1] <= 'Z' && ss[1] >= 'A')){ //aU

ok = "";

ok += ss[0];

ok += ss[1];

str.push_back(ok);

}

if((ss[1] > 'Z' || ss[1] < 'A') && (ss[2] <= 'Z' && ss[2] >= 'A')){ //aU

ok = "";

ok += ss[1];

ok += ss[2];

str.push_back(ok);

}

}

}

}

for(i = 0;i < str.size();i ++){

for(j = 1;j < 9;j ++){

if(mtr[j][0] == str[i][0]){ //Find a Then Find FirstVt(U)

for(int k = 0;k < lang.size();k ++){

if(lang[k].left == str[i][1]){ //Find U

for(int p = 0;p < lang[k].first.size();p ++){

for(int q = 1;q < 9;q ++){

if(mtr[q][0] == lang[k].first[p]){

mtr[j][q] = '<';

}

}

}

}

}

}

}

}

str.clear();

for(i = 0;i < lang.size();i ++){ //Ua LastVT(U) > a for(j = 0;j < lang[i].right.size();j ++){

string ss = lang[i].right[j];

string ok = "";

if(ss.length() > 2){

if((ss[1] > 'Z' || ss[1] < 'A') && (ss[0] <= 'Z' && ss[0] >= 'A')){ //Ua

ok = "";

ok += ss[0];

ok += ss[1];

str.push_back(ok);

}

if((ss[2] > 'Z' || ss[2] < 'A') && (ss[1] <= 'Z' && ss[1] >= 'A')){ //Ua

ok = "";

ok += ss[1];

ok += ss[2];

str.push_back(ok);

}

}

}

}

for(i = 0;i < str.size();i ++){

for(j = 1;j < 9;j ++){

if(mtr[0][j] == str[i][1]){ //Find a Then Find LastVt(U)

for(int k = 0;k < lang.size();k ++){

if(lang[k].left == str[i][0]){ //Find U

for(int p = 0;p < lang[k].last.size();p ++){

for(int q = 1;q < 9;q ++){

if(mtr[0][q] == lang[k].last[p]){

mtr[q][j] = '>';

}

}

}

}

}

}

}

}

str.clear();

for(i = 0;i < lang.size();i ++){ //ab aUb a = b

for(j = 0;j < lang[i].right.size();j ++){

string ss = lang[i].right[j];

string ok = "";

if(ss.length() > 2){

if((ss[1] > 'Z' || ss[1] < 'A') && (ss[0] > 'Z' || ss[0] < 'A')){ //aa

ok = "";

ok += ss[0];

ok += ss[1];

str.push_back(ok);

}

if((ss[2] > 'Z' || ss[2] < 'A') && (ss[1] > 'Z' || ss[1] < 'A')){ //aa

ok = "";

ok += ss[1];

ok += ss[2];

str.push_back(ok);

}

if((ss[2] > 'Z' || ss[2] < 'A') && (ss[0] > 'Z' || ss[0] < 'A')){ //aUa

ok = "";

ok += ss[0];

ok += ss[2];

str.push_back(ok);

}

}

}

}

for(i = 0;i < str.size();i ++){

for(j = 1;j < 9;j ++){

if(str[i][0] == mtr[j][0]){

for(int k = 1;k < 9;k ++){

if(mtr[0][k] == str[i][1]){

mtr[j][k] = '=';

}

}

}

}

}

for(i = 0;i < lang[0].first.size();i ++){ //#

for(j = 1;j < 9;j ++){

if(lang[0].first[i] == mtr[0][j]){

mtr[8][j] = '<';

}

}

}

for(i = 0;i < lang[0].first.size();i ++){ //#

for(j = 1;j < 9;j ++){

if(lang[0].first[i] == mtr[j][0]){

mtr[j][8] = '>';

}

}

}

mtr[8][8] = '=';

cout << "****************************************" << endl; for(i = 0;i < 9;i ++){

for(j = 0;j < 9;j ++){

if(mtr[i][j] != 'n')

cout << mtr[i][j] << " ";

else

cout << " ";

}

cout << endl;

}

cout << "****************************************" << endl; cout << endl;

}

void test(){

cout << "****************************************" << endl; cout << "请输入算术表达式:" << endl;

string str;

cin >> str;

str += '#';

int i,j,k;

stack data;

stack op;

op.push('#');

char now = 'n'; //记录当前栈顶操作符

int sign = 0;

for(i = 0;i < str.length();i ++){

sign = 0;

if(str[i] >= '0' && str[i] <= '9'){ //操作数

int temp = str[i] - '0';

data.push(temp);

}

else{ //运算符

op.push(str[i]);

sign = 1;

}

if(now != 'n' && sign == 1){ //有可比性,并且操作符栈有更新if(!op.empty()){

char top = op.top(); //栈顶元素

while(cmp(now,top) == 1){ //需要规约

int avg1 = data.top();

data.pop();

int avg2 = data.top();

data.pop();

out(now,avg2,avg1); //打印四元式

data.push(ope(now,avg2,avg1));

op.pop();

op.pop();

if(!op.empty()){

now = op.top();

}

else{

now = 'n';

}

op.push(top);

}

if(cmp(now,top) == 0){

op.pop();

op.pop();

if(!op.empty()){

now = op.top();

}

else{

char temp = '=';

if(!data.empty()){

int da = data.top();

out(temp,da,0);

}

}

}

}

}

else{ //不需要比较

if(!op.empty()){

now = op.top();

}

}

编译原理语义分析实验报告——免费!

语义分析实验报告 一、实验目的: 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。 二、实验要求: 采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 三、算法思想: 1、设置语义过程。 (1)emit(char *result,char *ag1,char *op,char *ag2) 该函数的功能是生成一个三地址语句送到四元式表中。 四元式表的结构如下: struct { char result[8]; char ag1[8]; char op[8]; char ag2[8]; }quad[20]; (2) char *newtemp() 该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2,… char *newtemp(void) { char *p; char m[8]; p=(char *)malloc(8); k++; itoa(k,m,10); strcpy(p+1,m); p[0]=’t’; return(p); } 2、函数lrparser 在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句进行翻译。

四、源程序代码: #include #include #include #include struct { char result[12]; char ag1[12]; char op[12]; char ag2[12]; }quad; char prog[80],token[12]; char ch; int syn,p,m=0,n,sum=0,kk; //p是缓冲区prog的指针,m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"}; void scaner(); char *factor(void); char *term(void); char *expression(void); int yucu(); void emit(char *result,char *ag1,char *op,char *ag2); char *newtemp(); int statement(); int k=0; void emit(char *result,char *ag1,char *op,char *ag2) { strcpy(quad.result,result); strcpy(quad.ag1,ag1); strcpy(quad.op,op); strcpy(quad.ag2,ag2);

编译原理词法分析器语法分析器实验报告

编译技术 班级网络0802 学号3080610052姓名叶晨舟 指导老师朱玉全2011年 7 月 4 日

一、目的 编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 二、任务及要求 基本要求: 1.词法分析器产生下述小语言的单词序列 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表: 单词符号种别编码助记符内码值 DIM IF DO STOP END 标识符 常数(整)= + * ** , ( )1 2 3 4 5 6 7 8 9 10 11 12 13 14 $DIM $IF $DO $STOP $END $ID $INT $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR - - - - - - 内部字符串 标准二进形式 - - - - - - 对于这个小语言,有几点重要的限制: 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的: IF(5)=x 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为

编译原理课程设计报告

2011-2012学年第二学期 《编译原理》课程设计报告 学院:计算机科学与工程学院 班级: 学生姓名:学号: 成绩: 指导教师: 时间:2012年5 月

目录 一、课程设计的目的 ---------------------------------------------------------------- - 1 - 二、课堂实验及课程设计的内容 -------------------------------------------------- - 1 - 2.1、课堂实验内容-------------------------------------------------------------- - 1 - 2.2、课程设计内容-------------------------------------------------------------- - 1 - 三、visual studio 2008 简介------------------------------------------------------- - 2 - 四、问题分析及相关原理介绍 ----------------------------------------------------- - 3 - 4.1、实验部分问题分析及相关原理介绍 ---------------------------------- - 3 - 4.1.1、词法分析功能介绍及分析------------------------------------- - 3 - 4.1.2、语法分析功能介绍及分析------------------------------------- - 3 - 4.1.3、语义分析功能介绍及分析------------------------------------- - 4 - 4.2、课程设计部分问题分析及相关原理介绍 ---------------------------- - 5 - 4.2.1、编译程序介绍 ----------------------------------------------------- - 5 - 4.2.2、对所写编译程序的源语言的描述(C语言) -------------- - 6 - 4.2.3、各部分的功能介绍及分析 -------------------------------------- - 7 - 4.3、关键算法:单词的识别-------------------------------------------------- - 8 - 4.3.1、算法思想介绍 ----------------------------------------------------- - 8 - 4.3.2、算法功能及分析 -------------------------------------------------- - 8 - 五、设计思路及关键问题的解决方法 ------------------------------------------ - 10 - 5.1、编译系统------------------------------------------------------------------ - 10 - 5.1.1、设计思路 --------------------------------------------------------- - 10 - 5.2、词法分析器总控算法--------------------------------------------------- - 12 - 5.2.1、设计思路 --------------------------------------------------------- - 12 - 5.2.2、关键问题及其解决方法 --------------------------------------- - 13 - 六、结果及测试分析-------------------------------------------------------------- - 14 - 6.1、软件运行环境及限制--------------------------------------------------- - 14 - 6.2、测试数据说明------------------------------------------------------------ - 14 - 6.3、运行结果及功能说明--------------------------------------------------- - 16 - 6.4、测试及分析说明--------------------------------------------------------- - 16 - 七、总结及心得体会 --------------------------------------------------------------- - 17 - 7.1、设计过程------------------------------------------------------------------ - 17 - 7.2、困难与收获 ------------------------------------------------------------- - 17 - 八、参考文献 ------------------------------------------------------------------------ - 18 -

编译原理知识点汇总

编译原理的复习提纲 1.编译原理=形式语言+编译技术 2.汇编程序: 把汇编语言程序翻译成等价的机器语言程序 3.编译程序: 把高级语言程序翻译成等价的低级语言程序 4.解释执行方式: 解释程序,逐个语句地模拟执行 翻译执行方式: 翻译程序,把程序设计语言程序翻译成等价的目标程序 5.计算机程序的编译过程类似,一般分为五个阶段: 词法分析、语法分析、语义分析及中间代码生成、代码优化、目标代码生成 词法分析的任务: 扫描源程序的字符串,识别出的最小的语法单位(标识符或无正负号数等) 语法分析是: 在词法分析的基础上的,语法分析不考虑语义。语法分析读入词法分析程序识别出的符号,根据给定的语法规则,识别出各个语法结构。 语义分析的任务是检查程序语义的正确性,解释程序结构的含义,语义分析包括检查变量是否有定义,变量在使用前是否具有值,数值是否溢出等。

语法分析完成之后,编译程序通常就依据语言的语义规则,利用语法制导技术把源程序翻译成某种中间代码。所谓中间代码是一种定义明确、便于处理、独立于计算机硬件的记号系统,可以认为是一种抽象机的程序 代码优化的主要任务是对前一阶段产生的中间代码进行等价变换,以便产生速度快、空间小的目标代码 编译的最后一个阶段是目标代码生成,其主要任务是把中间代码翻译成特定的机器指令或汇编程序 编译程序结构包括五个基本功能模块和两个辅助模块 6.编译划分成前端和后端。 编译前端的工作包括词法分析、语法分析、语义分析。编译前端只依赖于源程序,独立于目标计算机。前端进行分析 编译后端的工作主要是目标代码的生成和优化后端进行综合。独立于源程序,完全依赖于目标机器和中间代码。 把编译程序分为前端和后端的优点是: 可以优化配置不同的编译程序组合,实现编译重用,保持语言与机器的独立性。 7.汇编器把汇编语言代码翻译成一个特定的机器指令序列 第二章 1.符号,字母表,符号串,符号串的长度计算P18,子符号串的含义,符号串的简单运算XY,Xn, 2.符号串集合的概念,符号串集合的乘积运算,方幂运算,闭包与正闭包的概念P19,P20A0 ={ε} 3.重写规则,简称规则。非xx(V

词法分析实验报告

编译原理实验一 姓名:朱彦荣 学号:20132184 专业:软件工程2 实验题目:词法分析完成语言:C/C++ 上级系统:VC++6.0 日期:2015/11/7

词法分析 设计题目:手工设计c语言的词法分析器 (可以是c语言的子集) 设计容: 处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。 设计目的: 了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。 结果要求:课程设计报告。 完成日期:第十五周提交报告

一.分析 要想手工设计词法分析器,实现C语言子集的识别,就要明白什么是词法分析器,它的功能是什么。词法分析是编译程序进行编译时第一个要进行的任务,主要是对源程序进行编译预处理(去除注释、无用的回车换行找到包含的文件等)之后,对整个源程序进行分解,分解成一个个单词,这些单词有且只有五类,分别是标识符、保留字、常数、运算符、界符。以便为下面的语法分析和语义分析做准备。可以说词法分析面向的对象是单个的字符,目的是把它们组成有效的单词(字符串);而语法的分析则是利用词法分析的结果作为输入来分析是否符合语法规则并且进行语法制导下的语义分析,最后产生四元组(中间代码),进行优化(可有可无)之后最终生成目标代码。可见词法分析是所有后续工作的基础,如果这一步出错,比如明明是‘<=’却被拆分成‘<’和‘=’就会对下文造成不可挽回的影响。因此,在进行词法分析的时候一定要定义好这五种符号的集合。下面是我构造的一个C语言子集。 第一类:标识符 letter(letter | digit)* 无穷集 第二类:常数 (digit)+ 无穷集 第三类:保留字(32) auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while 第四类:界符‘/*’、‘//’、 () { } [ ] " " ' 等 第五类:运算符 <、<=、>、>=、=、+、-、*、/、^、等 对所有可数符号进行编码:

编译原理实验报告(语法分析器)

. 编译原理实验专业:13级网络工程

语法分析器1 一、实现方法描述 所给文法为G【E】; E->TE’ E’->+TE’|空 T->FT’ T’->*FT’|空 F->i|(E) 递归子程序法: 首先计算出五个非终结符的first集合follow集,然后根据五个产生式定义了五个函数。定义字符数组vocabulary来存储输入的句子,字符指针ch指向vocabulary。从非终结符E函数出发,如果首字符属于E的first集,则依次进入T函数和E’函数,开始递归调用。在每个函数中,都要判断指针所指字符是否属于该非终结符的first集,属于则根据产生式进入下一个函数进行调用,若first集中有空字符,还要判断是否属于该非终结符的follow集。以分号作为结束符。 二、实现代码 头文件shiyan3.h #include #include

#include using namespace std; #define num 100 char vocabulary[num]; char *ch; void judge_E(); void judge_EE(); void judge_T(); void judge_TT(); void judge_F(); 源文件 #include"shiyan3.h" void judge_E() { if(*ch==';') { cout<<"该句子符合此文法!"<

int a=0; cout<<"按1结束程序"<>a; if(a==1) exit(0); } else if(*ch=='('||*ch=='i') { judge_T(); judge_EE(); } else { cout<<"该句子不匹配此文法!"<>a; if(a==1) exit(0); }

北邮大三上-编译原理-语义分析实验报告

编译原理第六章语义分析 班级:09211311 学号: 姓名:schnee

目录 1. 实验题目和要求 (3) 2. 实验分析和思考 (3) 3. 翻译方案 (4) 4. LR实现自底向上分析(摘自语法分析实验) (5) 4.1.构造识别所有活前缀的DFA (5) 4.2.构造LR分析表 (6) 5. S属性定义的自底向上实现 (7) 5.1.扩充分析栈 (7) 5.2.改造分析程序 (7) 5.3.编程实现 (7) 6. 运行结果截图: (13)

1. 实验题目和要求 题目:语义分析程序的设计与实现。 实验内容:编写语义分析程序,实现对算术表达式的类型检查和求值。要求所分析算术表达式由如下的文法产生。 num E id F F F T F T T T T E T E E |)(||/|*||→→-+→ 实验要求:用自底向上的语法制导翻译技术实现对表达式的分析和翻译。 (1) 写出满足要求的语法制导定义或翻译方案。 (2) 编写分析程序,实现对表达式的类型进行检查和求值,并输出: ① 分析过程中所有产生式。 ② 识别出的表达式的类型。 ③ 识别出的表达式的值。 (3) 实验方法:可以选用以下两种方法之一。 ① 自己编写分析程序。 ② 利用YACC 自动生成工具。 2. 实验分析和思考 由于要求进行类型检查和求值,所以可以定义两个综合属性,一个记录值一个记录类型,存放在结构中,一并传入传出。 输出的产生式可以作为虚拟综合属性,在产生式的最后打印出来。 id 认为是定义的变量名,假设是26个小写字母,它们的值存于一个数组里。 将类型检查和求值归于一次扫描,当检查类型出错时则停止,否则继续。 哈希实现输入的映射,模拟词法分析的记号流。 输入格式为每个num 和id 对应两个输入字符,其他运算符仍对应一个字符。比如第4个num,输入为num4。 由于只具有综合属性,故可以用S 属性的自底向上翻译实现,利用LR 分析程序来实现,只需扩充分析站和改造分析程序。 PS:这次实验我只是简单模拟了最简单的显式严格匹配,即没有实现隐式类型转换。

词法分析器实验报告

词法分析器实验报告 词法分析器设计 一、实验目的: 对C语言的一个子集设计并实现一个简单的词法分析器,掌握利用状 态转换图设计词法分析器的基本方法。利用该词法分析器完成对源程 序字符串的词法分析。输出形式是源程序的单词符号二元式的代码, 并保存到文件中。 二、实验内容: 1. 设计原理 词法分析的任务:从左至右逐个字符地对源程序进行扫描,产生一个个单词符号。 理论基础:有限自动机、正规文法、正规式 词法分析器(Lexical Analyzer) 又称扫描器(Scanner):执行词法分析的程序 2. 词法分析器的功能和输出形式 功能:输入源程序、输出单词符号 程序语言的单词符号一般分为以下五种:关键字、标识符、常数、运算符,界符 3. 输出的单词符号的表示形式: 单词种别用整数编码,关键字一字一种,标识符统归为一种,常数一种,各种符号各一种。 4. 词法分析器的结构 单词符号 5. 状态转换图实现

三、程序设计 1.总体模块设计 /*用来存储目标文件名*/ string file_name; /*提取文本文件中的信息。*/ string GetText(); /*获得一个单词符号,从位置i开始查找。并且有一个引用参数j,用来返回这个单词最后一个字符在str的位置。*/ string GetWord(string str,int i,int& j); /*这个函数用来除去字符串中连续的空格和换行 int DeleteNull(string str,int i); /*判断i当前所指的字符是否为一个分界符,是的话返回真,反之假*/ bool IsBoundary(string str,int i); /*判断i当前所指的字符是否为一个运算符,是的话返回真,反之假*/ bool IsOperation(string str,int i);

PL 0 语言编译器分析实验报告

PL/0 语言编译器分析实验 一、实验目的 通过阅读与解析一个实际编译器(PL/0语言编译器)的源代码,加深对编译阶段(包括词法分析、语法分析、语义分析、中间代码生成等)和编译系统软件结构的理解,并达到提高学生学习兴趣的目的。 二、实验要求 (1)要求掌握基本的程序设计技巧(C语言)和阅读较大规模程序源代码的能力; (2)理解并掌握编译过程的逻辑阶段及各逻辑阶段的功能; (3)要求能把握整个系统(PL/0语言编译器)的体系结构,各功能模块的功能,各模块之间的接口; (4)要求能总结出实现编译过程各逻辑阶段功能采用的具体算法与技 三、实验报告 pl/0语言是pascal语言的一个子集,我们这里分析的pl/0的编译程序包括了对pl/0语言源程序进行分析处理、编译生成类pcode代码,并在虚拟机上解释运行生成的类pcode代码的功能。 pl/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。词法分析和代码生成作为独立的子程序供语法分析程序调用。语法分析的同时,提供了出错报告和出错恢复的功能。在源程序没有错误编译通过的情况下,调用类pcode 解释程序解释执行生成的类pcode代码。 词法分析子程序分析: 词法分析子程序名为getsym,功能是从源程序中读出一个单词符号(token),把它的信息放入全局变量sym、id和num中,语法分析器需要单词时,直接从这三个变量中获得。(注意!语法分析器每次用完这三个变量的值就立即调用getsym 子程序获取新的单词供下一次使用。而不是在需要新单词时才调用getsym过程。)getsym过程通过反复调用getch子过程从源程序过获取字符,并把它们拼成单词。getch过程中使用了行缓冲区技术以提高程序运行效率。 词法分析器的分析过程: 调用getsym时,它通过getch过程从源程序中获得一个字符。如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把sym变量赋成相应的保留字类型值;如果没有查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过程的名字),把sym 置为ident,把这个单词存入id变量。查保留字表时使用了二分法查找以提高效率。如果getch获得的字符是数字,则继续用getch获取数字,并把它们拼成一个整数,然后把sym置为number,并把拼成的数值放入num变量。如果识别出其它合

编译原理实验三-自下而上语法分析及语义分析.docx

上海电力学院 编译原理 课程实验报告 实验名称:实验三自下而上语法分析及语义分析 院系:计算机科学和技术学院 专业年级: 学生姓名:学号: 指导老师: 实验日期: 实验三自上而下的语法分析 一、实验目的: 通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。 二、实验学时: 4学时。 三、实验内容

根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。 对于正确的表达式,给出表达式的值。 对于错误的表达式,给出出错位置。 四、实验方法 采用LR分析法。 首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。 接下来给出LR分析表。 然后程序的具体实现: ● LR分析表可用二维数组(或其他)实现。 ●添加一个val栈作为语义分析实现的工具。 ●编写总控程序,实现语法分析和语义分析的过程。 注:对于整数的识别可以借助实验1。 五、文法定义 简单的表达式文法如下: (1)E->E+T (2)E->E-T (3)E->T

(4)T->T*F (5)T->T/F (6)T->F (7)F->(E) (8)F->i 状态ACTION(动作)GOTO(转换) i + - * / ( ) # E T F 0 S5 S4 1 2 3 1 S6 S1 2 acc 2 R 3 R3 S7 S13 R3 R3 3 R6 R6 R6 R6 R6 R6 4 S 5 S4 8 2 3 5 R8 R8 R8 R8 R8 R8 6 S5 S4 9 3 7 S5 S4 10 8 S6 R12 S11 9 R1 R1 S7 S13 R1 R1 10 R4 R4 R4 R4 R4 R4 11 R7 R7 R7 R7 R7 R7 12 S5 S4 14 3 13 S5 S4 15 14 R2 R2 S7 S13 R2 R2 15 R5 R5 R5 R5 R5 R5 五、处理程序例和处理结果例 示例1:20133191*(20133191+3191)+ 3191#

编译原理--词法分析,语法分析,语义分析(C语言)

词法分析 #include #include #include using namespace std; #define MAXN 20000 int syn,p,sum,kk,m,n,row; double dsum,pos; char index[800],len;//记录指数形式的浮点数 char r[6][10]={"function","if","then","while","do","endfunc"}; char token[MAXN],s[MAXN]; char ch; bool is_letter(char c) { return c>='a' && c<='z' || c>='A' && c<='Z'; } bool is_digtial(char c) { return c>='0' && c<='9'; } bool is_dot(char c) { return c==',' || c==';'; } void identifier()//标示符的判断 { m=0; while(ch>='a' && ch<='z' || ch>='0' && ch<='9') { token[m++]=ch; ch=s[++p]; } token[m]='\0';

ch=s[--p]; syn=10; for(n=0;n<6;n++) if(strcmp(token,r[n])==0) { syn=n+1; break; } } void digit(bool positive)//数字的判断{ len=sum=0; ch=s[p]; while(ch>='0' && ch<='9') { sum=sum*10+ch-'0'; ch=s[++p]; } if(ch=='.') { dsum=sum; ch=s[++p]; pos=0.1; while(ch>='0' && ch<='9') { dsum=dsum+(ch-'0')*pos; pos=pos*0.1; ch=s[++p]; } if(ch=='e') { index[len++]=ch; ch=s[++p]; if(ch=='-' || ch=='+') { index[len++]=ch; ch=s[++p]; } if(!(ch>='0' && ch<='9')) { syn=-1; } else

词法分析器实验报告

词法分析器实验报告 一、实验目的及要求 本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。 运行环境: 硬件:windows xp 软件:visual c++6.0 二、实验步骤 1.查询资料,了解词法分析器的工作过程与原理。 2.分析题目,整理出基本设计思路。 3.实践编码,将设计思想转换用c语言编码实现,编译运行。 4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。 三、实验内容 本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。标识符、常数是在分析过程中不断形成的。 对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。 输出形式例如:void $关键字

流程图、程序流程图:

程序: #include #include #include #include //定义关键字 char *Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流 int IsAlpha(char c) { //判断是否为字母 if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1; else return 0; } int IsNum(char c){ //判断是否为数字 if(c>='0'&&c<='9') return 1; else return 0; } int IsKey(char *Word){ //识别关键字函数 int m,i; for(i=0;i<9;i++){ if((m=strcmp(Word,Key[i]))==0) { if(i==0) return 2; return 1; } } return 0; } void scanner(FILE *fp){ //扫描函数 char Word[20]={'\0'}; char ch; int i,c; ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符 if(IsAlpha(ch)){ //判断该字符是否是字母 Word[0]=ch; ch=fgetc(fp);

语义分析实验报告

实验三语法分析 309 科3 李君林 一.实验目的: 通过使用、剖析和扩充TINY语言的语义分析程序,掌握编译器的语义分析程序的构造方法。 二.实验内容 (一)运行TINY的语义分析程序 (二)扩充TINY的语法分析程序 提示: 考虑作用域(如:函数)和数组时可能需要修改符号表。 三.实验步骤 1.先读懂TINY语义程序(相关联的文件:) (1)buildSymtab(syntaxTree); 充TINY的语法分析程序 本次实验我首先将源程序实现的功能改成符合C_MINUS的符号表与类型检测 然后加入没申明调用与数组调用错误即数组没申明而调用数组类型。 四.实验结果 1.正确的测试程序 /**/ int gcd (int u,int v[]) { if(v==0) return u; else return gcd(v,u); } void main(void) { int x;int y; read x; x=y=2; while(x>0) y=y-1; write y; return (gcd(x,y)); }

/**/ 运行结果: 经检验测试程序代码无语义错误2.错误测试程序 /**/ int gcd (int u,int v[]) { if(v==0) return u; else return gcd(v,u); } void main(void) { int x;int y; read x; t=1; x=y=2; x[2]=2; while(x>0) y=y-1; write y; return (gcd(x,y)); } /**/ 实验结果:

编译原理语法分析器实验报告

编译原理语法分析器实验报告 班级: 学号: 姓名:

实验名称语法分析器 一、实验目的 1、根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。 2、本次实验的目的主要是加深对自上而下分析法的理解。 二、实验内容 [问题描述] 递归下降分析法: 0.定义部分:定义常量、变量、数据结构。 1.初始化:从文件将输入符号串输入到字符缓冲区中。 2.利用递归下降分析法分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。 LL(1)分析法: 模块结构: 1、定义部分:定义常量、变量、数据结构。 2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等); 3、运行程序:让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则; 4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式 符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简 单的错误提示。 [基本要求] 1. 对数据输入读取 2. 格式化输出分析结果 2.简单的程序实现词法分析 public static void main(String args[]) { LL l = new LL(); l.setP(); String input = ""; boolean flag = true;

while (flag) { try { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); System.out.println(); System.out.print("请输入字符串(输入exit退出):"); input = br.readLine(); } catch (Exception e) { e.printStackTrace(); } if(input.equals("exit")){ flag = false; }else{ l.setInputString(input); l.setCount(1, 1, 0, 0); l.setFenxi(); System.out.println(); System.out.println("分析过程"); System.out.println("----------------------------------------------------------------------"); System.out.println(" 步骤| 分析栈 | 剩余输入串| 所用产生式"); System.out.println("----------------------------------------------------------------------"); boolean b = l.judge(); System.out.println("----------------------------------------------------------------------"); if(b){ System.out.println("您输入的字符串"+input+"是该文法的一个句子"); }else{ System.out.println("您输入的字符串"+input+"有词法错误!");

北邮 编译原理 语义分析实验报告

编译原理 第六章语义分析 目录 1. 实验题目和要求 (2) 2. 实验分析和思考 (3) 3. 翻译方案 (4) 4. LR实现自底向上分析(摘自语法分析实验) (5) 4.1.构造识别所有活前缀的DFA (5)

5.1. 扩充分析栈 ................................................................................................................ 7 5.2. 改造分析程序 ............................................................................................................ 7 5.3. 编程实现 .................................................................................................................... 7 6. 运行结果截图: (13) 1. 实验题目和要求 题目:语义分析程序的设计与实现。 实验内容:编写语义分析程序,实现对算术表达式的类型检查和求值。要求所分析算术表达式由如下的文法产生。 num E id F F F T F T T T T E T E E |)(||/|*||→→-+→ 实验要求:用自底向上的语法制导翻译技术实现对表达式的分析和翻译。 (1) 写出满足要求的语法制导定义或翻译方案。 (2) 编写分析程序,实现对表达式的类型进行检查和求值,并输出: ① 分析过程中所有产生式。 ② 识别出的表达式的类型。 ③ 识别出的表达式的值。 (3) 实验方法:可以选用以下两种方法之一。 ① 自己编写分析程序。 ② 利用YACC 自动生成工具。

《编译原理》总复习-07级

《编译原理》总复习-07级 第一章编译程序的概述 (一)内容 本章介绍编译程序在计算机科学中的地位和作用,介绍编译技术的发展历史,讲解编译程序、解释程序的基本概念,概述编译过程,介绍编译程序的逻辑结构和编译程序的组织形式等。 (二)本章重点 编译(程序),解释(程序),编译程序的逻辑结构。 (三)本章难点 编译程序的生成。 (四)本章考点 全部基本概念。 编译程序的逻辑结构。 (五)学习指导 引论部分主要是解释什么是编译程序以及编译的总体过程。因此学习时要对以下几个点进行重点学习:翻译、编译、目标语言和源语言这几个概念的理解;编译的总体过程:词法分析,语法分析、语义分析与中间代码的生成、代码优化、目标代码的生成,以及伴随着整个过程的表格管理与出错处理。 第三章文法和语言课外训练 (一)内容 本章是编译原理课程的理论基础,主要介绍与课程相关的形式语言的基本概念,包括符号串的基本概念和术语、文法和语言的形式定义、推导与归约、句子和句型、语法分析树和二义性文法等定义、文法和语言的Chomsky分类。 (二)本章重点 上下文无关文法,推导,句子和句型,文法生成的语言,语法分析树和二义性文法。(三)本章难点 上下文无关文法,语法分析树,文法的分类。 (四)本章考点 上下文无关文法的定义。 符号串的推导。 语法分析树的构造。 (五)学习指导 要构造编译程序,就要把源语言用某种方式进行定义和描述。学习高级语言的语法描述是学习编译原理的基础。上下文无关文法及语法树是本章学习的重点。语法与语义的概念;程序的在逻辑上的层次结构;文法的定义,文法是一个四元组:终结符号集,非终结符号集,开始符号、产生式集;与文法相关的概念,字符,正则闭包,积(连接),或,空集,产生式,推导,直接推导,句子,句型,语言,最左推导,最右推导(规范推导);学会用文法来描述语言及通过文法能分析该文法所描述的语言;语法树及二义性的概念、能通过画语法树来分析一个文法描述的语言是否具有二义性;上下文无关文法的定义和正规文法的定义,能判断一个语言的文法是哪一类文法。 附训练试题:

河北工业大学语义分析实验报告

实验三语义分析程序实现 一、实验设计 在实现词法、语法分析程序的基础上,编写相应的语义子程序,进行语义处理,加深对语法制导翻译原理的理解,进一步掌握将语法分析所识别的语法范畴变换为某种中间代码(四元式)的语义分析方法。 基本实验题目:对文法G2[<算术表达式>]中的产生式添加语义处理子程序,完成运算对象是简单变量(标识符)和无符号数的四则运算的计值处理,将输入的四则运算转换为四元式形式的中间代码。 语法制导翻译模式是在语法分析的基础上,增加语义操作来实现的,实际上是对前后文无关文法的一种扩展。一般而言,首先需要根据进行的语义分析工作,完成对给定文法的必要拆分和语义动作的编写,从而为每一个产生式都配备相应的语义子程序,以便在进行语法分析的同时进行语义解释。即在语法分析过程中,每当用一个产生式进行推导或归约时,语法分析程序除执行相应的语法分析动作之外,还要调用相应的语义子程序,以便完成生成中间代码、查填有关表格、检查并报告源程序中的语义错误等工作。每个语义子程序需指明相应产生式中各个符号的具体含义,并规定使用该产生式进行分析时所应采取的语义动作。这样,语法制导翻译程序在对源程序从左到右进行的一遍扫描中,既完成语法分析任务,又完成语义分析和中间代码生成方面的工作。本实验要求从编译器的整体设计出发,重点通过对实验二中语法分析程序的扩展,完成一个编译器前端程序的编写、调试和测试工作,形成一个将源程序翻译为中间代码序列的编译系统。 二、程序代码 在词法分析和语法分析的基础上,完成了语义的分析,同样采用了头文件的形式,在VC++6.0中运行 #include #include #include #include #include #include"cifa.h" #include"fenxibiao.h" # define PL 15 //+ # define MI 16 //-

相关文档
最新文档