PL/0编译器功能扩充

1 增加语句for(<语句>;<条件>;<语句>)

Step1: 在pl0.h中修改

    pl0.h中在enum symbol { } 符号枚举集中加入
    forsym, 并更改符号的个数 symnum

Step2: 增加保留字名字并增加对应的保留字符号

    名字: strcpy(&(word[6][0]),"for");
    符号: wsym[6]=forsym;
    (: 顺序按26个字母的顺序重新排列)

Step3: 增加语句开始符号集

    statbegsys[forsym]=true;

Step4: 语句处理函数内添加关于for语句的处理

//int i , cx1 , cx2 , cx3 , cx4 , cx5; (cx3,cx4,cx5为新增加的地址)
if(sym == forsym)
{
    getsymdo;
    if(sym != lparen)  error(34);//没有左括号出错
    else 
    {
        getsymdo;
        statementdo(nxtlev, ptx, lev);  //S1代码
        //语句缺少分号出错
        if(sym != semicolon)  error(10);                 
        else
        {
            /*cx是当前指令的地址 保存判断条件操作的    位置 */
            cx1=cx;
            getsymdo;
            conditiondo(nxtlev, ptx, lev);   //E代码
            if(sym != semicolon)  error(10);                              
            else 
            {   
                cx2=cx;
                gendo(jpc,0,0);
                cx3=cx;
                gendo(jmp,0,0);
                getsymdo;
                cx4=cx;
                //S2代码
                statementdo(nxtlev, ptx, lev);    
                if(sym != rparen)  error(22);  //缺少右括号出错
                else 
                {
                    gendo(jmp,0,cx1); // 回头重新判断条件 
                    getsymdo;
                    cx5=cx;
                    statementdo(nxtlev, ptx, lev);  //S3代码
                    code[cx3].a=cx5;
                    gendo(jmp,0,cx4); 
                    code[cx2].a=cx;  // 反填跳出循环的地址,与if类似
                }
            }
        }
    }
}

2 扩充语句if <条件> then <语句> else <语句>

Step1: 在pl0.h中修改

    pl0.h中在enum symbol { } 符号枚举集中加入
    elsesym, 并更改符号的个数 symnum

Step2: 增加保留字名字并增加对应的保留字符号

    名字: strcpy(&(word[4][0]),"else");
    符号: wsym[4]=elsesym;
    (: 顺序按26个字母的顺序重新排列)

Step3: 语句处理函数内添加关于if语句的处理

if(sym==ifsym) /*准备按照if语句处理*/
{
    getsymdo;
    memcpy(nxtlev,fsys,sizeof(bool)*symnum);
    nxtlev[thensym]=true;
    nxtlev[dosym]=true; /*后跟符号为then或do*/
    conditiondo(nxtlev,ptx,lev); /*调用条件处理(逻辑运算)函数*/
    if(sym==thensym)
    {
        getsymdo;
    }
    else
    {
        error(16); /*缺少then*/
    }
    cx1=cx; /*保存当前指令地址*/
    gendo(jpc,0,0); /*生成条件跳转指令,跳转地址暂写0*/
    statementdo(fsys,ptx,lev); /*处理then后的语句*/
    if(sym==semicolon)
    {
        getsymdo;
        if(sym==elsesym)    /*then语句后出现else*/
        {
            getsymdo;
            cx2=cx;
            /*cx为当前的指令地址,cx+1即为then语句执行后的else语句的位置,回填地址*/
            code[cx1].a=cx+1; 
            gendo(jmp,0,0);
            statementdo(fsys,ptx,lev);
            /*经statement处理后,cx为else后语句执行
            完的位置,它正是前面未定的跳转地址,回填地址*/
            code[cx2].a=cx; 
        }
        else
        {
            /*经statement处理后,cx为then后语句执行完的位置,它正是前面未定的跳转地址*/
            code[cx1].a=cx; 
        }
    }
    else
    {
        error(5);
    }
}

3 增加语句repeat <语句> until <条件>

Step1: 在pl0.h中修改

    pl0.h中在enum symbol { } 符号枚举集中加入
    repeatsym, untilsym, 并更改符号的个数 symnum

Step2: 增加保留字名字并增加对应的保留字符号

    名字: strcpy(&(word[11][0]),"repeat");
         strcpy(&(word[13][0]),"until");
    符号: wsym[11]=repeatsym;
         wsym[13]=untilsym;
    (: 顺序按26个字母的顺序重新排列)

Step3: 增加语句开始符号集

    statbegsys[repeatsym]=true;

Step4: 语句处理函数内添加关于repeat语句的处理

else if(sym==repeatsym)
{
    cx1=cx; /*保存当前指令地址*/
    getsymdo;
    memcpy(nxtlev,fsys,sizeof(bool)*symnum);
    nxtlev[untilsym]=true;
    statementdo(fsys,ptx,lev);
    if(sym==semicolon)
    {
        getsymdo;
        if(sym==untilsym)
        {
            getsymdo;
            conditiondo(fsys,ptx,lev);
            /*经condition处理后,cx1为repeat后循环语句的位置,条件为假时一直循环*/
            gendo(jpc,0,cx1); 
        }
    }
    else
    {
        error(5);
    }
}

4. 增加自增自减运算

对于++和–的扩充,分为两种情况:

    作为语句的情况
    例如: ++i,--i,i++,i--;
    作为表达式的因子的情况
    例如:  b:=a++;b:=a--;
           b:=++a;b:=--a;

第一种作为语句情况的扩充:
Step1: 在pl0.h中修改

    pl0.h中在enum symbol { } 符号枚举集中加入
    addadd, subsub, 并更改符号的个数 symnum

Step2: 语句处理函数内添加关于++ 和–的处理

else if(sym==addadd) /*检测到后置++符号*/
 {
     getsymdo; 
     // 如果++后面跟的量可以在名字表中找到 
     if(i!=0)
     {
         gendo(lod,lev-table[i].level,table[i].adr);
         gendo(lit,0,1);
         gendo(opr,0,2);
         gendo(sto,lev-table[i].level,table[i].adr);
     }
 }
 else if(sym==subsub) /*检测到后置--符号*/
 {
     getsymdo;
     // 如果 -- 后面跟的量可以在名字表中找到 
     if(i!=0)
     {
         gendo(lod,lev-table[i].level,table[i].adr);
         gendo(lit,0,1);
         gendo(opr,0,3);
         gendo(sto,lev-table[i].level,table[i].adr);
     }
 }

 if(sym==addadd) /*检测到前置++符号*/
 {
     getsymdo;
     if(sym==ident) /*后面跟的是变量*/
     {
         i=position(id,*ptx);
         if(i==0)
         {
             error(11);
         }
         else
         {
             if(table[i].kind!=variable)
             {         
                 /*++后没跟变量,出错*/
                 error(12);
                 i=0;
             }
             else
             {     
                 /*++后跟变量,处理生成中间代码*/
                 getsymdo;
                 /*先取    值到栈顶*/
                 gendo(lod,lev-table[i].level,table[i].adr);
                 gendo(lit,0,1);  /*将1放到栈顶*/
                 gendo(opr,0,2); /*加法,即+1,栈顶加次栈顶*/
                 /*出栈取值到内存*/
                 gendo(sto,lev-table[i].level,table[i].adr);
             }
         }
     }
 }

 else if(sym==subsub) /*检测到前置--符号*/
 {
     getsymdo;
     if(sym==ident) /*后面跟的是变量*/
     {
         i=position(id,*ptx);
         if(i==0)
         {
             error(11);
         }
         else
         {
             /*--后没跟变量,出错*/
             if(table[i].kind!=variable) 
             {
             error(12);
             i=0;
             }
             else /*--后跟变量,处理生成中间代码*/
             {
                 if(table[i].kind==variable) /*后跟变量*/
                 {
                     getsymdo;
                     /*先取值到栈顶*/
                     gendo(lod,lev-table[i].level,table[i].adr);
                     gendo(lit,0,1); /*将1放到栈顶*/
                     gendo(opr,0,3); /*减法,即-1,栈顶减次栈顶*/
                     /*出栈取值到内存*/
                     gendo(sto,lev-table[i].level,table[i].adr);
                 }
             }
         }
     }
 }

第二种作为语句情况的扩充:

Step1: 添加因子开始符号集

   facbegsys[addadd]=true; /*前置++*/
   facbegsys[subsub]=true; /*前置--*/

Step2: 在因子处理函数factor中添加 ++和–相关处理

if(sym==addadd) /*因子出2现b:=a++类型*/
{
    gendo(lit,lev-table[i].level,1); /*将值入栈*/
    /*加法,即+1,栈顶加次栈顶*/
    gendo(opr,lev-table[i].level,2);         
    /*出栈取值到内存*/                                                    
    gendo(sto,lev-table[i].level,table[i].adr); 
    /*取值到栈顶*/

    gendo(lod,lev-table[i].level,table[i].adr); 
    gendo(lit,0,1);
    gendo(opr,0,3); /*栈顶值减*/
    getsymdo;
}
else if(sym==subsub) /*因子出现b:=a--类型*/
{
    gendo(lit,lev-table[i].level,1); /*将值入栈*/
    /*减法,即-1,栈顶减次栈顶*/
    gendo(opr,lev-table[i].level,3); 
    /*出栈取值到内存*/    
    gendo(sto,lev-table[i].level,table[i].adr);                         
    gendo(lod,lev-table[i].level,table[i].adr);
    gendo(lit,0,1);
    gendo(opr,0,2); /*栈顶值加*/
    getsymdo;
}
else if(sym==addadd) /*因子出现b:=++a类型*/
{
    getsymdo;
    if(sym==ident)
    {
        getsymdo;
        i=position(id,*ptx);
        if(i==0)
        {
            error(11);
        }
        else
        {
            if(table[i].kind==variable) /*变量*/
            {     
                /*先加后再用a*/
                /*先取值到栈顶*/
                gendo(lod,lev-table[i].level,table[i].adr);
                gendo(lit,0,1);/*将值入栈*/
                gendo(opr,0,2);/*加法,即+1,栈顶加次栈顶*/
                /*出栈取值到内存*/
                gendo(sto,lev-table[i].level,table[i].adr);
                /*取值到栈顶*/
                gendo(lod,lev-table[i].level,table[i].adr);
            }
        }
    }
}
else if(sym==subsub) /*因子出现b:=--a类型*/
{
    getsymdo;
    if(sym==ident)
    {
        getsymdo;
        i=position(id,*ptx);
        if(i==0)
        {
            error(11);
        }
        else
        {
            if(table[i].kind==variable) /*变量*/
            { 
                /*先减后再用a*/
                /*先取值到栈顶*/
                gendo(lod,lev-table[i].level,table[i].adr);
                gendo(lit,0,1); /*将值入栈*/
                gendo(opr,0,3); /*减法,即-1,栈顶减次栈顶*/
                /*出栈取值到内存*/
                gendo(sto,lev-table[i].level,table[i].adr);
                /*取值到栈顶*/
                gendo(lod,lev-table[i].level,table[i].adr); 
            }
        }
    }
}

5. 增加+=,-=,*=,/=运算

Step1: 在pl0.h中修改

    pl0.h中在enum symbol { } 符号枚举集中加入
    addequal,subequal, timeseql, slasheql,, 并更
    改符号的个数 symnum

Step2: 在getSym()函数中处理:

if(ch=='+')
{
    getchdo;
    if(ch=='=')
    {
        sym=addequal;
        getchdo;
    }
    else{
        sym=plus;
    }
}
else
{
    if(ch=='-')
    {
        getchdo;
        if(ch=='=')
        {
            sym=subequal;
            getchdo;
        }else{
            sym=minus;
        }
    }
    else 
    {
        if(ch=='*')
        {
            getchdo;
            if(ch=='=')
            {
                sym=timeseql;
                getchdo;
            }
            else
            {
                sym=times;
            }
        } 
        else
        {
            if(ch=='/')
            {
                getchdo;
                if(ch=='=')
                {
                    sym=slasheql;
                    getchdo;
                }
                getchdo;
            } else{
                sym=slash;
            }
        }else{
            /*当符号不满足上述条件时,全部按照单字符号处理*/
            sym=ssym[ch]; 
            if(sym!=period)
            {
                getchdo;
            }
        }
    }
}

Step3: 在语句处理函数中添加处理

else if(sym==addequal) /*检测到+=符号*/
{
    getsymdo;
    /*找到变量地址并将其值入栈*/
    gendo(lod,lev-table[i].level,table[i].adr); 
    if(sym==semicolon)
    {
        getsymdo;
        printf("+=后面直接跟了分号");
    }
    memcpy(nxtlev,fsys,sizeof(bool)* symnum);
    expressiondo(nxtlev,ptx,lev);
    gendo(opr,0,2);
    if(i!=0)
    {
        gendo(sto,lev-table[i].level,table[i].adr);
    }
}
else if(sym==subequal) /*检测到-=符号*/
{
    getsymdo;
    /*找到变量地址并将其值入栈*/
    gendo(lod,lev-table[i].level,table[i].adr);                          
    if(sym==semicolon)
    { 
        getsymdo;
    }
    memcpy(nxtlev,fsys,sizeof(bool)* symnum);
    expressiondo(nxtlev,ptx,lev);
    gendo(opr,0,3);
    if(i!=0)
    {
        gendo(sto,lev-table[i].level,table[i].adr);
    }
}
else if(sym==timeseql) /*检测到*=符号*/
{
    getsymdo;
    /*找到变量地址并将其值入栈*/
    gendo(lod,lev-table[i].level,table[i].adr);                        
    if(sym==semicolon)
    {
        getsymdo;
    }
    memcpy(nxtlev,fsys,sizeof(bool)* symnum);
    expressiondo(nxtlev,ptx,lev);
    gendo(opr,0,4);
    if(i!=0)
    { 
        gendo(sto,lev-table[i].level,table[i].adr);
    }
}
else if(sym==slasheql) /*检测到/=符号*/
{
    getsymdo;
     /*找到变量地址并将其值入栈*/
    gendo(lod,lev-table[i].level,table[i].adr);
    if(sym==semicolon)
    {
        getsymdo;
    }
    memcpy(nxtlev,fsys,sizeof(bool)* symnum);
    expressiondo(nxtlev,ptx,lev);
    gendo(opr,0,5);
    if(i!=0)
    {
        gendo(sto,lev-table[i].level,table[i].adr);
    }
}
  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
2. 课程设计 基本内容(成绩范围:“中”、“及格”或“不及格”) (1)扩充赋值运算:+= 和 -= (2)扩充语句 REPEAT DOWHILE 其中,是循环条件,即条件成立时,重复执行循环体的 选做内容(成绩评定范围扩大到:“优”和“良”) (1)增加运算:++ 和 --。 (2)增加类型:① 字符类型; ② 实数类型。 (3)扩充函数:① 有返回值和返回语句;② 有参数函数。 (4)增加一维数组类型(可增加指令)。 (5)其他典型语言设施。 3. 要求和说明 (1)放假前完成,提交课程设计报告和光盘 (各班统一制作一张光盘,每人的目录名:xxx姓名,xxx是学号末3位)。 (2)在程序运行界面突出显示: 设计者的班级、学号和姓名; 开始调试时间; 完成调试时间。 (3)实验报告内容 1)完成的实验内容及说明 2)概述: 源、目标语言,实现工具(平台),运行平台 3)结构设计说明 各功能模块描述 4)主要成分描述 ① 符号表 ② 运行时存储组织和管理 ③ 语法分析方法 ④ 中间代码表示 5)测试用例 6)开发过程和完成情况 (4)光盘内含: ① 扩充后的PLO编译程序的源程序文件和可执行程序文件; ② 测试用例的PL0语言源程序和编译运行结果; ③ 课程设计报告文档(令需交打印文档一份)。 (5)成绩分五档:优,良,中,及格和不及格。 根据完成的程序和报告的质量评定成绩。 只完成基本内容者,成绩至高为“中”。 鼓励完成选做内容,可获得加分:“良”,直到“优”。 如果有下列情况,则视情节严重程度,成绩下降若干档次,直至不及格: • 光盘文件含有病毒或者内容不能正确读出; • 抄袭、复制别人程序或文档; • 未能按时提交报告和光盘文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值