写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文!

本博客全网唯一合法URL:http://www.cnblogs.com/acm-icpcer/p/9173880.html

  基于C++语言实现的PL/0语言的算术表达式的自下而上的语法分析程序。该语言的其他语法实现思想与此一致,故不赘述。

  运行此程序前,必须先将代码通过:【编译原理】c++实现词法分析器的词法分析,生成词法表(词法表是txt文件,为了语法分析成功,务必删除文件中最后空着的一行,即文件末尾不可以留空白行)。生成的该词法表为此程序的必要输入。

  产生式:

  S->X(AX)*|AX(AX)*
    X->Y(MY)*
    Y->I|N|(S)
    A->+|-
    M->*|/
    C->=|#|<|<=|>|>=

  本次的代码主要是在【编译原理】c++实现自下而上语法分析器的基础上,伴随着归约的过程,增加了生成四元式的过程,也就是一边归约一边生成中间代码。

Talk is cheap, show you my source code:

/*
this code was first initiated by TZ,COI,HZAU
contact email:xmb028@163.com
personal website:wnm1503303791.github.io
personal blogs:www.cnblogs.com/acm-icpcer/
this code has been posted on my personal blog,checking url:www.cnblogs.com/acm-icpcer/p/9173880.html
Copyright 2018/6/12 TZ.
All Rights Reserved.
*/ #include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include<fstream>
using namespace std; //预处理函数
bool preproccess(char *a,char *b,char *c)
{
int i1=,i2=;//i2为原串指针
memset(b,,'\0');
while(a[i2]!=',')
{
b[i1]=a[i2];
++i1,++i2;
}
b[i1]='\0'; i1=;i2++;
while(a[i2]!=')')
{
c[i1]=a[i2];
++i1,++i2;
}
c[i1]='\0';
//cout<<b<<endl;
return true;
} fstream f2("stack.txt", ios::out);//打开文件,供写
fstream f3("quaternary.txt", ios::out);//打开文件,供写
static int mcount=;//存储打印次数
//当移进或者归约时打印栈内情况,以供分析
bool outf(int head,char data[][],fstream &f)
{
f<<"times("<<mcount<<"),";
f<<"head is:"<<head<<endl;
for(int i=head;i>=;i--)
{
f<<data[i]<<endl;
}
mcount++;
f<<endl;
return true;
}
//四元式写入文件函数1
bool outf2(int top,char dt[][],fstream &f)
{
/*
char arg1[1024],arg2[1024],op[1024];
memset(arg1,sizeof(arg1),'\0');
strcpy(arg1,dt[top]);
memset(op,sizeof(op),'\0');
strcpy(op,dt[top-1]);
memset(arg2,sizeof(arg2),'\0');
strcpy(arg2,dt[top-2]); f<<"("<<op<<","<<arg1<<","<<arg2<<","<<"T"<<")"<<endl;
*/
f<<"("<<dt[top-]<<","<<dt[top]<<","<<dt[top-]<<","<<"T"<<")"<<endl;
return true;
}
//四元式写入文件函数2
bool outf3(int top,char dt[][],fstream &f)
{
f<<"("<<dt[top-]<<","<<dt[top]<<","<<"-"<<","<<"T"<<")"<<endl;
return true;
}
//四元式写入文件函数3
bool outf4(int top,char dt[][],fstream &f,char T)
{
f<<"("<<":="<<","<<dt[top]<<","<<"-"<<","<<T<<")"<<endl;
return true;
} //“策略”设计模式,面向对象方法
class presentation
{
private:
char data[][];//栈
char dt[][];//四元式栈
fstream *infile;//词法分析表
int head,top;//两个栈的栈顶指针
public:
//first initiated the object
presentation(fstream *in_f)
{
this->infile=in_f;
memset(data,sizeof(data),'\0');
memset(dt,sizeof(dt),'\0');
head=top=-;
}
bool push()
{
head++;
top++; infile->getline(data[head],);
char t1[],t2[];//存放字符标志
preproccess(data[head],t1,t2); cout<<data[head]<<","<<t1<<endl; memset(data[head],,'\0');
strcpy(data[head],t1); memset(dt[top],,'\0');
strcpy(dt[top],t2);
cout<<dt[top]<<","<<t2<<endl;
} /*
S->X(AX)*|AX(AX)*
X->Y(MY)*
Y->I|N|(S)
A->+|-
M->*|/
C->=|#|<|<=|>|>=
*/
//归约函数
bool reduce()
{
//S->X(AX)*|AX(AX)*
if( head>=&&
(!strcmp(data[head],"X"))&&
(!strcmp(data[head-],"plus")||!strcmp(data[head-],"minus"))&&
(!strcmp(data[head-],"X"))&&
(!strcmp(data[head-],"plus")||!strcmp(data[head-],"minus"))&&
(!strcmp(data[head-],"X"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"S");//归约
/*
stack description:
top-> arg
op
top-2-> arg
op
arg
*/
if(outf2(top,dt,f3)&&outf2(top-,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&
(!strcmp(data[head],"X"))&&
(!strcmp(data[head-],"plus")||!strcmp(data[head-],"minus"))&&
(!strcmp(data[head-],"X"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"S");
if(outf2(top,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&/*top>=3*/
(!strcmp(data[head],"plus")||!strcmp(data[head],"minus"))&&
(!strcmp(data[head-],"X"))&&
(!strcmp(data[head-],"plus")||!strcmp(data[head-],"minus"))&&
(!strcmp(data[head-],"X"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"S");
if(outf3(top,dt,f3)&&outf3(top-,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&
(!strcmp(data[head],"plus")||!strcmp(data[head],"minus"))&&
(!strcmp(data[head-],"X"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"S");
if(outf3(top,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} //X->Y(MY)*
if( head>=&&
(!strcmp(data[head],"Y"))&&
(!strcmp(data[head-],"times")||!strcmp(data[head-],"slash"))&&
(!strcmp(data[head-],"Y"))&&
(!strcmp(data[head-],"times")||!strcmp(data[head-],"slash"))&&
(!strcmp(data[head-],"Y"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"X");
/*
current stack description:
top-> arg
op
top-2-> arg
op
arg
*/
if(outf2(top,dt,f3)&&outf2(top-,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&
(!strcmp(data[head],"Y"))&&
(!strcmp(data[head-],"times")||!strcmp(data[head-],"slash"))&&
(!strcmp(data[head-],"Y"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"X");
/*
current stack description:
top->arg
op
arg
*/
if(outf2(top,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&(!strcmp(data[head],"Y"))
)
{
memset(data[head],,'\0');
head=head-+; strcpy(data[head],"X");
if(outf4(top,dt,f3,'X'))
{
top==-;
memset(dt,sizeof(dt),'\0');
}
return true;
} //Y->I|N|(S)
if( head>=&&(!strcmp(data[head],"ident"))
)
{
memset(data[head],,'\0');
head=head-+; strcpy(data[head],"Y");
if(outf4(top,dt,f3,'Y'))
{
top==-;
memset(dt,sizeof(dt),'\0');
}
return true;
} if( head>=&&(!strcmp(data[head],"number"))
)
{
memset(data[head],,'\0');
head=head-+; strcpy(data[head],"Y");
if(outf4(top,dt,f3,'Y'))
{
top==-;
memset(dt,sizeof(dt),'\0');
}
return true;
} if( head>=&&
(!strcmp(data[head],"rparen"))&&
(!strcmp(data[head-],"S"))&&
(!strcmp(data[head-],"lparen"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"Y");
return true;
} return false;
}
//遍历栈
bool visit_data()
{
cout<<"current stack:"<<endl;
for(int i=head;i>=;i--)
{
cout<<data[i]<<endl;
}
return true;
}
//主控函数
bool mainf()
{
while(!infile->eof())
{
push();
bool t=reduce();
outf(head,data,f2);
//每当移进结束时就检查一下是否有可规约串
while(t)//防止规约嵌套
{
t=reduce();
outf(head,data,f2);
}
//visit_data();
} visit_data(); bool flag=false;
for(int i=head;i>=;i--)
{
if(!strcmp(data[i],"S"))
{
flag=true;
}
if( strcmp(data[i],"S")&&
strcmp(data[i],"X")&&
strcmp(data[i],"A")&&
strcmp(data[i],"Y")&&
strcmp(data[i],"M")&&
strcmp(data[i],"C")
)
{
return false;
}
} return flag; /*
while(head>0)
{
bool t=reduce();
//每当移进结束时就检查一下是否有可规约串
while(t)//防止规约嵌套
{
t=reduce();
}
//visit_data();
outf(head,data,f2);
}
*/
}
}; int main()
{
fstream f1;
f1.open("lexical.txt", ios::in);//打开词法分析表,供读 presentation* s1=new presentation(&f1);
bool result=s1->mainf(); if(result)
cout<<"ACCEPTED!"<<endl;
else
cout<<"ERROR!"<<endl; f1.close();
f2.close();
return ;
}

运行示例:

(1)合法的语句:

(2)不合法的语句:

tz@COI HZAU

2018/6/12

【编译原理】c++实现自下而上语法分析及中间代码(四元式)生成的更多相关文章

  1. 现代编译原理——第二章:语法分析之LL(K)

    转自: http://www.cnblogs.com/BlackWalnut/p/4472122.html LL(K)语法分析技术是建立在预测分析的技术之上的.我们先来了解预测分析技术.考虑以下文法: ...

  2. 编译原理 #04# 中缀表达式转化为四元式(JavaScript实现)

    // 实验存档 运行截图: 代码中的总体转化流程:中缀表达式字符串→tokens→逆波兰tokens(即后缀表达式)→四元式. 由后缀表达式写出四元式非常容易,比较繁琐的地方在于中缀转逆波兰,这里采用 ...

  3. 编译原理实验之SLR1文法分析

    ---内容开始--- 这是一份编译原理实验报告,分析表是手动造的,可以作为借鉴. 基于  SLR(1) 分析法的语法制导翻译及中间代码生成程序设计原理与实现1 .理论传授语法制导的基本概念,目标代码结 ...

  4. 编译原理(一)绪论概念&文法与语言

    绪论概念&文法与语言 以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 绪论基本概念 1. 低级语言:字位码.机器语言.汇编语言.与特定的机器有关,功效高,但使用复杂.繁琐.费时 ...

  5. MOOC 编译原理笔记(一):编译原理概述以及程序设计语言的定义

    编译原理概述 什么是编译程序 编译程序指:把某一种高级语言程序等价地转换成另一张低级语言程序(如汇编语言或机器代码)的程序. 高级语言程序-翻译->机器语言程序-运行->结果. 其中编译程 ...

  6. 编译原理_P1004

    龙书相关知识点总结 //*************************引论***********************************// 1. 编译器(compiler):从一中语言( ...

  7. python实现算术表达式的词法语法语义分析(编译原理应用)

    本学期编译原理的一个大作业,我的选题是算术表达式的词法语法语义分析,当时由于学得比较渣,只用了递归下降的方法进行了分析. 首先,用户输入算术表达式,其中算术表达式可以包含基本运算符,括号,数字,以及用 ...

  8. 《编译原理》控制流语句 if 和 while 语句的翻译 - 例题解析

    <编译原理>控制流语句 if 和 while 语句的翻译 - 例题解析 将 if 和 while 语句翻译成四元式 注:不同教材会有小差异,使用 _ 或者 - ,如果是 -,请注意区分 - ...

  9. Java 实现《编译原理》中间代码生成 -逆波兰式生成与计算 - 程序解析

    Java 实现<编译原理>中间代码生成 -逆波兰式生成与计算 - 程序解析 编译原理学习笔记 (一)逆波兰式是什么? 逆波兰式(Reverse Polish notation,RPN,或逆 ...

随机推荐

  1. iOS Block不能修改外部变量的值

    __block int a = 0; void (^foo)(void) = ^{ a = 1; }; Block不允许修改外部变量的值.Apple这样设计,应该是考虑到了block的特殊性,bloc ...

  2. android 对话框全屏

    对话框风格 <style name="Lam.Dialog.FullScreen" parent="@style/Theme.AppCompat.Dialog&qu ...

  3. 译:6.RabbitMQ Java Client 之 Remote procedure call (RPC,远程过程调用)

    在  译:2. RabbitMQ 之Work Queues (工作队列)  我们学习了如何使用工作队列在多个工作人员之间分配耗时的任务. 但是如果我们需要在远程计算机上运行一个函数并等待结果呢?嗯,这 ...

  4. 如何在TextView类中创建超链接 Linkify

    Linkify是一个辅助类,通过RegEx样式匹配,自动地在TextView类(和继承的类)中创建超链接.符合特定的RegEx样式的文本会被转变成可点击的超链接,这些超链接隐式的调用startActi ...

  5. linux每日命令(32):gzip命令

    减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用.gzip不仅可以用 ...

  6. 如何取消Visual Studio Browser Link

    VS2013.2015新建MVC网站并浏览后,页面默认自动启用Browser Link功能 解决方法,只需要在web.config中添加配置节点即可 <appSettings> <a ...

  7. Java知多少(51)finally

    当异常被抛出,通常方法的执行将作一个陡峭的非线性的转向.依赖于方法是怎样编码的,异常甚至可以导致方法过早返回.这在一些方法中是一个问题.例如,如果一个方法打开一个文件项并关闭,然后退出,你不希望关闭文 ...

  8. FPGA编程—组合逻辑编码器等verilog实现

    本篇博客主要实现对组合逻辑电路的一些常用模块的实现.组合逻辑中,包括译码器,编码器,输入输出选择器,数值比较器,算法单元等.  先来实现编码器,最常用的8-3编码器,这里先讲一下要用到的case ,c ...

  9. 【转】燃烧吧,TestMice!

    ...当我们几个人碰面的时候,就感觉应该做点测试业内的实事. 记得当时的17站出了一些QTP辅件,给了我一些灵感.2008年做了一整年的QTP企业级实施,从方案到最后的收尾支持,得到最大的教训就是,当 ...

  10. win8 下 TortoiseSVN 不显示图标

    如果你安装 TortoiseSVN 之后,功能使用正常,但是文件夹或文件左上角就是不显示图标,那么你可能 1. 64bit 系统上装了 32bit 的 TortoiseSVN 解决方法是,再安装 64 ...