PL/0语言编译程序设计1(C语言)

本文地址:http://www.cnblogs.com/archimedes/p/pl0-compiler1.html,转载请注明源地址。

PL/0简介

以下内容摘自维基:

PL/0,is similar to but much simpler than the general-purpose programming language Pascal, intended as an educational programming language. It serves as an example of how to construct a compiler. It was originally introduced in the book, Algorithms + Data Structures = Programs, by Niklaus Wirth in 1975. It features quite limited language constructs: there are no real numbers, very few basic arithmetic operations and no control-flow constructs other than "if" and "while" blocks. While these limitations make writing real applications in this language impractical, it helps the compiler remain compact and simple.

翻译如下:

PL/0语言,作为一个教育用的编程语言,和通用编程语言Pascal有些类似但是要简单得多。作为如何构建一个编译器的一个例子。它最初是出自Niklaus Wirth于1975年写的《算法+数据结构=程序》一书中。它具有非常有限的语言构造:没有实数,只有很少量的基本算术运算,除了"if"和"while"语句块以外没有其他的控制流。虽然这些限制使这种语言在实际应用中受到限制,但它却有助于编译器保持紧凑和简单。

PL/0语言是PASCAL语言的子集

同PASCAL

作用域规则(内层可引用包围它的外层定义的标识符),上下文约束,过程可嵌套定义,可递归调用

子集

数据类型,只有整型

数据结构 ,只有简变和常数

数字最多为14位

标识符的有效长度是10

语句种类

过程最多可嵌套三层

从上面的叙述可以看出,熟悉PL/0的相关指令,并能用其他语言(我选择C语言)来写一个简单的解释器,在某种程度上掌握一些编译器的原理,提高自身的编程能力

PL/0程序示例

举几个实例更加的直观:

1、计算最大公约数

var m, n, r, q;
{ 计算m和n的最大公约数 }
procedure  gcd;
    begin
        while r#0  do
             begin
                 q := m / n;
                  r := m - q * n;
                 m := n;
                 n := r;
             end
   end;
begin
     read(m);
     read(n);
     { 为了方便,规定m >= n }
     if m < n then
         begin
              r := m;
              m := n;
              n := r;
         end;
     begin
         r:=1;
         call gcd;
         write(m);
     end;
end.

2、计算 sum = 1! + 2 ! + ... + n!  (n从控制台读入)

var n, m, fact, sum;
{ 递归计算 fact = m! }
procedure factorial;
    begin
        if m > 0 then
            begin
                fact := fact * m;
                m := m - 1;
                call factorial;
            end;
    end;
begin
     {读入n }
     read(n);
     sum := 0;
     while n > 0 do
          begin
               m := n;
               fact := 1;
               call factorial;
               sum  := sum + fact;
               n := n - 1;
          end;
          {输出n! }
          write(sum);
end.

对于上面的代码,熟悉Pascal语言的同学应该很熟悉,没错,pl/0就是简化版本的pascal,为了降低设计编译程序的难度而故意为之专供教学用的。

PL/0编译程序

PL/0编译系统

类pcode代码指令的结构

PL/0编译程序所产生的目标代码是一个假想栈式计算机的汇编语言,可称为类PCODE指令代码,它不依赖具体计算机,其指令集极为简单,指令格式也很单纯,其格式如下:

f l a

其中f代表功能码,l表示层次差,也就是变量或过程被引用的分程序与说明该变量或过程的分程序之间的层次差。a的含意对不同的指令有所区别,对存取指令表示位移量,而对其它的指令则分别有不同的含义,见下面对每条指令的解释说明。

目标指令有8条:

① LIT:将常量值取到运行栈顶。a域为常数值。

② LOD:将变量放到栈顶。a域为变量在所说明层中的相对位置,l为调用层与说明层的层差值。

③ STO:将栈顶的内容送入某变量单元中。a,l域的含意同LOD指令。

④ CAL:调用过程的指令。a为被调用过程的目标程序入口地址,l为层差。

⑤ INT:为被调用的过程(或主程序)在运行栈中开辟数据区。a域为开辟的单元个数。

⑥ JMP:无条件转移指令,a为转向地址。

⑦ JPC:条件转移指令,当栈顶的布尔值为非真时,转向a域的地址,否则顺序执行。

⑧ OPR:关系运算和算术运算指令。将栈顶和次栈顶的内容进行运算,结果存放在次栈顶,此外还可以是读写等特殊功能的指令,具体操作由a域值给出。(详见解释执行程序)。

pcode代码指令的详细解释(指令功能表)

LIT 0 a 将常数值取到栈顶,a为常数值
LOD l a 将变量值取到栈顶,a为偏移量,l为层差
STO l a 将栈顶内容送入某变量单元中,a为偏移量,l为层差
CAL l a 调用过程,a为过程地址,l为层差
INT 0 a 在运行栈中为被调用的过程开辟a个单元的数据区
JMP 0 a 无条件跳转至a地址
JPC 0 a 条件跳转,当栈顶布尔值非真则跳转至a地址,否则顺序执行
OPR 0 0 过程调用结束后,返回调用点并退栈
OPR 0 1 栈顶元素取反
OPR 0 2 次栈顶与栈顶相加,退两个栈元素,结果值进栈
OPR 0 3 次栈顶减去栈顶,退两个栈元素,结果值进栈
OPR 0 4 次栈顶乘以栈顶,退两个栈元素,结果值进栈
OPR 0 5  次栈顶除以栈顶,退两个栈元素,结果值进栈 
OPR 0 6  栈顶元素的奇偶判断,结果值在栈顶
OPR 0 7  
OPR 0 8 次栈顶与栈顶是否相等,退两个栈元素,结果值进栈 
OPR 0 9 次栈顶与栈顶是否不等,退两个栈元素,结果值进栈 
OPR 0 10 次栈顶是否小于栈顶,退两个栈元素,结果值进栈
OPR 0 11 次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈 
OPR 0 12 次栈顶是否大于栈顶,退两个栈元素,结果值进栈 
OPR 0 13 次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈 
OPR 0 14 栈顶值输出至屏幕 
OPR 0 15 屏幕输出换行 
OPR 0 16 从命令行读入一个输入置于栈顶

一个PL/0程序与目标代码类pcode指令的映射例子:


PL/0编译程序总体结构

PL/0编译程序的组织:一个以语法、语义分析程序为中心的单遍编译程序

参考资料

《编译原理》--清华大学出版社

时间: 2024-10-06 00:45:10

PL/0语言编译程序设计1(C语言)的相关文章

C语言及程序设计 例程 - C语言程序初体验

让程序会计算:求a和b两个数之和 #include <stdio.h> int main( ) {     int a,b,sum;     scanf("%d %d", &a, &b);     sum=a+b;     printf("%d\n", sum);     return 0; } 用户界面友好(或罗里罗嗦)的程序 #include <stdio.h> int main( ) {     int a,b,sum;

14. Go 语言编译与工具

Go 语言编译与工具 Go 语言的工具链非常丰富,从获取源码.编译.文档.测试.性能分析,到源码格式化.源码提示.重构工具等应有尽有. 在 Go 语言中可以使用测试框架编写单元测试,使用统一的命令行即可测试及输出测试报告的工作.基准测试提供可自定义的计时器和一套基准测试算法,能方便快速地分析一段代码可能存在的 CPU 耗用和内存分配问题.性能分析工具可以将程序的 CPU 耗用.内存分配.竞态问题以图形化方式展现出来. go build命令(go语言编译命令)完全攻略 Go语言的编译速度非常快.G

编译原理 实验1 PL/0语言词法分析

PL/0语言词法分析 一. 实验目的 通过完成词法分析程序,了解词法分析的过程.编制一个读单词程序,对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,即基本保留字.标识符.常数.运算符.界符五大类. 二. 实验环境 操作系统:window xp 编写环境:visual c++ .c-free.turbo c 编写语言:c语言 分析语言:PL/0 三. 实验内容 对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,其词法描述如下: (1) 关键字:

PL/0语言编译器的设计与实现

一.设计任务 1.1程序实现要求 PL/0语言可以看成PASCAL语言的子集,它的编译程序是一个编译解释执行系统.PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关. PL/0的编译程序和目标程序的解释执行程序都是用JAVA语言书写的,因此PL/0语言可在配备JDK的任何机器上实现. 其编译过程采用一趟扫描方式,以语法分析程序为核心,词法分析和代码生成程序都作为一个独立的过程,当语法分析需要读单词时就调用词法分析程序,而当语法分析正确需要生成相应的目标代码时,则调用代码生成程序. 用

PL/0语言词法分析器

前言:关于词法分析的基础知识的介绍可以看一下这篇博客,我再累述估计也不会有这篇讲的清楚QAQ. https://www.cnblogs.com/yanlingyin/archive/2012/04/17/2451717.html    默认大家已经对词法分析有了基本的了解了. 一:下面讨论PL/0语言的词法分析器的单词结构 1.关键字 关键字(共11个):空格分隔列表如下 begin  end  if  then  while  do  const  var  call  procedure  

C语言程序设计-第1章 程序设计和C语言

所谓程序,就是一组计算机能识别和执行的指令. 每一条指令使计算机执行特定的操作.一个特定的指令序列,用来完成一定的功能. 计算机的本质是程序的机器,程序和指令是计算机系统中最基本的概念. 计算机能直接识别和接受的二进制代码称为机器指令(machine instruction),机器指令的集合就是该计算机的机器语言(machine language).为了克服机器语言的难学难写难记难检查难修改难推广使用的缺点,人们创造出了符号语言(symbolic language),它用一些英文字母和数字表示一

第1章 程序设计和C语言

1.1什么是计算机程序 1.2什么是计算机语言 1.机器语言 2.符号语言=符号汇编语言=汇编语言 3.高级语言 1.源程序:高级语言写的程序 2.目标程序:机器指令的程序 3.高级语言发展阶段:1.非结构化的语言(BASIC,FORTRAN,ALGOL) 2.结构化语言(QBASIC,FORTRAN 77,C语言) 3.面向对象的语言(C++,C#,Visual Basic,Java) 1.3 C语言的发展及其特点 1.本书的叙述以C 99标准为依据 2.C 语言允许直接访问物理地址,能进行位

网易云课堂程序设计入门--C语言第七周:指针与字符串学习笔记

====================================== 第七周:指针与字符串学习笔记 网易云课堂 程序设计入门–C语言 指针与字符串 学习笔记 ====================================== 7-1指针初步 7-1-1类型大小与取地址运算 sizeof是一个运算符 给出某个变量货类型在内存中所占据的字节数 sizeof(int); sizeif(i); double变量在内存中占据的空间是int变量的两倍 { int a; a =6; prin

程序设计入门——C语言 习题汇总

?? 中国大学MOOC 程序设计入门--C语言 翁恺 公告 评分标准 课件 测验与作业 考试 讨论区 教材与参考资料 分享到 帮助中心 测验与作业 次汇总由CSDN-fjinhao原创,转载请注明来源,此汇总由于本人 能力有限,欢迎各位程序爱好者来此讨论交流,给予指正,本人 联系邮箱[email protected],谢谢. 查看帮助 老师还没有发布测试和作业,请耐心等待 第1周:计算   第1周编程练习 截止时间:2015年5月4日 0:00 前往作业 作业类型 Online Judge作