已有预测分析表时的语法分析

原创 2015年11月19日 19:36:46

这篇是编译原理的课堂作业实验题

  • 题目要求
    为给定文法写预测分析程序,预测分析表已知(虽然求取预测分析表更重要,但是老师要求是给定预测分析表的情况下写预测分析程序),文法如下:
    E–>TE’
    E’–> +TE’|ε
    T–>FT’
    T’–> *FT’|ε
    F–>(E) | i
    预测分析表(太难打了):
表格 i + * ( ) #
E E–>TE’ E–>TE’
E’ E’–> +TE’ E’–>ε E’–>ε
T T–>FT’ T–>FT’
T’ T’–>ε T’–> *FT’ T’–>ε T’–>ε
F F–>i F–>(E)
  • 设计分析
    预测分析程序的重点应该是预测分析表的创建,但是我猜老师的意思应该是考察我们的编程能力,时间有限,我们只做老师要求的在给定预测分析表的情况下写预测分析程序,关于预测分析表的生成等内容可以在任意编译原理课本上找到,这里不再赘述。
    虽然给定预测分析表,但是编程时还是有很多东西需要考虑,首先是预测分析表用什么存储,我是用了一个Node结构体
struct Node{
    char vn;        //非终结符
    char vt[VT];    //所有终结符
    int p[VT];      //产生式规则
    Node(){
        memset(p,-1,sizeof(p));
    }
};

“vn”用于存储非终结符,“vt”数组存储所有的终结符号,在 p数组中存储预测分析表中,确定非终结符和确定终结符所需要的产生式规则,这里所找到的是产生式规则的索引,我们将产生式存放在一个字符指针数组中

const char* production[]

我们得到的索引就是对应的数组下标(这样存储在数据更多的时候可以节省很多空间)。
数据结构定义好之后,程序实现就很简单了,源代码如下:

  • 代码实现
#include<iostream>
#include<cstring>
#include<ctype.h>
#include<cstdio>
#define VT 6    //终结符号个数
#define VN 5    //非终结符号个数
#define MAXLINE 100
using namespace std;
struct Node{
    char vn;        //非终结符
    char vt[VT];    //所有终结符
    int p[VT];      //产生式规则
    Node(){
        memset(p,-1,sizeof(p));
    }
};
Node MTable[VN];
const char* production[]={"Te","Ft","i","+Te","$","*Ft","(E)"}; //所有的产生式右部
void getTable(Node *);      //获得预测分析表
void out(int cnt,const char* st,const char *tex,int j,int k,char c);   //输出当前状态
char st[MAXLINE];       //栈
int sp=0;               //栈顶指针
int main()
{
    int c,l;
    getTable(MTable);
    char tex[MAXLINE];
    memset(st,' ',sizeof(st));
    gets(tex);
    /*
    while((c=getchar())!='#'&& c!=-1)
        *(p++)=c;
    *(p++)=c;
    *p='\0';
    */

    l=strlen(tex);
    tex[l]='#'; tex[l+1]='\0';
    st[sp++]='#';
    st[sp++]='E';
    int cnt=1,i,j,k=0;
    cout<<"步骤"<<"    "<<"分析栈"<<"               "<<"剩余输入串"<<"         "<<"指导所用产生式或函数"<<endl;
    char cur,pd[MAXLINE],*pp;  //pd:production缩写,cur当前栈顶元素
    for(i=0;sp>0;cnt++){
        cur=st[--sp];
        if(st[sp]=='#'){
            st[sp+1]='\0';
            out(cnt,st,tex+i,j,-1,'#');
            continue;
        }
        if(cur==(c=tex[i])&&i<l){
            i++;
            st[sp+1]='\0';
            out(cnt,st,tex+i-1,j,-1,c);
            continue;
        }
        pp=pd;  memset(pd,0,sizeof(pd));
        for(j=0;j<VN;j++)                       //查找该非终结符对应哪个结点
            if(MTable[j].vn==cur)    break;
        if(MTable[j].vn!=cur){
            cout<<"error:不能识别输入的字符串"<<endl;
            break;
        }
        k=0;
        while(k<VT&&MTable[j].vt[k]!=c) k++;    //当前非终结符遇到该终结符对应的产生式规则
        if(k==VT) { cout<<"Error:输入有误"<<endl;    break;}
        k=MTable[j].p[k];       //重用
        st[sp+1]='\0';
        out(cnt,st,tex+i,j,k,'a');


        memcpy(pp,production[k],sizeof(production[k]));
        if(k!=4){       //产生式不为空串'$'
            int len=strlen(pp);
            while(--len>=0) st[sp++]=*(pp+len); //逆序入栈
        }
    }
    return 0;
}
void getTable(Node*t)        //获得预测分析表
{
    t[0].vn='E',t[1].vn='e',t[2].vn='T',t[3].vn='t',t[4].vn='F';    //非终结符
    for(int i=0;i<VT;i++){          //终结符
        t[i].vt[0]='i';     t[i].vt[1]='+';   t[i].vt[2]='*';
        t[i].vt[3]='(';     t[i].vt[4]=')';   t[i].vt[5]='#';
    }
    //下面用来存储相应的产生式的索引
    t[0].p[0]=0;    t[0].p[3]=0;
    t[1].p[1]=3;    t[1].p[4]=4;    t[1].p[5]=4;
    t[2].p[0]=1;    t[2].p[3]=1;
    t[3].p[1]=4;    t[3].p[2]=5;    t[3].p[4]=4;    t[3].p[5]=4;
    t[4].p[0]=2;    t[4].p[3]=6;
}
/*cnt是步骤计数,st是栈底指针,tex是剩余输入符号指针,j表示第j个Node,k表示运用的产生式
 *的索引号,如果k=-1表示一个非终结符匹配成功或者完成接受*/
void out(int cnt,const char* st,const char *tex,int j,int k,char ac)    ////输出当前状态
{
    char s[MAXLINE],*p,cu[3],cur=MTable[j].vn,pd[MAXLINE],*q;
    p=s;    q=pd;
    int i=0,c;
    while((c=*(st+i))!='\0'){
        if(islower(c)&&c!='i'){
            *(p++)=toupper(c);
            *(p++)='\'';
        }else
            *(p++)=c;
        i++;
    }
    *p='\0';    i=0;
    if(k!=-1){
        while((c=*(production[k]+i))!='\0'){
            if(islower(c)&&c!='i'){
                *(q++)=toupper(c);
                *(q++)='\'';
            }else
                *(q++)=c;
            i++;
        }
    }else
        *(q++)=ac;
    *q='\0';    i=0;
    if(islower(cur)&&cur!='i'){
        cu[i++]=toupper(cur);
        cu[i++]='\'';
    }else
        cu[i++]=cur;
    cu[i]='\0';
    if(k!=-1)
        printf("%4d    %-15s %15s        %-2s-->%s\n",cnt,s,tex,cu,pd);
    else if(ac!='#')
        printf("%4d    %-15s %15s        %s匹配\n",cnt,s,tex,pd);
    else
        printf("%4d    %-15s %15s        接受\n",cnt,s,tex,cu,pd);
}

这个程序可以接受所有的 + *的表达式(要求表达式的字母只能为i)如:
i+i*i、 (i+i)*(i+i)+i 等等

  • 程序测试 输入 (i+i)*(i+i)+i
    注意括号为英文符号
    这里写图片描述
    这里写图片描述

所有的函数都有我编写的时候留下的注释,应该可以看得明白,如有疑问,可以留言,力所能及 乐意解答

版权声明:本文为博主原创文章,未经博主允许不得转载。

预测分析表【LL(1)分析表】的构造

预测分析表【LL(1)分析表】的构造 算法: 对于G中的每一个产生式, A -> α ,执行以下2步: 1.for  ∀ a ∈ FIRST(α), 将 A -> α 填入 M [A, a ]; ...
  • hit_rxz
  • hit_rxz
  • 2014年12月01日 20:26
  • 9674

编译原理:LL(1)文法 语法分析器(预测分析表法)

设计要求:对于任意输入的一个LL(1)文法,构造其预测分析表,并对指定输入串分析其是否为该文法的句子。 思路:首先实现集合FIRST(X)构造算法和集合FOLLOW(A)构造算法,再根据FIRST和F...
  • NK_test
  • NK_test
  • 2016年05月22日 20:54
  • 21871

预测分析表中的FIRST和FOLLOW集合求法个人小结

FIRST(a)其实就是可从a推导得出的串的首符号的集合.FOLLOW(a)就是在某些句型中可能紧跟在a右边的终结符号的集合.它们有一个很严谨但是很难懂的创建规则: FIRST集求法 Firs...
  • linhaiyun_ytdx
  • linhaiyun_ytdx
  • 2016年05月17日 17:06
  • 1442

编译原理:LL(1)文法 语法分析器(预测分析表法)

设计要求:对于任意输入的一个LL(1)文法,构造其预测分析表,并对指定输入串分析其是否为该文法的句子。 思路:首先实现集合FIRST(X)构造算法和集合FOLLOW(A)构造算法,再根据FIRST和...
  • bfboys
  • bfboys
  • 2016年09月08日 19:02
  • 985

语法分析器 (基于预测分析表)

老师有木有让你写个语法分析器   编译原理第
  • u014403845
  • u014403845
  • 2014年05月21日 00:00
  • 484

SLR(1)预测分析表的构建以及对句子的分析步骤

SLR(1)预测分析表相关知识 首先,SLR(1)分析器是自上而下语法分析里面的分析器; 步骤:(1)写出已知文法G的扩展文法G'            (2)写出扩展文法G'的初始项目集     ...
  • qq_36744540
  • qq_36744540
  • 2017年06月20日 17:35
  • 1361

LL(1)文法的预测分析表法2.0加强版

  • 2016年09月30日 00:03
  • 112KB
  • 下载

预测分析表

  • 2008年07月31日 09:09
  • 3KB
  • 下载

编译原理(五) LL(1)文法分析法(预测分析表的构造算法C++实现)

基本定义 FIRST(α):FIRST(\alpha): 令G是一个不含左递归的文法,对G的所有非终结符的每个候选α定义它的终结首符集FIRST(α)为: FIRST(α)={a | α=>*a…...
  • qq_24451605
  • qq_24451605
  • 2015年11月28日 20:02
  • 7903

编译原理 预测分析表的实现

 /**//* *  程序功能:该程序为语法分析中的预测分析程序, *            可根据给出的文法分析一段表达式是否 *            满足该文法。 *  *  版本 :1.00 ...
  • sparkvivid
  • sparkvivid
  • 2008年05月25日 01:48
  • 6262
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:已有预测分析表时的语法分析
举报原因:
原因补充:

(最多只允许输入30个字)