pl/0程序书写技巧

对于pl/0程序的编写,初学者可能会出现许多的错误,例如分号的错误添加抑或是遗漏,对于数据类型的错误理解,都可能导致运行出错。现在简单说一下题主所犯的错以及改正方法。

在pl/0程序中数据类型只有整型,用var声明;数据结构只有简变和常数;标识符的有效长度为10;过程调用中是没有参数的,并且最多能够嵌套三层;一层由begin和end标志,最后一个end要加“.”(非常重要)。这些规则都是在我们编写时要注意的,我就在实验中犯过if语句前一个end没有加“;”的错误。

下面是一个实例,用于比较n!与2^m次方的大小的pl/0程序:

var n,m,c,a,b;

procedure p;
begin
   while n>0 do
      begin
         a:=n*a;
         n:=n-1;
      end;
end;

procedure q;
begin
   while m#0 do
      begin
         b:=2*b;
         m:=m-1;
      end;
   if a > b then
      begin
         c:=1;
      end;
end;

begin 
   read(n);
   read(m);
   a:=1;
   b:=1;
   c:=0;
   call p;call q;
   write(a);
   write(b);
   write(c); 
end.

代码运行方式如下:先读取输入的数字n和m,然后初始化一众变量,先后调用procedure p以及procedure q,分别求出n的阶乘 以及2的m次方,然后输出n的阶乘 以及2的m次方两个数字以及它们比较的结果,当前者大于后者时,输出数字1,另外所有情况输出数字0。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
program PL0 (input,output); (*PL/0 compiler with code generation*) (*Program 5.6 in Algorithms + Data Structures = Programs*) (*Almost identical with the version in Compilerbau*) (*Author: Niklaus Wirth*) label 99; (*定义标号*) const (*定义常量*) norw = 11; (*保留字最大长度*) txmax = 100; (*符号表最大记录数*) nmax = 14; (*数值型数据所含字符的最大长度*) al = 10; (*标识符最大长度*) amax = 2047; (*最大地址*) levmax = 3; (*分程序最大递归深度*) cxmax = 200; (*目标代码数组大小*) type (*定义类型*) symbol = (nul,ident,number,plus,minus,times,slash,oddsym, eql,neq,lss,leq,gtr,geq,lparen,rparen,comma,semicolon, period,becomes,beginsym,endsym,ifsym,thensym, whilesym,dosym,callsym,constsym,varsym,procsym); (*单词符号机内表示*) alfa = packed array[1..al] of char; (*标识符类型*) object = (constant,variable,procedure); (*类型标识符*) symset = set of symbol; (*式后字集合类型*) fct = (lit,opr,lod,sto,cal,int,jmp,jpc); (*目标代码中的操作码类型*) instruction = packed record f: fct; (*操作码*) l: 0..levmax; (*层差*) a: 0..amax; (*相对地址*) end; (* lit 0,a: 取常量a opr 0,a: 执行a 运算 lod l,a: 取变量(相对地址为a ,层差为l) sto l,a: 存变量 (相对地址为a ,层差为l) cal l,a: 调用过程(入口地址为a ,层差为l) int 0,a: 运行栈S 的指针值增加 a jmp 0,a: 转移到指令地址a 处 jpc 0,a: 条件转移到指令地址a 处*) var ch: char; (*当前字符*) sym: symbol; (*当前单词符号*) id: alfa; (*当前标识符*) num: integer;(*当前数*) cc: integer; (*行字符计数*) ll: integer; (*行长*) kk,err: integer; cx: integer; (*目标代码存放数组下标*) line: array[1..81] of char; (*行缓冲区*) a: alfa; code: array[0..cxmax] of instruction; (*目标代码区*) word: array[1..norw] of alfa; (*保留字表*) wsym: array[1..norw] of symbol; (*保留字机内表示表*) ssym: array[char] of symbol; (*运算符、界限符机内表示表*) mnemonic: array[fct] of packed array[1..5] of char; declbegsys,statbegsys,facbegsys: symset; table: array[0..txmax] of record name: alfa; case kind: object of constant: (val: integer); variable,procedure: (level,adr: integer) end; (*符号表*) procedure error(n: integer); (*报错程序*) begin writeln('****',' ':cc-1,'^',n:2); err:= err+1 end; (*error*)
在《算法+数据结构=程序》一书中,Niklaus Wirth 设计的 PL/0 语言编译器分成两部分,把源语言翻译成中间语言的编译器和中间语言解释器,编译器用的是递归下降的预测分析方法中间语言是一种栈机器代码,其指令集是根据 PL/0 语言的需要来设计的。编译器源码及测试程序可从。一条指令由三个域组成: (1)操作码 f:上面已经列出了所有 8 种操作码。 (2)层次差 l:这里的层次差就是 5.3.2 节介绍嵌套深度时的 n p − n a 。该域仅用于存取指令和调用指令。 (3)多用途 a:在运算指令中,a 的值用来区分不同的运算;在其他情况,a 或是一个数(lit,int),或是一个程序地址(jmp,jpc,cal),或是一个数据地址(lod,sto)。 编译器PL/0 源程序进行一遍扫描,并逐行输出源程序。在源程序无错的情况下,编译器每编译完一个分程序,就列出该分程序的代码,这由编译器的 listcode 过程完成。每个分程序的第一条指令是 jmp 指令,其作用是绕过该分程序声明部分产生的代码(即绕过内嵌过程的代码)。listcode 过程没有列出这条代码。 解释器是编译器中的一个过程,若源程序无错,则编译结束时调用解释过程 interpret。由于 PL/0 语言没有输出语句,解释器按执行次序,每遇到对变量赋值时就输出该值。 由于 PL/0 语言是过程嵌套语言,因此程序运行时,活动记录栈中每个活动记录需要包含控制链和访问。活动记录栈的栈顶以外的存储空间作为代码执行过程中所需要的计算栈,无需另外设立计算栈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值