现代编译原理 第一章

入门小练习:


找出给定语句内任意子表达式的print函数的最大参数个数


#include"slp.h"
#include"prog1.h"
#include<stdio.h>
int maxargs(A_stm stm);
int maxargsexlst(A_expList expList);
int maxargsex(A_exp exp);
int countargs(A_expList expList);
int max(int temp1, int temp2)
{
	return temp1 > temp2 ? temp1 : temp2;
}

int maxargsexlst(A_expList expList)
{
	switch (expList->kind)
	{
	case A_pairExpList:
	{
						  int temp1 = maxargsexlst(expList->u.pair.tail);
						  int temp2 = maxargsex(expList->u.pair.head);
						  return max(temp1, temp2);
	}
	case A_lastExpList:
		return maxargsex(expList->u.last);
	default:
		return 0;
	}
}
int maxargsex(A_exp exp)
{
	switch (exp->kind)
	{
	case A_opExp:
	{
					int temp1 = maxargsex(exp->u.op.left);
					int temp2 = maxargsex(exp->u.op.right);
					return max(temp1, temp2);
	}
	case A_eseqExp:
	{

					  int temp3 = maxargsex(exp->u.eseq.exp);
					  int temp4 = maxargs(exp->u.eseq.stm);
					  return max(temp3, temp4); 
	}
	default:
		return 0;
	}
}

int maxargs(A_stm stm)
{
	switch (stm->kind)
	{
	case A_compoundStm:
	{
						  int temp1 = maxargs(stm->u.compound.stm1);
						  int temp2 = maxargs(stm->u.compound.stm2);
						  return max(temp1, temp2);
	}
	case A_assignStm:
	{
		A_exp tempExp = stm->u.assign.exp;
		return maxargsex(tempExp);
	}
	case A_printStm:
		return max(maxargsexlst(stm->u.print.exps), countargs(stm->u.print.exps));
	default:
		return 0;
	}
}

int countargs(A_expList expList)
{
	if (expList->kind == A_pairExpList)
	{
		return 1 + countargs(expList->u.pair.tail);
	}
	else
		return 1;
}
/**********************************************************/
int main()
{
	A_stm stm = prog();
	printf("%d",maxargs(stm));
	//system("pause");
	return 0;
} 

直线式程序语言的解释可以利用语法抽象的方法,理解程序短语可以抽象为树这种数据结构来分析。利用树结构的递归性去设计解释方法。

countargs是对A_printStm参数个数的分析

maxargs    maxargsex    maxargsexlst 是查找A_printStm





写一个函数
void interp(A_stm);

typedef struct table{
	string id;
	int value;
	struct table* tail;
}*Table_;

typedef struct IntAndTable{
	int i;
	Table_ t;
}*IntAndTable_;

Table_ Table(Table_ t, string id, int value);
int lookUp(Table_ t, string id);
Table_ updateTable(Table_ t, string id, int newResult);
void interp(A_stm stm);
Table_ interpStm(A_stm stm, Table_ t);
int getOpResult(int x, int y, int kind);
IntAndTable_ interpExp(A_exp exp, Table_ t);
IntAndTable_ intAndTable(int i, Table_ t);
IntAndTable_ interpAndPrint(A_expList expLst, Table_ t);


Table_ Table(Table_ t,string id, int value)
{
	Table_ temp = (Table_)checked_malloc(sizeof(*t));
	temp->id = id;
	temp->value = value;
	temp->tail = t;
	return temp;
}

//返回id 所对应的值
int lookUp(Table_ t, string id)
{
	Table_ curr = t;
	while (curr != NULL)
	{
		if (curr->id == id)
			return curr->value;
		curr = curr->tail;
	}
	assert(!curr);
	return 0;
}
//将变量的值插入在表的开头
Table_ updateTable(Table_ t, string id, int newResult)
{
	Table_ temp = Table(t, id, newResult);
	return temp;
}


void interp(A_stm stm)
{
	interpStm(stm,NULL);
}

Table_ interpStm(A_stm stm,Table_ t)
{
	if (stm != NULL)
	{
		switch (stm->kind)
		{
		case A_compoundStm:
			t = interpStm(stm->u.compound.stm1, t);
			t = interpStm(stm->u.compound.stm2, t);
			break;
		case A_assignStm:
		{
			IntAndTable_ intTable = intAndTable(0, t);
			intTable = interpExp(stm->u.assign.exp, t);
			t=updateTable(t, stm->u.assign.id, intTable->i);
			break;
		}
		case A_printStm:
			interpAndPrint(stm->u.print.exps,t);
			break;
		}
	}
	return t;
}
//解释并打印表达式结果
IntAndTable_ interpAndPrint(A_expList expLst, Table_ t)
{
	assert(expLst);
	IntAndTable_ intTable = intAndTable(0,t);
	while (expLst->kind == A_pairExpList)
	{
		intTable = interpExp(expLst->u.pair.head, intTable->t);
		expLst = expLst->u.pair.tail;
	}
	intTable = interpExp(expLst->u.last, intTable->t);  
	printf("%d\n", intTable->i);
}

IntAndTable_ intAndTable(int i, Table_ t)
{
	IntAndTable_ temp = (IntAndTable_)checked_malloc(sizeof(*temp));
	temp->i = i;
	temp->t = t;
	return temp;
}

IntAndTable_ interpExp(A_exp exp, Table_ t)
{
	if (exp == NULL)
	{
		return NULL;
	}
	else
	{
		IntAndTable_ intTable = intAndTable(0, t);
		switch (exp->kind)
		{
		case A_idExp:
			intTable->i = lookUp(t, exp->u.id);
			break;
		case A_numExp:
			intTable->i = exp->u.num; 
			break;
		case A_opExp:
			intTable= interpExp(exp->u.op.left, t);
			int i = intTable->i;
			intTable = interpExp(exp->u.op.right, intTable->t);
			int j = intTable->i;
			intTable->i = getOpResult(i,j,exp->u.op.oper);
			break;
		case A_eseqExp:
			t = interpStm(exp->u.eseq.stm,t);
			intTable = interpExp(exp->u.eseq.exp, t);
			break;
		}
		return intTable;
	}
}

int getOpResult(int x, int y,int kind)
{
	switch (kind)
	{
	case A_plus:return x + y;
	case A_minus:return x - y;
	case A_div:return x / y;
	case A_times:return x*y;
	}
}

interpExp(A_exp exp,Table_ t) 是对exp的解释 返回表达式的值并更新映射表

为了在赋值语句的解释中不产生其他副作用,赋值语句将不对已有变量做修改 而是利用updateTable将新值更新到映射表

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作者简介: Andrew W.Appel,美国普林斯顿大学计算机科学系教授,第26届ACM SIGPLAN-SIGACT程序设计原理年会大会执行主席,1998-1999年在贝尔实验室做研究工作。主要研究方向是计算机安全、编译器设计、程序设计语言等。 内容简介: 本书全面讲述了现代编译器的各个组成部分,包括词法分析、语法分析、抽象语法、语义检查、中间代码表示、指令选择、数据流分析、寄存器分配以及运行时系统等。全书分成两部分,第一部分是编译的基础知识,适用于第一门编译原理课程(一个学期);第二部分是高级主题,包括面向对象语言和函数语言、垃圾收集、循环优化、SSA(静态单赋值)形式、循环调度、存储结构优化等,适合于后续课程或研究生教学。书中专门为学生提供了一个用C语言编写的实习项目,包括前端和后端设计,学生可以在一学期内创建一个功能完整的编译器。   本书适用于高等院校计算机及相关专业的本科生或研究生,也可供科研人员或工程技术人员参考。 目录: 第一部分 编译基本原理 第1章 绪论 1 1.1 模块与接口 1 1.2 工具和软件 3 1.3 树语言的数据结构 3 程序设计:直线式程序解释器 7 推荐阅读 9 习题 9 第2章 词法分析 10 2.1 词法单词 10 2.2 正则表达式 11 2.3 有限自动机 13 2.4 非确定有限自动机 15 2.4.1 将正则表达式转换为NFA 16 2.4.2 将NFA转换为DFA 18 2.5 Lex:词法分析器的生成器 20 程序设计:词法分析 22 推荐阅读 23 习题 23 第3章 语法分析 27 3.1 上下文无关文法 28 3.1.1 推导 29 3.1.2 语法分析树 29 3.1.3 二义性文法 30 3.1.4 文件结束符 31 3.2 预测分析 32 3.2.1 FIRST集合和FOLLOW集合 33 3.2.2 构造一个预测分析器 35 3.2.3 消除左递归 36 3.2.4 提取左因子 37 3.2.5 错误恢复 37 3.3 LR分析 39 3.3.1 LR分析引擎 40 3.3.2 LR(0)分析器生成器 41 3.3.3 SLR分析器的生成 44 3.3.4 LR(1)项和LR(1)分析表 45 3.3.5 LALR(1)分析表 46 3.3.6 各类文法的层次 47 3.3.7 二义性文法的LR分析 47 3.4 使用分析器的生成器 48 3.4.1 冲突 49 3.4.2 优先级指导 50 3.4.3 语法和语义 53 3.5 错误恢复 54 3.5.1 用error符号恢复 54 3.5.2 全局错误修复 55 程序设计:语法分析 57 推荐阅读 58 习题 58 第4章 抽象语法 62 4.1 语义动作 62 4.1.1 递归下降 62 4.1.2 Yacc生成的分析器 62 4.1.3 语义动作的解释器 64 4.2 抽象语法分析树 65 4.2.1 位置 67 4.2.2 Tiger的抽象语法 68 程序设计:抽象语法 71 推荐阅读 71 习题 72 第5章 语义分析 73 5.1 符号表 73 5.1.1 多个符号表 74 5.1.2 高效的命令式风格符号表 75 5.1.3 高效的函数式符号表 76 5.1.4 Tiger编译器的符号 77 5.1.5 函数式风格的符号表 79 5.2 Tiger编译器的绑定 79 5.3 表达式的类型检查 82 5.4 声明的类型检查 84 5.4.1 变量声明 84 5.4.2 类型声明 85 5.4.3 函数声明 85 5.4.4 递归声明 86 程序设计:类型检查 87 习题 87 第6章 活动记录 89 6.1 栈帧 90 6.1.1 帧指针 91 6.1.2 寄存器 92 6.1.3 参数传递 92 6.1.4 返回地址 94 6.1.5 栈帧内的变量 94 6.1.6 静态链 95 6.2 Tiger编译器的栈帧 96 6.2.1 栈帧描述的表示 98 6.2.2 局部变量 98 6.2.3 计算逃逸变量 99 6.2.4 临时变量和标号 100 6.2.5 两层抽象 100 6.2.6 管理静态链 102 6.2.7 追踪层次信息 102 程序设计:栈帧 103 推荐阅读 103 习题 103 第7章 翻译成中间代码 106 7.1 中间表示树 106 7.2 翻译为树中间语言 108 7.2.1 表达式的种类 108 7.2.2 简单变量 111 7.2.3 追随静态链 112 7.2.4 数组变量 113 7.2.5 结构化的左值 114 7.2.6 下标和域选择 114 7.2.7 关于安全性的劝告 115 7.2.8 算术操作 116 7.2.9 条件表达式 1

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值