编译原理2

1 Algorithms for attribute computation

属性定义计算方法Top downBottom up
Inherited Attributes依赖关系不是子节点指向父节点,包括父指向子或者兄弟指向兄弟preorderfunction Parameterexternal data structure
Synthesized Attributes该属性总是由子节点指向父节点。(先计算子节点的属性值,然后赋值给父节点)post orderreturn valuevalue stack

S-attributed grammar:

An attribute grammar in which all the attributes are synthesized

所有属性必须是综合属性

L-attributed Definition

  • 综合属性
  • 继承属性,依赖于父节点或者左边的兄弟节点

S属性一定是L属性的

继承属性转为综合属性:

继承属性一般出现在右子树得到值,然后传递给左子树,接着传递给叶子节点,导致了继承

1: 消除左递归,存在A-> A xxx|B 的,修改为两条:

A->BA’和A’->xxxxA’|e (左边改为右边)

2: 将出现A的式子中A后面的部分替代e。比如有S->A b,此时将A’->xxxxA’|e修改为A’->xxxxA’|b即可,然后将原来的修改为S->A

3: 将多余的非终结符消掉,比如将S->A b修改为S-> BA’

如果没有左递归,则消除右递归,需要修改的地方是:
1: A->xxx A | B 变为 A-> A’B A’-> A’xxx | e

一个右递归的例子:

decl -> type var-list
type -> int|float
var-list -> id,var-list|id

消除右递归:var-list -> v’ id
v’->v’ id, | e
替换e: v’->v’ id, | type
消除var-list: decl -> v’ id
v’->v’ id, | type

2 The symbol table

画Symbol table:

1: 每个节点有三个元素:类型,名称,指向下一个节点的指针

2: 执行到第i句话开始,则从i句话开始往前找,依次按照列表往下画
这是因为symbol table插入是插入到头上的,因此必须从后面开始找

如果遇到块语句(封闭的大括号),则里面声明的变量直接跳过。

3 Data types and type checking

各种等价
Structural equivalencetwo types are the same if and only if they have the same structure
Name equivalencetype and name is same
Declaration equivalence显示声明了t1=t2

4 Active Record, Stack-based runtime environment

control link:指向调用该函数的函数的AR

Access link: 指向定义该函数的AR,第一个AR没有access link,

函数的定义在函数体之外,比如

program nonlocalRef;
procedure p;
	var n: integer;
	//函数定义,和局部变量一样
	procedure q;
	begin
		(* a reference to n is 
		now non-local and 
		non-global *)
	end; (*q*)
	
	procedure r(n:intege r);
	begin
		q;
	end; (*r*)

//这里是p函数的函数体定义
begin (* p*)
	n :=1;
	r(2);
end; (*p*)

//这里是主函数
begin (*main*)
	p;
end.

fp:指向当前的AR

sp:指向堆栈顶部

在栈中的顺序:参数,之前的fp,返回地址,函数内部局部变量

在这里插入图片描述

5 Parameter passing mechanisms

Pass by Value:

1: 将值拷贝到函数栈中进行计算,
2: 在函数中修改的值不影响外部的值

Pass by Reference:

1: 将值的地址进行传递,因此对变量的变化会反应到函数外部
2: 如果同一个变量传入两次,则对它们的操作是叠加的

Pass by Value-Result:

1: 对变量值的修改不是实时的,而是只在返回之前将对应的变量的值拷贝到参数中去。

int y; 
calling_procedure() 
{
   y = 10;     
   copy_restore(y); //l-value of y is passed
   printf y; //prints 99 
}
copy_restore(int x) 
{     
   x = 99; // y still has value 10 (unaffected)
   y = 0; // y is now 0 
   //在这里把x的值拷贝到了y的地址中(传进来的是y的地址)
}
void p(int x, int y) {
	x++; //此时x=2, a[0] = 1
	y++; //此时y=2, a[0] = 1
	//将x拷贝到a[0], a[0] = 2
	//将y拷贝到a[0], a[0] = 2
}

int main() {
	int a[2] = {1, 1};
	p(a[0], a[0]);
}

Pass by name:

1: 将函数体拷贝到main中,然后将参数文本替代

void p(int x, int y) {
	x++; 
	i++;
	y++; 
}

int i  = 0;
int main() {
	int a[2] = {1, 1};
	p(a[i], a[i]);
	printf("%d %d", a[0], a[1]);
}

执行过程为:

int i = 0;
int main() {
	int a[2] = {1, 1};
	//将p函数体文本拷贝到main中
	a[i]++;
	i++;
	a[i]++;
	printf("%d %d", a[0], a[1]); //结果是2 2
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值