自上而下语法分析

实验二 自上而下语法分析
1.实验目的
(1)给出 PL/0 文法规范,要求编写 PL/0 语言的语法分析程序。
(2)通过设计、编制、调试一个典型的自上而下语法分析程序,实现对 词法分析程序所提供的单词序列进行语法检查和结构分析,进一步 掌握常用的语法分析方法。
(3)选择最有代表性的语法分析方法,如递归下降分析法、预测分析法; 选择对各种常见程序语言都具备的语法结构,如赋值语句,特别是 表达式,作为分析对象。
2.实验内容
(1)已给 PL/0 语言文法,构造表达式部分的语法分析器。
 分析对象〈算术表达式〉的 BNF 定义如下:
<表达式> ::= [+|-]<项>{<加法运算符> <项>}
<项> ::= <因子>{<乘法运算符> <因子>}
<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
<关系运算符> ::= =|#|<|<=|>|>=
(2)根据实验一的词法分析的结果进行输入:
对于语法正确的表达式,输出为“Yes,it is correct.”
对于语法错误的表达式,输出为“No,it is wrong.”
3.实验步骤
(1)根据BNF画出语法图并写出文法
表达式的语法图:

项的语法图:

因子的语法图:

文法为:
B->JX(JX)* | X(JX)* (表达式)
X->Y(CY)* (项)
Y->I|N|(B) (因子)
J->+|- (加法运算符)
C->*|/ (乘法运算符)
G->=|#|<|<=|>|>= (关系运算符)
(2)计算是否是LL(1)文法,并算出first和follow集合

根据这三个条件判断LL(1)文法;
不含左递归
计算得到FIRST和FOLLOW集合为:
FIRST(表达式)={+,-,字母,数字}
FIRST(项)={字母,数字,(}
FIRST(因子)={字母,数字,(}
FIRST(加法运算符)={+,- }
FIRST(乘法运算符)={,/}
FIRST(关系运算符)={ =,#,<,<=,>,>=}
FOLLOW(表达式)={+,-,),#}
FOLLOW(项)={+,- ,
,/, ),#}
FOLLOW(因子)={*,/,+,-,),#}
FOLLOW(加法运算符)={字母,数字}
FOLLOW(乘法运算符)={字母,数字}
FOLLOW(关系运算符)={字母,数字}
各个产生式的首符集两两不相交
在表达式中:{+}{-}{字母,数字}两两不相交
在因子中:{字母}{数字}{( }两两不相交
各个FIRST集合中不存在空,不需要讨论。
综上所述,即该文法满足LL(1)文法。
(3)画出程序的算法流程图

表达式递归下降子程序为:
PROCEDURE 表达式;
BEGIN
IF SYM=’+’ OR SYM=’-’ THEN
ADVANCE;
ELSE IF SYM =FIRST(项)
ELSE ERROR;
BEGIN 项;
END;
WHILE SYM=’+’ OR SYM=’-’ THEN
BEGIN
ADVANCE;
项;
END;
项递归下降子程序为:
PROCEDURE 项;
BEGIN
IF SYM =FIRST(因子) THEN
BEGIN
因子;
END;
ELSE ERROR;
WHILE SYM =’*’OR SYM=’/’ THEN
IF SYM =FIRST(因子) THEN
BEGIN
ADVANCE;
因子;
END;
ELSE ERROR;
因子递归下降子程序为:
PROCEDURE 因子;
BEGIN
IF SYM =’(’ THEN
ADVANCE;
表达式;
ADVANCE;
IF SYM=’)’ THEN
ADVANCE;
ELSE ERROR;
ELSE IF SYM =FIRST(因子) THEN
ADVANCE;
ELSE ERROR;
END;
(4)编写代码并测试结果
实验代码在附录中(总结之后)。

4.实验总结
(1)这次实验自己采用的方法是自上而下分析中的递归下降分析法,首先画出了递归下降分析的语法图,然后写出了递归下降的子程序,最后写出了代码,在代码中即可以调用上次词法分析的程序,将结果传到result的这个结构体中即可,或像这次写道的,直接对输入的字符串进行分割传入result结构体。如果想要识别数组函数的话,直接更改首符集的符号即可识别。之前在分割中出现错误,分割字符只取了一个字母,并没有完全截取。还有个错误就是std要写到结构体的前面,否则传参数传不过来。
(2)通过这次实验对于LL(1)文法的三个条件有了更深刻的认识,以及加深对于first 和follow 集合的求法。并且独立完成递归调用函数的书写和实现,对于递归思想又有了进一步的认识,要写函数结束出口,防止函数进入死循环。
(3)通过这次实验进一步了解了自上而下的语法分析:对于输入的词法分析结果,进行左推导,得到一个合法句子或者非法结构,是一种递归和试探的方法,并且自上而下建立输入序列的分析树。而且需要消除左递归并且提取公因子。进一步理解了理论课所学的具体内容,加深对于一些自上而下课后题的理解。这次实验课的收获很大。
5.附录(实验代码)
#include <bits/stdc++.h>
using namespace std;
struct sv
{
string s; //词法分析的类型
string v; //词法分析变量的值
};

string input; //输入全局
int cnt; //全局变量
sv result[200];//存放结果
int k=0;//下标
int ans=0;//遍历的时候的下标
bool error=true;//出错标志
void biaodashi();
void xiang();
void yinzi();
bool judge (string input, string s) ///判断是否和目标串匹配
{
int i=0;
if (input.length()!=s.length()) return false;
else
{

    for(i=0;i<s.length();i++)
    {
        if(input[i]!=s[i])
        {
            //cout<<input[i]<<s[i]<<endl;
            return false;
        }

    }
    return true;
}

}
void shuru()///输入词法分析结果,并把结果存储在结构体中
{
string aa;
//int xx=7;
while(cin>>aa)
{

    const char *d = " ,";
    char *p;
    char buf[1001] ;
    strcpy(buf , aa.c_str());  //字符串转成数组
      p = strtok(buf,d);  //p是一个char*
      int x=0;
      while(p)
      {
        if(x%2==0)
      result[k].s=p;
      else
        result[k].v=p;
        x++;
      //cout<<result[k].v<<endl;
      p=strtok(NULL,d);
      }k++;
     // cout<<result[0].v<<endl;
}
 result[k].v="#";
 k--;

}

void biaodashi() ///表达式的递归下降分析函数
{
if(ans>k) return ;
if(judge(result[ans].v,"+)") || judge(result[ans].v,"-)")) ///加减符号
{
ans++;
if(ans>k)
{
cout<<1<<endl;
error=false;///错误判定
}
xiang();
}

else if( judge(result[ans].v,"()") ||judge(result[ans].s,"(ident") ||judge(result[ans].s,"(number"))
{
    xiang();//项目判定,前面条件是first集合
}
else
{
    cout<<2<<endl;
    error=false;///错误判定
}//

while(judge(result[ans].v,"+)") || judge(result[ans].v,"-)"))
{
    ans++;
    if(ans>k)
    {
        cout<<3<<endl;
        error=false;///错误判定
    }
    xiang();   //项目循环
}

}
void xiang()
{
if(ans>k) return ;
yinzi(); //因子判断

while(judge(result[ans].v,"*)") || judge(result[ans].v,"/)"))
{
    ans++;
    if(ans>k)
    {
        cout<<4<<endl;
        error=false;///错误判定
    }
    yinzi();
}

}
void yinzi()
{
if(ans>=k) return ;
if(judge(result[ans].s,"(ident") ||judge(result[ans].s,"(number")) //开头字母或数字
{
ans++;
if(ans>k)
{
cout<<5<<endl;
error=false;///错误判定
}
}
else if(judge(result[ans].v,"()")) //左括号
{
ans++;
biaodashi(); //表达式

    if(judge(result[ans].v,"))"))  //右括号
    {
        ans++;
      if(ans>k)
      {
          cout<<6<<endl;
          error=false;///错误判定
      }

    }

}
else
{
    cout<<7<<endl;
    error=false;///错误判定
}

}
int main()
{
shuru(); //输入词法分析结果,写到result里
biaodashi();//语法分析
if(!judge(result[ans+1].v,"#"))
{
error=false;
}
//cout<<ans<<endl;
if(error==true)
cout<<“Yes,it is correct.”<<endl;

else
{
cout<<“No,it is wrong.”<<endl;
}
return 0;
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值