编译原理 7 运行存储分配学习课件_第1页
编译原理 7 运行存储分配学习课件_第2页
编译原理 7 运行存储分配学习课件_第3页
编译原理 7 运行存储分配学习课件_第4页
编译原理 7 运行存储分配学习课件_第5页
已阅读5页,还剩71页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

运行存储分配

哈尔滨工业大学陈鄞第七章7.1存储组织7.2静态存储分配7.3栈式存储分配7.4非局部数据的访问7.5堆式存储分配7.6符号表提纲编译器在工作过程中,必须为源程序中出现的一些数据对象分配运行时的存储空间对于那些在编译时刻就可以确定大小的数据对象,可以在编译时刻就为它们分配存储空间,这样的分配策略称为静态存储分配反之,如果不能在编译时完全确定数据对象的大小,就要采用动态存储分配的策略。即在编译时仅产生各种必要的信息,而在运行时刻,再动态的分配数据对象的存储空间栈式存储分配堆式存储分配静态和动态分别对应编译时刻和运行时刻7.1存储组织静态代码区静态数据区栈(Stack)区堆

(Heap)区动态数据区域空闲内存运行时内存的划分使用过程(或函数、方法)作为用户自定义动作的单元的语言,其编译器通常以过程为单位分配存储空间过程体的每次执行称为该过程的一个活动(activation)过程每执行一次,就为它分配一块连续存储区,用来管理过程一次执行所需的信息,这块连续存储区称为活动记录(activationrecord)活动记录实参临时变量控制链访问链保存的机器状态局部数据指向调用者的活动记录用来访问存放于其它活动记录中的非局部数据返回值活动记录的一般形式7.1存储组织7.2静态存储分配7.3栈式存储分配7.4非局部数据的访问7.5堆式存储分配7.6符号表提纲在静态存储分配中,编译器为每个过程确定其活动记录在目标程序中的位置这样,过程中每个名字的存储位置就确定了因此,这些名字的存储地址可以被编译到目标代码中过程每次执行时,它的名字都绑定到同样的存储单元7.2静态存储分配适合静态存储分配的语言必须满足以下条件数组上下界必须是常数不允许过程的递归调用不允许动态建立数据实体满足这些条件的语言有BASIC和FORTRAN等静态存储分配的限制条件顺序分配法层次分配法常用的静态存储分配方法按照程序段出现的先后顺序逐段分配存储空间各过程的活动记录占用互不相交的存储空间

1/222/153/184/176/105/23过程编号/所需存储空间

过程存储区域

10~21222~36

337~54

455~71

572~94

695~104共需要105个存储单元优点:处理上简单缺点:对内存空间的使用不够经济合理能用更少的空间么?顺序分配法通过对过程间的调用关系进行分析,凡属无相互调用关系的并列过程,尽量使其局部数据共享存储空间过程4(0~16)过程2(17~31)过程6(0~9)过程5(0~22)过程3(23~40)过程1(41~62)共需要63个存储单元7/80如何分配?层次分配法1/222/153/184/176/105/23过程编号/所需存储空间

B[n][n]:过程调用关系矩阵B[i][j]=1:表示第i个过程调用第j个过程B[i][j]=0:表示第i个过程不调用第j个过程

Units[n]:过程所需内存量矩阵

123456101100020001013000011400000050000006000000层次分配算法base[i]:第i个过程局部数据区的基地址

allocated[i]:第i个过程局部数据区是否分配的标志

voidMakeFortranBlockAllocated(int

*Units,int*base,intNoOfBlocks){/*

NoOfBlocksindicatinghowmanyblocksthereare

*/inti

,j,k,Sum;int*allocated;/*usedtoindicateiftheblockisallocated*/allocated=(int*)malloc(sizeof(int)*NoOfBlocks);for(i=0;i<NoOfBlocks;i++)/*Initialarraysbaseandallocated*/{base[i]=0;allocated[i]=0;}for(j=0;j<NoOfBlocks;j++)for(i=0;i<NoOfBlocks;i++){Sum=0;for(k=0;k<NoOfBlocks;k++)Sum+=B[i][k];

/*tocheckoutifblockicallssomeblockwhichhasnotbeenallocated*

/if(!Sum&&!allocated[i])

{/*Sum=0meansblockicallsnoblockwhichhasnotbeenallocated;allocated[i]=0;meansblockiisnotallocated*/allocated[i]=1;printf(′′%d:%d-%d/n′′,i,base[i],base[i]+Units[i]-1);for(k=0;k<NoOfBlocks;k++)

if(B[k][i])/*b[k][i]!=0maensblockkcallsblocki*/{/*Sinceblockkcallsi,itmustbeallocatedafterblocki.Itmeansthebaseofblockkmustbegreaterthanbaseofblocki*/if(base[k]<base[i]+Units[i])base[k]=base[i]-Units[i];B[k][i]=0;/*SinceblockinhasbeenallocatedB[k][i]shouldbemodified*/}}}free(allocated);}7.1存储组织7.2静态存储分配7.3栈式存储分配7.4非局部数据的访问7.5堆式存储分配7.6符号表提纲有些语言使用过程、函数或方法作为用户自定义动作的单元,几乎所有针对这些语言的编译器都把它们的(至少一部分的)运行时刻存储以栈的形式进行管理,称为栈式存储分配当一个过程被调用时,该过程的活动记录被压入栈;当过程结束时,该活动记录被弹出栈这种安排不仅允许活跃时段不交叠的多个过程调用之间共享空间,而且允许以如下方式为一个过程编译代码:它的非局部变量的相对地址总是固定的,和过程调用的序列无关7.3栈式存储分配用来描述程序运行期间控制进入和离开各个活动的情况的树称为活动树树中的每个结点对应于一个活动。根结点是启动程序执行的main过程的活动在表示过程p的某个活动的结点上,其子结点对应于被p的这次活动调用的各个过程的活动。按照这些活动被调用的顺序,自左向右地显示它们。一个子结点必须在其右兄弟结点的活动开始之前结束活动树p(1,3)q(1,0)q(2,3)p(5,9)q(5,5)q(7,9)mq(1,9)rp(1,9)q(1,3)q(5,9)p(2,3)q(2,1)q(3,3)p(7,9)q(7,7)q(9,9)inta[11];

voidreadArray()/*将9个整数读入到a[1],…,a[9]中

*/{inti;…}intpartition(intm,intn){/*选择一个分割值v,划分a[m…n],使得a[m…p-1]小于v,a[p]=v,a[p+1…n]大于v。返回

p*/…

}voidquicksort(intm,intn){inti;if(n>m){i=partition(m,n);quicksort(m,i-1);quicksort(i+1,n);}}main(){readArray();a[0]=-9999;a[10]=9999;quicksort(1,9);}每个活跃的活动都有一个位于控制栈中的活动记录例:一个快速排序程序的概要mrmainint

a[11]rint

i活动树控制栈mq(1,9)rp(1,9)mainint

a[11]q(1,9)int

ip(1,9)int

i活动树控制栈mq(1,9)rp(1,9)q(1,3)p(1,3)mainint

a[11]q(1,9)int

ip(1,3)int

i活动树控制栈q(1,3)int

imq(1,9)rp(1,9)q(1,3)p(1,3)mainint

a[11]q(1,9)int

i活动树控制栈q(1,3)int

iq(1,0)q(1,0)int

i当一个过程是递归的时,常常会有该过程的多个活动记录同时出现在栈中mq(1,9)rp(1,9)q(1,3)p(1,3)mainint

a[11]q(1,9)int

i活动树控制栈q(1,3)int

iq(1,0)q(2,3)int

iq(2,3)q(2,1)q(3,3)p(2,3)q(5,9)q(5,5)p(5,9)q(7,9)q(7,7)q(9,9)p(7,9)

每个活跃的活动都有一个位于控制栈中的活动记录

活动树的根的活动记录位于栈底

程序控制所在的活动的记录位于栈顶

栈中全部活动记录的序列对应于在活动树中到达当前控制所在的活动结点的路径在调用者和被调用者之间传递的值一般被放在被调用者的活动记录的开始位置,这样它们可以尽可能地靠近调用者的活动记录固定长度的项被放置在中间位置控制连、访问链、机器状态字在早期不知道大小的项被放置在活动记录的尾部栈顶指针寄存器top_sp指向活动记录中局部数据开始的位置,以该位置作为基地址被调用者的活动记录控制链访问链和机器状态参数和返回值局部数据临时数据参数和返回值控制链访问链和机器状态局部数据临时数据...栈top_sp调用者的活动记录设计活动记录的一些原则过程调用和过程返回都需要执行一些代码来管理活动记录栈,保存或恢复机器状态等调用序列实现过程调用的代码段。为一个活动记录在栈中分配空间,并在此记录的字段中填写信息返回序列恢复机器状态,使得调用过程能够在调用结束之后继续执行一个调用代码序列中的代码通常被分割到调用过程(调用者)和被调用过程(被调用者)中。返回序列也是如此调用序列和返回序列

调用者计算实际参数的值

调用者将返回地址(程序计数器的值)放到被调用者的机器状态字段中。将原来的top-sp值放到被调用者的控制链中。然后,增加top-sp的值,使其指向被调用者局部数据开始的位置

被调用者保存寄存器值和其它状态信息

被调用者初始化其局部数据并开始执行……参数和返回值控制链访问链保存的机器状态局部数据和临时数据参数和返回值控制链访问链保存的机器状态局部数据和临时数据……top_sp被调用者的活动记录调用者的活动记录调用序列

被调用者将返回值放到与参数相邻的位置使用机器状态字段中的信息,被调用者恢复top-sp和其它寄存器,然后跳转到由调用者放在机器状态字段中的返回地址尽管top-sp已经被减小,但调用者仍然知道返回值相对于当前top-sp值的位置。因此,调用者可以使用那个返回值……参数和返回值控制链访问链保存的机器状态局部数据和临时数据参数和返回值控制链访问链保存的机器状态局部数据和临时数据……top_sp被调用者的活动记录调用者的活动记录返回序列调用者填写被调用者填写被调用者填写调用者更新被调用者恢复……参数和返回值控制链访问链保存的机器状态局部数据和临时数据参数和返回值控制链访问链保存的机器状态局部数据和临时数据……top_sp被调用者的活动记录调用者的活动记录调用者和被调用者之间的任务划分在现代程序设计语言中,在编译时刻不能确定大小的对象将被分配在堆区。但是,如果它们是过程的局部对象,也可以将它们分配在运行时刻栈中。尽量将对象放置在栈区的原因:可以避免对它们的空间进行垃圾回收,也就减少了相应的开销只有一个数据对象局部于某个过程,且当此过程结束时它变得不可访问,才可以使用栈为这个对象分配空间变长数据…控制链和保存的机器状态…指向a的指针指向c的指针指向b的指针…数组a数组b数组c控制链和保存的机器状态top_sptop被调用者q的活动记录调用者p的活动记录q的数组p的数组访问动态分配的数组7.1存储组织7.2静态存储分配7.3栈式存储分配7.4非局部数据的访问7.5堆式存储分配7.6符号表提纲7.4非局部数据的访问一个过程除了可以使用过程自身定义的局部数据以外,还可以使用过程外定义的非局部数据语言可以分为两种类型

支持过程嵌套声明的语言可以在一个过程中声明另一个过程例:Pascal

不支持过程嵌套声明的语言不可以在一个过程中声明另一个过程例:C例:C语言inta[11];

voidreadArray()/*将9个整数读入到a[1],…,a[9]中

*/{inti;…}intpartition(intm,intn){/*选择一个分割值v,划分a[m…n],使得a[m…p-1]小于v,a[p]=v,

a[p+1…n]大于v。返回

p*/…

}voidquicksort(intm,intn){inti;if(n>m){i=partition(m,n);quicksort(m,i-1);quicksort(i+1,n);}}main(){readArray();

a[0]=-9999;

a[10]=9999;quicksort(1,9);}不支持过程嵌套声明的语言过程中使用的非局部数据是全局数据例:Pascal语言支持过程嵌套声明的语言program

sort(input,output);

var

a:array[0..10]ofinteger;x:integer;

procedure

readarray;

var

i:integer;

begin…a…end{readarray};

procedure

exchange(i,j:integer);

begin

x=a[i];a[i]=a[j];a[j]=x;end{exchange};

procedure

quicksort(m,n:integer);

var

k,v:integer;

function

partition(y,z:integer):integer;

var

i,j:integer;

begin…a…v

…exchange(i,j)…end{partition};

begin…a…v…partition

…quicksort

…end{quicksort};

begin…a…readarray

…quicksort

…end{sort};过程中使用的非局部数据不一定都是全局数据,也可能是其它过程定义的数据例

procedure

A;

var

x:integer; …

procedure

B;

var

x:integer; …

procedure

C;

var

a:real;

begin…x

…end{C};

begin…end{B};

begin…end{A};名字x的当前出现对应的是哪个声明语句?在程序的不同部分可能有同一名字的互相独立的声明x的一个声明的作用域(scope)是指程序的一个区域,在其中对x的使用都指向这个声明如果仅通过阅读程序就可以确定一个声明的作用域,那么这个语言使用的是静态作用域。否则,这个语言使用的是动态作用域包括C及其同类语言在内的大多数语言使用静态作用域C语言的作用域规则是基于程序结构的,声明的作用域由该声明在程序中出现的位置隐含地决定稍后出现的语言,如C++、Java和

C#,也通过诸如public、private和protected等关键字的使用,提供对作用域的显式的控制静态作用域块是声明和语句的一个组合C使用括号“{”和“}”来界定一个块另一种为同一目的使用begin和end的方法可以追溯到Algol块结构语言中声明的静态作用域规则如果名字x的声明D属于块B,那么D的作用域包括整个B,但是以任意深度嵌套在B中、重新声明了x的所有块B'不在此作用域中例

procedure

A;

varx:integer; …

procedureB;

var

x:integer; …

procedure

C;

var

a:real;

begin…x…end{C};

begin…end{B};

begin…end{A};块结构语言中声明的静态作用域规则不支持过程嵌套声明的语言在C系列语言中,各个变量要么在某个函数内定义,要么在所有函数之外(全局地)定义一个全局变量v的作用域包含了该变量声明后出现的所有函数,但那些存在标识符v的局部定义的地方除外在一个函数内部声明的变量的作用域就是这个函数,或者如果该函数具有嵌套的语句块,这个变量的作用域可能是该函数的部分区域无过程嵌套声明时的静态作用域变量的存储分配和访问全局变量被分配在静态区,使用静态确定的地址访问它们其它变量一定是栈顶活动的局部变量。可以通过运行时刻栈的top_sp指针访问它们无过程嵌套声明时的数据访问根据块结构语言的静态作用域规则,只要过程a的声明包含过程b的声明,过程b就可以访问过程a中声明的对象program

sort

(input,output);

var

a:array[0..10]ofinteger;x:integer;

procedure

readarray;

var

i:integer;

begin…a…end{readarray};

procedure

exchange(i,j:integer);

begin

x=a[i];a[i]=a[j];a[j]=x;end{exchange};

procedure

quicksort(m,

n:integer);

var

k,v:integer;

function

partition(y,z:integer):integer;

var

i,j:integer;

begin…a…v

…exchange(i,

j)…end{partition};

begin…

a

v

…partition

…quicksort

…end{quicksort};

begin…a…readarray

…quicksort

…end{sort};有过程嵌套声明时的数据访问运行时如何访问在过程外声明的数据?过程的嵌套深度不内嵌在任何其它过程中的过程,设其嵌套深度为1如果一个过程p在一个嵌套深度为i的过程中定义,则设定p的嵌套深度为i+1变量的嵌套深度将变量声明所在过程的嵌套深度作为该名字的嵌套深度嵌套深度

过程 嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3program

sort(input,output);

var

a:array[0..10]ofinteger;x:integer;

procedure

readarray;

var

i:integer;

begin…a…end{readarray};

procedure

exchange(i,j:integer);

begin

x=a[i];a[i]=a[j];a[j]=x;end{exchange};

procedure

quicksort(m,n:integer);

var

k,v:integer;

function

partition(y,z:integer):integer;

var

i,j:integer;

begin…a…v

…exchange(i,j)…end{partition};

begin…a…v…partition

…quicksort

…end{quicksort};

begin…a…readarray

…quicksort

…end{sort};例静态作用域规则:只要过程b的声明嵌套在过程a的声明中,过程b就可以访问过程a中声明的对象可以在相互嵌套的过程的活动记录之间建立一种称为访问链(Accesslink)的指针,使得内嵌的过程可以访问外层过程中声明的对象如果过程b在源代码中直接嵌套在过程a中(b的嵌套深度比a的嵌套深度多1),那么b的任何活动中的访问链都指向最近的a的活动访问链(AccessLinks)sq(1,9)rp(1,9)q(1,3)q(1,0)p(1,3)q(2,3)q(5,9)eeprogram

sort(input,output);

var

a:array[0..10]ofinteger;x:integer;

procedure

readarray;

var

i:integer;

begin…a…end{readarray};

procedure

exchange(i,j:integer);

begin

x=a[i];a[i]=a[j];a[j]=x;end{exchange};

procedure

quicksort(m,n:integer);

var

k,v:integer;

function

partition(y,z:integer):integer;

var

i,j:integer;

begin…a…v

…exchange(i,j)…end{partition};

begin…a…v…partition

…quicksort

…end{quicksort};

begin…a…readarray

…quicksort

…end{sort};例s活动树sa访问链控制栈

过程 嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3sr活动树控制栈

过程 嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3sa访问链ri访问链r中的访问链指向s的活动记录,这不是因为s调用了r,而是因为在程序中,s是r外围的最靠近r的嵌套函数sq(1,9)rp(1,9)活动树sa访问链控制栈

过程 嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3q(1,9)v访问链p(1,9)i,j访问链ee访问链sq(1,9)rp(1,9)q(1,3)p(1,3)活动树

过程 嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3sa访问链控制栈q(1,9)v访问链q(1,3)v访问链p(1,3)i,j访问链eee访问链假定栈顶的过程b的嵌套深度是nb且b需要访问x,而x是在某个包围b的嵌套深度为na的过程a中定义的一个元素(na≤nb)。可以按如下方法找到x从位于栈顶的b的活动记录开始,沿着访问链进行nb

-na次从一个活动记录到另一个活动记录的查找,最终找到a的活动记录。这一定是当前出现在栈中离b最近的a的活动记录。这个活动记录中包括要找的元素xsa访问链q(1,9)v访问链q(1,3)v访问链p(1,3)i,j访问链

过程嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3利用访问链访问非局部数据的方法建立访问链的代码属于调用序列的一部分假设嵌套深度为nx的过程x调用嵌套深度为ny的过程y

(x→y)nx<ny的情况(外层调用内层)y一定是直接嵌套在x中(例如:s→q,

q→p),因此,ny=nx+1在调用代码序列中增加一个步骤:(利用控制链)在y的访问链中放置一个指向x的活动记录的指针sa访问链q(1,9)v访问链q(1,3)v访问链p(1,3)i,j访问链e访问链

过程嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3访问链的建立sa访问链q(1,9)v访问链q(1,3)v访问链p(1,3)i,j访问链e访问链

过程嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3建立访问链的代码属于调用序列的一部分假设嵌套深度为nx的过程x调用嵌套深度为ny的过程y

(x→y)nx<ny的情况(外层调用内层)nx=ny的情况(本层调用本层)递归调用(例如:q→q)被调用者的活动记录的访问链与调用者的活动记录的访问链是相同的,可以直接复制访问链的建立sa访问链q(1,9)v访问链q(1,3)v访问链p(1,3)i,j访问链e访问链

过程嵌套深度sort 1

readarray 2

exchange 2

quicksort 2

partition 3建立访问链的代码属于调用序列的一部分假设嵌套深度为nx的过程x调用嵌套深度为ny的过程y

(x→y)nx<ny的情况(外层调用内层)nx=ny的情况(本层调用本层)nx>ny的情况(内层调用外层,如:p→e)过程x必定嵌套在某个过程z中,而z中直接定义了过程y从x的活动记录开始,沿着访问链经过nx

-ny

+1步就可以找到离栈顶最近的z的活动记录。y的访问链必须指向z的这个活动记录访问链的建立7.1存储组织7.2静态存储分配7.3栈式存储分配7.4非局部数据的访问7.5堆式存储分配7.6符号表提纲堆式存储分配是把连续存储区域分成块,当活动记录或其它对象需要时就分配块的释放可以按任意次序进行,所以经过一段时间后,对可能包含交错的正在使用和已经释放的区域堆式存储分配链头指针FREEA已占用块记录表堆式存储分配的示意图申请设当前自由块总长为M,欲申请长度为n如果存在若干个长度大于或等于n的存储块,可按以下策略之一进行存储分配取长度m满足需求的第1个自由块,将长度为m-n的剩余部分仍放在自由链中取长度m满足需求的最小的自由块取长度m满足需求的最大的自由块如果不存在长度大于或等于n的存储块如果M≥n,将自由块在堆中进行移位和重组(对各有关部分都需作相应的修改,是一件十分复杂和困难的工作)如果M<n,则应采用更复杂的策略来解决堆的管理问题申请设当前自由块总长为M,欲申请长度为n如果存在若干个长度大于或等于n的存储块,可按以下策略之一进行存储分配释放只需将被释放的存储块作为新的自由块插入自由链中,并删除已占块记录表中相应的记录即可申请为实现堆式存储管理须完成大量的辅助操作如排序、查表、填表、插入、删除、……其空间和时间的开销较大7.1存储组织7.2静态存储分配7.3栈式存储分配7.4非局部数据的访问7.5堆式存储分配7.6符号表提纲符号表的组织为每个作用域(程序块)建立一个独立的符号表7.6符号表program

sort(input,output);

vara:array[0..10]ofinteger;

x:integer;

procedure

readarray;

var

i:integer;

begin

…a…

end;

procedure

exchange(i,j:integer);

begin

x=a[i];a[i]=a[j];a[j]=x;end;

procedure

quicksort(m,n:integer);

var

k,v:integer;

function

partition(y,z:integer):integer;

var

i,j:integer;

begin

…a…v…exchange(i,j)…end;

begin

…a…v…partition…quicksort…quicksort…end

;

begin

…a…readarray…quicksort…end;kint0vint4jint4iint0header48sortreadarraryaarray0xint44readarrayexchangeheader0exchangeheader8quicksortheader8partitionpartitionquicksortheader4

iint0例访问栈中的非局部数据kint0vint4jint4iint0header48sortreadarraryaarray0xint44readarrayexchangeheader0exchangeheader8quicksortheader8partitionpartitionquicksortheader4

iint0sa访问链q(1,9)v访问链q(1,3)v访问链p(1,3)i,j访问链实际上,这种为每个过程或作用域建立的符号表与编译时的活动记录是对应的。一个过程的非局部名字的信息可以通过扫描外围过程的符号表而得到符号表的使用访问栈中的非局部数据构造访问链kint0vint4jint4iint0header48sortreadarraryaarray0xint44readarrayexchangeheader0exchangeheader8quicksortheader8partitionpartitionquicksortheader4

iint0sa访问链q(1,9)v访问链q(1,3)v访问链p(1,3)i,j访问链e访问链x→y

nx<ny的情况(例:

s→q,

q→p)nx=ny的情况(例:

q→q)nx>ny的情况(例:p→e)符号表的使用当在某一层的声明语句中识别出一个标识符(id的定义性出现)时,以此标识符查相应于本层的符号表如果查到,则报错并发出诊断信息“id重复声明”否则,在符号表中加入新登记项,将标识符及有关信息填入当在可执行语句部分扫视到标识符时(id的应用性出现)首先在该层符号表中查找该id,如果找不到,则到直接外层符号表中去查,如此等等,一旦找到,则在表中取出有关信息并作相应处理如果查遍所有外层符号表均未找到该id,则报错并发出诊断信息“id未声明”标识符的基本处理方法嵌套过程声明语句的文法 P

D

D

D

D|procid;D

S|id:T;在允许嵌套过程声明的语言中,局部于每个过程的名字可以使用第6章介绍的方法分配相对地址;当看到嵌套的过程p时,应暂时挂起对外围过程q声明语句的处理符号表的建立P

M

D

{addwidth(top(tblptr),top(offset));

pop(tblptr);

pop(offset);}M

{t=mktable(nil);

push(t,tblptr);

push(0,offset);}D

D1

D2Dp

procid;N

D1

S{t=top(tblptr);

addwidth(t,top(offset));

pop(tblptr);

pop(offset);

enterproc(top(tblptr),id.lexeme,t);}Dv

id:T;{enter(top(tblptr),id.lexeme,T.type,top(offset));

top(offset)

=top(offset)+T.width;}N

{t=mktable(top(tblptr));

push(t,tblptr);push(0,offset);}mktable(previous)创建一个新的符号表,并返回指向新表的指针。参数previous指向先前创建的符号表(外围过程的符号表)enter(table,name,type,offset)在table指向的符号表中为名字name建立一个新表项addwidth(table,width)将table指向的符号表中所有表项的宽度之和width记录在符号表的表头中enterproc(table,name,newtable)在table指向的符号表中为过程name建立一条记录,newtable指向过程name的符号表嵌套过程声明语句的SDTprogram

sort(input,output);

vara:array[0..10]ofinteger;

x:integer;

procedure

readarray;

var

i:integer;

begin

…a…

end;

procedure

exchange(i,j:integer);

begin

x=a[i];a[i]=a[j];a[j]=x;end;

procedure

quicksort(m,n:integer);

var

k,v:integer;

function

partition(y,z:integer):integer;

var

i,j:integer;

begin

…a…v…exchange(i,j)…end;

begin

…a…v…partition…quicksort…quicksort…end

;

begin

…a…readarray…quicksort…end;program

sort;

vara:int[11];x:int;

proc

readarray;

var

i:int;{…}

proc

exchange;{…}

proc

quicksort;

var

k,v:int;

func

partitin;

var

i,j:int;{…}{…}{…}例headersortP

M

D

{addwidth(top(tblptr),top(offset));

pop(tblptr);pop(offset);}M

{t=mktable(nil);

push(t,tblptr);push(0,offset);}D

D1

D2Dp

procid;N

D1

S{t=top(tblptr);addwidth(t,top(offset));

pop(tblptr);pop(offset);enterproc(top(tblptr),id.lexeme,t);}Dv

id:T;{enter(top(tblptr),id.lexeme,T.type,top(offset));

top(offset)

=top(offset)+T.width;}N

{t=mktable(top(tblptr));push(t,tblptr);push(0,offset);}readarraryheaderprogram

sort;

vara:int[11];x:int;

proc

readarray;

var

i:int;{…}

proc

exchange;{…}

proc

quicksort;

var

k,v:int;

func

partitin;

var

i,j:int;{…}{…}{…}header

niloffsettblptraarray00044xint44480iint044readarray例headersortP

M

D

{addwidth(top(tblptr),top(offset));

pop(tblptr);pop(offset);}M

{t=mktable(nil);

push(t,tblptr);push(0,offset);}D

D1

D2Dp

procid;N

D1

S{t=top(tblptr);addwidth(t,top(offset));

pop(tblptr);pop(offset);enterproc(top(tblptr),id.lexeme,t);}Dv

id:T;{enter(top(tblptr),id.lexeme,T.type,top(offset));

top(offset)

=top(offset)+T.width;}N

{t=mktable(top(tblptr));push(t,tblptr);push(0,offset);}readarraryheaderprogram

sort;

vara:int[11];x:int;

proc

readarray;

var

i:int;{…}

proc

exchange;{…}

proc

quicksort;

var

k,v:int;

func

partitin;

var

i,j:int;{…}{…}{…}header

niloffsettblptraarray00040xint4448iint04readarrayexchangeheader00exchange例headersortP

M

D

{addwidth(top(tblptr),top(offset));

pop(tblptr);pop(offset);}M

{t=mktable(nil);

push(t,tblptr);push(0,offset);}D

D1

D2Dp

procid;N

D1

S{t=top(tblptr);addwidth(t,top(offset));

pop(tblptr);pop(offset);enterproc(top(tblptr),id.lexeme,t);}Dv

id:T;{enter(top(tblptr),id.lexeme,T.type,top(offset));

top(offset)

=top(offset)+T.width;}N

{t=mktable(top(tblptr));push(t,tblptr);push(0,offset);}readarraryheaderprogram

sort;

vara:int[11];x:int;

proc

readarray;

var

i:int;{…}

proc

exchange;{…}

proc

quicksort;

var

k,v:int;

func

partitin;

var

i,j:int;{…}{…}{…}header

niloffsettblptraarray00040xint4448iint04readarrayexchangeheader0exchangeheaderquicksort0k

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论