编译原理 | 实验任务一:在计算机上实现PL0语言的编译程序

本文介绍了如何在计算机上实现PL0语言的编译程序。首先,找到并安装Free Pascal编译系统,使用VSCode进行编辑。接着,对PL0编译程序进行修改和调试,包括格式调整、符号修改等。然后,建立输入和输出文件,读取PL0源程序,并生成中间代码。在编译过程中,增加了对输入输出文件的操作,并扩展了词法分析以支持更多运算符。最后,发现并修复了getsym中判断数字的错误。
摘要由CSDN通过智能技术生成
代码及结果:task1
任务二博客:编译原理 | 实验任务二:扩展Read和Write语句

1 找到PASCAL编译系统

下载安装free pascal,设置环境变量,然后用vscode编辑。
参考资料:在windows命令行下编译运行Pascal程序


2 在PASCAL系统上运行PL0编译程序,需要对PL0编译程序作一些修改、调试

1.改格式(缩进、注释)

2.符号修改

~ -> not//~这个符号打不出来,反正就是非的意思

//procedure和object在pascal中是关键字,所以分别使用proceduree和objectt替代
object -> objectt;
procedure -> proceduree;

cc—1 -> cc-1;
↑ -> ^;
≤ -> <=;
≠ -> <>

3. 注释掉不必要的(其实是报错的)语句,如

在这里插入图片描述
直接注释掉(或删掉)
在这里插入图片描述

4.标号99原来是用于退出程序的,由于不支持跨过程的跳转,所以直接退出
在这里插入图片描述

//procedure  gen(x : fct; y, z : integer);
    	if cx > cxmax then 
        begin 
            write('PROGRAM TOO LONG'); 
            exit
            //goto 99
        end;
//procedure  getch ; 

        if eof(fin) then {
   如果已到文件尾}
        begin
            writeln('PROGRAM INCOMPLETE'); 
            exit;
            //goto 99
        end;

//主程序
//99 : writeln
    writeln;

5.现在暂时没有错误了
在这里插入图片描述


3 建立输入文件和输出文件

在输入文件中存放PL0源程序
在这里插入图片描述
在输出文件中存放PL0源程序被编译后产生的中间代码和运行数据
在这里插入图片描述


4 通过输入文件输入PL0源程序,在输出文件中产生源程序的中间代码, 然后运行该中间代码, 在输出文件中产生运行数据

1.增加变量fin和fout,以命令行形式读取和写入文件
在这里插入图片描述

//{全局变量定义}
//var
fin : text;       {
   源代码文件}
fout : text;      {
   输出文件}
...

begin  {
   主程序}
    assign(fin,paramstr(1));
    assign(fout,paramstr(2));	{
   将命令行参数str变量赋值给文件变量}
    reset(fin);
    rewrite(fout);	{
   打开输入输出文件}
    ...
    //99 : writeln
    writeln;
    close(fin);
    close(fout);

2.exit时关闭文件

//getch
		begin
            writeln('PROGRAM INCOMPLETE'); 
            close(fin);
            close(fout);
            exit;
            //goto 99
        end;

//gen
		begin 
            write('PROGRAM TOO LONG'); 
            close(fin);
            close(fout);
            exit
            //goto 99
        end;

3.将所有input改成fin,有read的地方都改成从fin文件读入,有write的地方都改成写到fout文件:

//getch
	if eof(fin) then {
   如果已到文件尾}
	...
	while not eoln(fin) do {
   如果不是行末}
        begin
            ll := ll + 1; {
   将行缓冲区的长度+1}
            read(fin, ch); {
   从源文件中读取一个字符到ch中}
            write(fout, ch);{
   输出ch到输出文件中}
            line[ll] := ch  {
   把这个字符放到当前行末尾}
        end;
        writeln(fout); {
   换行}
        readln(fin);{
   从源文件下一行开始读取}
        ll := ll + 1; {
   将行缓冲区的长度+1}
        line[ll] := ' ' {
    pro
在《算法+数据结构=程序》一书中,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、付费专栏及课程。

余额充值