编译原理pl0项目

文章目录

  • 编译原理pl0修改
    • 项目要求
    • 环境设置
    • part1修改
      • 文件流的修改
      • 符号的修改
      • 变量名的替换
      • goto语句
      • 运算符的修改
      • 语法修改
    • part2修改
    • 参考链接
    • github地址

编译原理pl0修改

项目要求

除了文档里面的要求,还有一些隐藏要求已经被确认了。

  • 可以修改pl0源代码,一般是认为修改pl0编译程序,使得可以运行pl0源代码,但是实际上可以一起修改pl0源代码和pl0编译程序,使得最后可以运行。
  • read和write语句,能够实现读入integer数据和输出integer数据即可,而且从键盘或文件输入输出只要完成一项即可,没必要键盘和文件流都完成,此项目完成的是键盘输入和输出。

环境设置

我是用的Free Pascal IDE,以及Vscode,Vscode可以下载pascal的编译和格式插件,然后在user setting里面设置变量,格式化之后代码格式就会很整齐。
编译原理pl0项目_第1张图片
{[^}]+}正则表达式替换空,可以去掉所有的注释。
^\s*(?=\r?$)\n正则表达式替换空,可以去掉所有的空行。

part1修改

part1的要求就是可以运行就行了。

文件流的修改

首先是program PL0 ( input, output);,第一行参数可要可不要,可以随后在后面设置,其中有一行代码page(output);代表着输出文件到output里面,可以直接删掉,因为page没有定义。然后在一开始var申明里面加上fin,fout: text;,然后直接全局替换掉input即可,顺便加上sfile,dfile: string;用于表示文件名。在主程序里面加上下面代码,打开文件流。

 writeln('please input source program file name : ');
 readln(sfile);
 assign(fin,sfile);
 reset(fin);
 writeln('please input the file name to save result : ');
 readln(dfile);
 assign(fout,dfile);
 rewrite(fout);

这样在每个writeln后面都加上一个文件流输入语句就可以了,比如像下面一样。

writeln( '****', ' ':cc-1, '^', n:2 );
writeln(fout,'****', ' ':cc-1, '^', n:2);

符号的修改

主要是引号和减号,全部替换成英文的就可以了。

变量名的替换

主要是两个,都在这行里object = (constant, variable, procedure);objectprocedure,这两个都是pascal语言的保留字,所以用这个两个变量名肯定会报错,所以改成objecttypprosedure,以防冲突,另外代码中的其他部分也需要替换,但是不能全局替换,因为有的是使用pascalprocedure,所以这部分改起来很麻烦。

goto语句

直接删掉就好了,一共三条语句。

运算符的修改

代码中有的符号很不友好,主要是下面三个符号

  ssym[‘≠’] := neq;
  ssym[‘≤’] := leq;      
  ssym[‘≥’] := geq;

具体使用是将改成<>,将改成<=,将改成>=。然后这三行直接删掉就可以了。相应的在pl0源程序里面要把符号改掉。改掉之后要增加符号的识别语句,可以在识别:=的语句后面模仿写下如下代码,这样可以识别新加的三个符号。

Else If ch = '<'
         Then
         Begin
           getch;
           If ch = '='
             Then
             Begin
               sym := leq;
               getch
             End
           Else If ch = '>'
                  Then
                  Begin
                    sym := neq;
                    getch
                  End
           Else sym := lss
         End
  Else If ch = '>'
         Then
         Begin
           getch;
           If ch = '='
             Then
             Begin
               sym := geq;
               getch
             End
           Else sym := gtr
         End

语法修改

将代码以前内容改成小写

  word[1] := 'begin        ';
  word[2] := 'call         ';
  word[3] := 'const        ';
  word[4] := 'do           ';
  word[5] := 'end          ';
  word[6] := 'if           ';
  word[7] := 'odd          ';
  word[8] := 'procedure    ';
  word[9] := 'then         ';
  word[10] := 'var          ';
  word[11] := 'while        ';

这句话原本是没有Not的,所以只读一句话就结束了。

While Not eoln(fin) Do

这个处理程序原本也是没有Not

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;

这行原本也没有Not

Until Not (sym In declbegsys);

这行原本也没有Not

If Not (sym In [eql, neq, lss, leq, gtr, geq]) Then

part2修改

主要是加write和read语句

pl0源程序修改为一下内容,并且用这个文件测试

procedure test;
  var input;
  begin
    read(input);
    write(input);
  end;

begin
  call test;
end.

首先Const norw = 11;改成Const norw = 13;,因为要新加两个保留字。
然后修改

  word[1] := 'begin        ';
  word[2] := 'call         ';
  word[3] := 'const        ';
  word[4] := 'do           ';
  word[5] := 'end          ';
  word[6] := 'if           ';
  word[7] := 'odd          ';
  word[8] := 'procedure    ';
  word[9] := 'read         ';
  word[10] := 'then         ';
  word[11] := 'var          ';
  word[12] := 'while        ';
  word[13] := 'write        ';
  wsym[1] := beginsym;
  wsym[2] := callsym;
  wsym[3] := constsym;
  wsym[4] := dosym;
  wsym[5] := endsym;
  wsym[6] := ifsym;
  wsym[7] := oddsym;
  wsym[8] := procsym;
  wsym[9] := readsym;
  wsym[10] := thensym;
  wsym[11] := varsym;
  wsym[12] := whilesym;
  wsym[13] := writesym;

  mnemonic[lit] := 'LIT  ';
  mnemonic[opr] := 'OPR  ';
  mnemonic[lod] := 'LOD  ';
  mnemonic[sto] := 'STO  ';
  mnemonic[cal] := 'CAL  ';
  mnemonic[int] := 'INT  ';
  mnemonic[jmp] := 'JMP  ';
  mnemonic[jpc] := 'JPC  ';
  mnemonic[red] := 'RED  ';
  mnemonic[wrt] := 'WRT  ';

在解释程序里面加

red :
              Begin
                writeln('Input a integer:');
                writeln(fout,'Input a integer:');
                readln(s[base(l)+a]);
                writeln(fout,s[base(l)+a]);
              End;
        wrt :
              Begin
                writeln('Here is the integer:');
                writeln(s[t]);
                writeln(fout,'Here is the integer:');
                writeln(fout,s[t]);
                t := t+1
              End

condition里面加

Else If sym = readsym
         Then
         Begin
           getsym;
           If sym = lparen
             Then
             Repeat
               getsym;
               If sym = ident
                 Then
                 Begin
                   i := position(id);
                   If i = 0
                     Then error(11)
                   Else If table[i].kind <> variable
                          Then
                          Begin
                            error(12);
                            i := 0
                          End
                   Else With table[i] Do
                          gen(red,lev-level,adr)
                 End
               Else error(4);
               getsym;
             Until sym <> comma
           Else error(40);
           If sym <> rparen
             Then error(22);
           getsym
         End
  Else If sym = writesym
         Then
         Begin
           getsym;
           If sym = lparen
             Then
             Begin
               Repeat
                 getsym;
                 expression([rparen,comma]+fsys);
                 gen(wrt,0,0);
               Until sym <> comma;
               If sym <> rparen
                 Then error(22);
               getsym
             End
           Else error(40)
         End;

参考链接

参考博客

github地址

项目地址

你可能感兴趣的:(编译原理)