- 1 实验目的和内容
- 1.1 实验目的
- 1.2 实验内容
- 1.3 实验要求
- 2 设计思想
- 2.1 语义规则
- 2.2 递归下降翻译器
- 2.3 递归下降子程序伪代码
- 3 算法流程
- 4 源程序
- 5 调试数据
- 5.1 测试样例一
- 5.2 测试样例二
- 5.3 测试样例三
- 5.4 测试样例四
- 6 实验调试情况及体会
- 6.1 实验调试情况
- 6.2 实验体会
(1)通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析 所识别的语法范畴变换为某种中间代码的语义翻译方法。
(2)掌握目前普遍采用的语义分析方法──语法制导翻译技术。
(3)给出 PL/0 文法规范,要求在语法分析程序中添加语义处理,对于语法正确的表达式,输出其中间代码;对于语法正确的算术表达式,输出其计算值。
1.2 实验内容已给 PL/0 语言文法,在实验二或实验三的表达式语法分析程序里,添加语义处理部分,输出表达式的中间代码,用四元式序列表示。
1.3 实验要求(1)语义分析对象重点考虑经过语法分析后已是正确的语法范畴,本实 验重点是语义子程序。
(2)在实验二或实验三“语法分析器”的里面添加 PL/0 语言“表达式”部分的语义处理,输出表达式的中间代码,计算表达式的语义值。
(3)中间代码用四元式序列表示。
2 设计思想 2.1 语义规则属性计算的过程即是语义处理的过程对于文法的每一个产生式配备一组属性的计算规则,则称为语义规则。
(1)终结符只有综合属性,它由词法分析器提供。
(2)非终结符既可以有综合属性也可以有继承属性,文法开始符号的所有继承属性作为属性计算前的初始值。
(3)产生式右边符号的继承属性和产生式左边符号的综合属性都必须提供一个计算规则。
(4)产生式左边符号的继承属性和产生式右边符号的综合属性由其它产生式的属性规则计算。
2.2 递归下降翻译器递归下降分析法的原理是利用函数之间的递归调用来模拟语法树自上而下的构建过程。从根节点出发,自顶向下为输入串中寻找一个最左匹配序列,建立一棵语法树。对于每个非终结符的继承属性当作形式参数,函数的返回值当作非终结符的继承属性;对于终结符要初始化所有的继承属性。再进行分析过程中,非终结符根据当前的输入符号决定使用哪个产生式候选。
2.3 递归下降子程序伪代码(1)表达式
function表达式:string;
string s1, s2, s3, result;
BEGIN
IF SYM=’+’ OR SYM=’-’ THEN
ADVANCE;
ELSE IF SYM =FIRST(项)
ELSE ERROR;
BEGIN s1:=项;
END;
WHILE SYM=’+’ OR SYM=’-’ THEN
BEGIN
ADVANCE;
S2:=项;
result := newtemp();
emit(SYM,s1,s2,result);
s1:= result;
END;
Return result;
END;
(2)项
function 项:string;
string s1, s2, s3, result;
BEGIN
IF SYM =FIRST(因子) THEN
BEGIN
s1:=因子;
END;
ELSE ERROR;
WHILE SYM =’*’OR SYM=’/’ THEN
IF SYM =FIRST(因子) THEN
BEGIN
ADVANCE;
S2:=因子;
result := newtemp();
emit(SYM,s1,s2,result);
s1:= result;
END;
Return result;
END;
ELSE ERROR;
(3)因子
function 因子:string;
string s;
BEGIN
IF SYM =’(’ THEN
ADVANCE;
s:=表达式;
ADVANCE;
IF SYM=’)’ THEN
ADVANCE;
Return s;
ELSE ERROR;
ELSE IF SYM =FIRST(因子) THEN
ADVANCE;
ELSE ERROR;
END;
3 算法流程
算法流程图如下所示,首先输入表达式,然后进行词法分析,把词法分析的结果存在结构体中,之后调用递归下降分析器中的表达式子程序进行分析,最后得到四元组并存在相应的结构体中,下一步进行判断,如果是算术表达式,就计算该算术表达式的值并输出,如果不是算术表达式,就不做处理,直接输出四元组,最后判断程序的输入是否结束,如果没有结束,就再次输入表达式,重复上述步骤,如果结束,则程序退出。
图1 算法流程图
4 源程序#include
#include
#include
#include
using namespace std;
//存储词法分析的结果
struct cf_tv
{
string t; //词法分析的类型
string v; //词法分析变量的值
};
//存储四元组
struct qua
{
string symbal; //符号
string op_a; //第一个操作数
string op_b; //第二个操作数
string result; //结果
};
string input; //全局输入
int cnt; //全局变量
int k=0; //tv输入
int ljw=0;
cf_tv result[200]; //存放结果
qua output[200]; //存放输出的四元组
int x=0; //qua 的下标
int ans=0; //遍历的时候的下标
bool error=true; //出错标志
int is_letter=0;
int t[1001]; //临时存放空间
string item();
string factor();
//产生新变量名t1,t2等
string new_temp()
{
char *pq;
char mm[18];
pq=(char*)malloc(18);
ljw++;
//转换成字符串格式
snprintf(mm,sizeof(mm),"%d",ljw);
strcpy(pq+1,mm);
pq[0]='t';
string s;
s=pq;
return s;
}
//判断是否和目标串匹配
bool judge (string input, string s)
{
if (input.length()!=s.length()) return false;
else
{
for(unsigned int i=0;i>str)
{
cnt=0;
const char *d = " +-*/=:(),;.";
char *p;
//运用空格和运算符和界符分割字符串并且遍历
char buf[1001] ;
//字符串转成数组
strcpy(buf , str.c_str());
//p是一个char*
p = strtok(buf,d);
while(p)
{
//当前无符号
if(str[cnt]==p[0])
{
not_fh(p);
cnt=cnt+strlen(p);
}
//当前是符号
else
{
while(str[cnt]!=p[0])
{
fh_1(str,cnt);
cnt=change(str,cnt);
cnt=cnt+1;
}
not_fh(p);
cnt=cnt+strlen(p);
}
//下移一位,进行遍历
p=strtok(NULL,d);
}
for(unsigned int i=cnt;ik)
{
cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?