编译原理实验(四):语义分析及中间代码生成-根据 PL/0 语言的文法规范,要求在语法分析程序中添加语义处理,对于语法正确的表达式,输出其中间代码;对于语法正确的算术表达式, 输出其计算值。

**

任务说明

**
1. 实验目的
  通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析
所识别的语法范畴变换为某种中间代码的语义翻译方法。
  掌握目前普遍采用的语义分析方法──语法制导翻译技术。
  给出 PL/0 文法规范,要求在语法分析程序中添加语义处理,对于语法正确的表达式,输出其中间代码;对于语法正确的算术表达式,输出其计算值。
2. 实验准备
  微机安装好 C 语言,或 C++,或 Visual C++.
3.实验内容
  已给 PL/0 语言文法,在实验二或实验三的表达式语法分析程序里,添加语义处理部分,输出表达式的中间代码,用四元式序列表示。
4. 实验要求
  语义分析对象重点考虑经过语法分析后已是正确的语法范畴,本实验重点是语义子程序。
  在实验二或实验三“语法分析器”的里面添加 PL/0 语言“表达式”部分的语义处理,输出表达式的中间代码,计算表达式的语义值。
  中间代码用四元式序列表示。
5. 输入输出
 (1) PL/0 算术表达式的语义计算:
  输入:
    PL/0 算术表达式,例如:2+35 作为输入。
  输出:《编译原理》实验指导书
    13 of 14
   17
 (2)PL/0 表达式的中间代码表示
  输入:
    PL/0 表达式,例如: a
(b+c)。
  输出:
   (+,b,c,t1)
   (*,a,t1,t2)

具体实现

设计思想

扩充的巴科斯范式
  <表达式> ::= [+|-]<项>{<加法运算符> <项>}
  <项> ::= <因子>{<乘法运算符> <因子>}
  <因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
  <加法运算符> ::= +|-
  <乘法运算符> ::= *|/
普通的巴科斯范式
  为表示方便:
  表达式E、项X、因子Y、标识符b,无符号整数z,加法运算符A,乘法运算符C改进后的产生式和语义动作以及变量函数说明:
  (1)设定每个非终结符有一个综合属性place,表示存放值的变量名。变量名和值都会保存在符号表中。
  (2)newtemp函数:产生一个新的变量名,并返回。
  (3)emit函数:产生一个四元式,并保存在四元式列表中。
  说明:语义规则中的函数设计和代码实现中的会有些出入,不过功能是一样的。
  ·适合一遍扫描的翻译模式:
  在这里插入图片描述
  由于本次实验使用自下而上的LR分析方法,所以不用消除左递归。

FIRST和FOLLOW集合
  FIRST(S’)={b,z,(,-}    FOLLOW(S’)={#}
  FIRST(E)={b,z,(,-}    FOLLOW(E)={#,),+,-}
  FIRST(X)={b,z,(}    FOLLOW(X)={ ,/,+,-,#,)}
  FIRST(Y)={b,z,(}    FOLLOW(Y)={
,/,+,-,#,)}

LR分析表
  因为改进后的文法跟实验三稍有不同,所以LR分析表也有些不同。
在这里插入图片描述

算法流程

该流程是在实验3的LR分析流程上稍作修改的,词法分析过程和实验1相同,图中不再展开说明,另外加入了一些关于语义分析的过程。
在这里插入图片描述

代码

//实验1词法分析+实验3LR分析+实验4语义分析和中间代码生成 
#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <sstream>
using namespace std;
/*                    变量声明                              */
/****词法分析***/
//分析的单词,s1为编码,s2为单词符号(词法分析器的输出每个单词的格式)
struct strs
{
   
    string s1,s2;
};
string str_out="";//词法分析完成后输出,也是语法分析的输入
/****语法分析***/
int account=1;//记录需语法分析的单词的个数,再加上#
int flag=0; //记录语法分析状态 flag=1语法分析正确,即对应lr分析表中acc状态
int p=-1;//指针作用,表示当前扫描单词的下标
strs analystr;//当前分析的单词
stack <int> State;  //状态栈
stack <string> in;  //符号栈
int error=0;//错误处理,对应lr分析表中空白位置,当遇到空白位置时说明分析错误,error置为1
/****语义分析***/
int countt=0;//变量名的个数
int countquad=0;//四元式个数
//为记录X,Y,E的place属性值,也为它们申请变量,保存在符号表中
int countX=0; //语法分析时遇到的X个数
int countY=0; //语法分析时遇到的Y个数
int countE=0; //语法分析时遇到的E个数
map<string,string>words;//符号表
map<string,int>res;//当分析算术表达式时,记录每个四元式result值
//四元式结构
struct four
{
   
    string op;//操作符
    string o1;//操作数1
    string o2;//操作数2
    string result;//记录结果变量名,真实的结果数据在res表中
};
four four[50];//四元式列表

/*               函数                */

//扫描下一个单词
void Advance(strs *S)
{
   
    p++;
    analystr = S[p];
}
//产生新的变量名
string newtemp(string s)
{
   
    stringstream ss;
    if(s=="t")
    {
   
        countt++;
        ss<<s<<countt;//拼接
    }
    else if(s=="X")
    {
   
        countX++;
        ss<<s<<countX;//拼接
    }
    else if(s=="Y")
    {
   
        countY++;
        ss<<s<<countY;//拼接
    }
    else
    {
   
        countE++;
        ss<<s<<countE;//拼接
    }
    return ss.str();
}
//产生四元式并保存到四元式列表中
void emit(string op,string o1,string o2,string res)
{
   
    four[countquad].op=op;
    four[countquad].o1=o1;
    four[countquad].o2=o2;
    four[countquad].result=res;
    countquad++;
}
//词法分析:用于识别是基本字或标识符
void Letter(string str){
   
    /*-------------------识别基本字--------------------*/
    if(str=="begin")
        {
   account++;str_out = str_out +"(beginsym,begin)"+' ';}
    else if(str=="call")
        {
   account++;str_out = str_out +"(callsym,call)"+' ';}
    else if(str=="const")
        {
   account++;str_out = str_out +"(constsym,const)"+' ';}
    else if(str=="do")
        {
   account++;str_out = str_out +"(dosym,do)"+' ';}
    else if(str=="end")
        {
   account++;str_out = str_out +"(endsym,end)"+' ';}
    else if(str=="if")
        {
   account++;str_out = str_out +"(ifsym,if)"+' ';}
    else if(str=="odd")
        {
   account++;str_out = str_out +"(oddsym,odd)"+' ';}
    else if(str=="procedure")
        {
   account++;str_out = str_out +"(proceduresym,procedure)"+' ';}
    else if(str=="read")
        {
   account++;str_out = str_out +"(readsym,read)"+' ';}
    else if(str=="then")
        {
   account++;str_out = str_out +"(thensym,then)"+' ';}
    else if(str=="while")
        {
   account++;str_out = str_out +"(whilesym,while)"+' ';}
    else if(str=="var")
        {
   account++;str_out = str_out +"(varsym,var)"+' ';}
    else if(str=="write")
        {
   account++;str_out = str_out +"(writesym,write)"+' ';}
    /*-------------------end---------------------------*/


    /*-------------------识别标识符--------------------*/
    else{
   
        account++;str_out = str_out+"(ident,"+str+")"+' ';
    }
    /*-------------------end---------------------------*/
}
//语法LR分析:对应goto表,执行归约后,根据当前状态和符号确定哪一个状态应该进入State中
void Analy_goto()
{
   
    int state=State.top(); //取当前栈顶状态
    string si=in.top(); //当前符号栈的栈顶符号
    char sii=si[0];  //string->char转换
    switch(state)
    {
   
    //根据goto表,压入状态的代码
    case 0:
        if(sii=='E') State.push(1);
        else if(sii=='X') State.push(3);
        else if(sii=='Y') State.push(4);
        else error=1;
        break;
    case 2:
        if(sii=='X') State.push(10);
        else if(sii=='Y') State.push(11);
        else error=1;
        break;
    case 5:
        if(sii=='E') State.push(14);
        else if(sii=='X') State.push(3);
        else if(sii=='Y') State.push(11);
        else error=1;
        break;
    case 8:
        if(sii=='X') State.push(15);
        else if(sii=='Y') State.push(11);
        else error=1;
        break;
    case 9:
        if(sii=='X') State.push(16);
        else if(sii&#
  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值