PL0程序设计语言

PL0被视为Pascal语言的简化版,常用于编译原理教学。编译程序包括两部分:生成中间代码及显示运行时栈数据,以及添加read和write功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PL0语言可看成是Pascal[1]语言的子集,它的编译程序是一个编译解释执行系统。

PL/0的目标程序为假象栈试计算机的汇编语言,与具体计算机无关。

编译原理的课程作业,就是实现一个PL0的编译程序,分两个任务。第一个任务是生成中间代码以及输出运行过程的栈中数据,第二个任务在第一个任务的基础上实现PL0的read和write函数。

program pl0(input, output);
    {任务一的代码实现}
     
    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;
         objects=(constant,variable,procedur);
         {procedure和object在pascal中是关键字,所以分别使用procedur和object替代}
         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;
    var fa:text;			   {文本文件fa用于列出中间程序}
        srccode,data:text;	   {文本文件srccode用于列出源代码、data用于记录运行数据}
        ch:char;               {最近读到的字符}
        sym:symbol;            {最近读到的符号}
        id:alfa;               {最近读到的标识符}
        num:integer;           {最近读到的数}
        cc:integer;            {字符计数}
        ll:integer;            {行长}
        kk: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:objects of
                  constant:(val:integer);
                  variable,procedur:(level,adr,size:integer)
              end;
        fin,fout:text;
        fname:string;
        err:integer;
        endf:boolean;
     
    procedure error(n:integer);
    begin
      writeln('****',' ':cc-1,'!',n:2);
      writeln(srccode,'****','':cc-1,'!',n:2);
      err:=err+1;
    end; {error}
     
    procedure exitp;
    begin
      endf:=true;
      close(fin);
      writeln;
      exit;
    end;
     
    procedure getsym;
    var i,j,k:integer;
     
      procedure getch;
      begin
        if cc=ll then begin
          if eof(fin) then begin
             write('program incomplete');
             close(fin);
             writeln;
             exitp;
           (*  goto 99;*)
          end;
          ll:=0;
          cc:=0;
          write(cx:5,' ');
          write(srccode,cx:5,' ');
          while not eoln(fin) do begin
            ll:=ll+1;
            read(fin,ch);
            write(ch);
            write(srccode,ch);
            line[ll]:=ch;
          end;
          writeln;
          ll:=ll+1;
          line[ll]:=' ';
          readln(fin);
          writeln(srccode);
        end;
        cc:=cc+1;
        ch:=line[cc];
      end; {getch}
     
    begin {getsym}
      while ch=' ' do getch;
      if ch in ['a'..'z'] then begin
         k:=0;
         repeat
           if k<al then begin
              k:=k+1;
              a[k]:=ch;
           end;
           getch;
         until not(ch in ['a'..'z','0'..'9']);
         if k>=kk then kk:=k
         else repeat
                a[kk]:=' ';
                kk:=kk-1;
              until kk=k;
         id:=a;
         i:=1;
         j:=norw;
         repeat
           k:=(i+j) div 2;
           if id<=word[k] then j:=k-1;
           if id>=word[k] then i:=k+1;
         until i>j;
         if i-1>j then sym:=wsym[k] else sym:=ident;
      end else if ch in ['0'..'9'] then begin 
        k:=0;
        num:=0;
        sym:=number;
        repeat
          num:=10*num+(ord(ch)-ord('0'));
          k:=k+1;
          getch;
        until not(ch in['0'..'9']);
        if k>nmax then error(30);
      end else if ch=':' then begin
        getch;
        if ch='=' then begin
           sym:=becomes;
           getch;
        end else sym:=nul;
      end else if ch='<' then begin
        getch;
        if ch='=' then begin
           sym:=leq;
           getch;
        end else sym:=lss;
      end else if ch='>' then begin
        getch;
        if ch='=' then begin
           sym:=geq;
           getch;
        end else sym:=gtr;
      end else begin
        sym:=ssym[ch];
        getch;
      end;
    end; {getsym}
     
    procedure gen(x:fct;y,z:integer);
    begin
      if cx>cxmax then begin
         write('program too long');
        (* goto 99;*)
      end;
      with code[cx] do begin
           f:=x;
           l:=y;
           a:=z;
      end;
      cx:=cx+1;
    end; {gen}
     
    procedure test(s1,s2:symset;n:integer);
    begin
      if not(sym in s1) then begin
         error(n);
         s1:=s1+s2;
         while not(sym in s1) do getsym;
      end;
    end; {test}
     
    procedure block(lev,tx:integer;fsys:symset);
    var dx:integer;   {数据分配下标}
        tx0:integer;  {起始标识符表的下标}
        cx0:integer;  {起始代码的下标}
        procedure enter(k:objects);
        begin {把objects填入标识符表中}
          tx:=tx+1;
          with table[tx] do begin
            name:=id;
            kind:=k;
            case k of
              constant: begin
                          if num>amax then begin error(30); num:=0; end;
                          val:=num;
                        end;
              variable: begin
                          level:=lev;
                          adr:=dx;
                          dx:=dx+1;
                        end;
              procedur: level:=lev;
            end;
          end;
        end; {enter}
     
        function position(id:alfa):integer;
        var i:integer;
        begin {在标识符表中查标识符id}
          table[0].name:=id;
          i:=tx;
          while table[i].name<>id do i:=i-1;
          position:=i;
        end; {position}
     
        procedure constdeclaration;
        begin
          if sym=ident then begin
             getsym;
             if sym in [eql,becomes] then begin
                if sym=becomes then error(1);
                getsym;
                if sym=number then begin
                   enter(constant);
                   getsym;
                end else error(2);
             end else error(3);
          end else error(4);
        end; {constdeclaration}
     
        procedure vardeclaration;
        begin
          if sym=ident then begin
             enter(variable);
             getsym;
          end else error(4);
        end; {vardeclaration}
     
        procedure listcode;
        var i:integer;
        begin
          for i:=cx0 to cx-1 do
            with code[i] do begin
                writeln(i,mnemonic[f]:5,l:3,a:5);
                writeln(fa,i:4,mnemonic[f]:5,l:3,a:5);
            end;
        end; {listcode}
     
        procedure statement(fsys:symset);
        var i,cx1,cx2:integer;
            procedure expression(fsys
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*)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值