跳至正文

编译原理lab5

内容目录

编译原理lab5

1. 阅读PL/0编译器源代码(C语言版-仅词语法分析),熟悉该编译程序的整体架构,识别出各语法单位对应的子程序,读懂各子程序之间的调用关系,读懂词法分析程序是如何接入到编译程序主体的。本次实验要求你对PL/0语言进行扩充,使之支持repeat,语法定义如下:<直到型循环语句>::=repeat <语句> until <条件>

下面是PL/0的语法描述图,请画出扩充repeat后的PL/0语法图,只需要画<语句>部分,可使用画图工具,也可手画拍照上传。说明:语法描述图的画法为:

img
img

扩充repeat后的PL/0语法图如下:

IMG_0837

2. 接上题,请对提供的PL/0编译器源代码(C语言版-仅词语法分析)进行扩充,使之支持repeat(只需要完成词语法分析):(1)提交扩充后的C源程序;(2)自行编写一个含有repeat语句的PL0源程序作为编译器输入,给出输入输出截图。

扩充后程序见:https://gitee.com/WilliamSamShen/complier-concepts/blob/master/Lab/lab5/ex1_2/src/pl0Compiler_Syntax_Analysis_repeat.c

主要部分修改如下:

#define norw 15       /* 保留字个数,扩充了repeat和until */

/* 符号 */
enum 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,
    writesym, readsym, dosym, callsym, constsym,
    varsym, procsym,repeatsym,untilsym
};

/*
 * 初始化
 */
void init()
{
    int i;

    ...

    /* 设置保留字名字,按照字母顺序,便于二分查找 */
    strcpy(&(word[0][0]), "begin");
    strcpy(&(word[1][0]), "call");
    strcpy(&(word[2][0]), "const");
    strcpy(&(word[3][0]), "do");
    strcpy(&(word[4][0]), "end");
    strcpy(&(word[5][0]), "if");
    strcpy(&(word[6][0]), "odd");
    strcpy(&(word[7][0]), "procedure");
    strcpy(&(word[8][0]), "read");
    strcpy(&(word[9][0]), "repeat");  /* 扩充repeat */
    strcpy(&(word[10][0]), "then");
    strcpy(&(word[11][0]), "until");  /* 扩充util */
    strcpy(&(word[12][0]), "var");
    strcpy(&(word[13][0]), "while");
    strcpy(&(word[14][0]), "write");

    /* 设置保留字符号 */
    wsym[0] = beginsym;
    wsym[1] = callsym;
    wsym[2] = constsym;
    wsym[3] = dosym;
    wsym[4] = endsym;
    wsym[5] = ifsym;
    wsym[6] = oddsym;
    wsym[7] = procsym;
    wsym[8] = readsym;
    wsym[9] = repeatsym;
    wsym[10] = thensym;
    wsym[11] = untilsym;
    wsym[12] = varsym;
    wsym[13] = whilesym;
    wsym[14] = writesym;
}

/*
 * 语句处理
 */
void statement(int* ptx)
{
    int i;

    if (sym == ident)   /* 准备按照赋值语句处理 */
    {
        ...
    }
    else
    {
        if (sym == readsym) /* 准备按照read语句处理 */
        {
            ...
        }
        else
        {
            if (sym == writesym)    /* 准备按照write语句处理 */
            {
                ...
            }
            else
            {
                if (sym == callsym) /* 准备按照call语句处理 */
                {
                    ...
                }
                else
                {
                    if (sym == ifsym)   /* 准备按照if语句处理 */
                    {
                        ...
                    }
                    else
                    {
                        if (sym == beginsym)    /* 准备按照复合语句处理 */
                        {
                            ...
                        }
                        else
                        {
                            if (sym == whilesym)    /* 准备按照while语句处理 */
                            {
                                ...
                            }
                            else    /* 扩充repeat语句 */
                            {
                                if (sym == repeatsym)
                                {
                                    getsym();
                                    statement(ptx);
                                    if (sym == untilsym)
                                    {
                                        getsym();
                                    }
                                    else
                                    {
                                        error(19);
                                    }
                                    condition(ptx);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

输入pl/0源程序如下:

const BEGIN=1,END=100;
procedure addup;
var a,b,sum;
  begin
    a:=BEGIN;
    b:=END;
    sum:=0;
    repeat 
      begin
        sum := sum+a;
        a := a+1;
      end
    until a >= b;
   write(sum);
  end;
begin
  call addup;
end.

输入输出截图如下:

截屏2024-04-06 20.38.35

代码链接

https://gitee.com/WilliamSamShen/complier-concepts/tree/master/Lab/lab5