编译原理:语法分析1-递归下降

递归下降的预测分析:为每一个非终结符写一个分析过程。

要求:

  1. 使用的文法如下:
    E →TE’
    E → + TE’ | ε
    T → FT’
    T →* FT’ | ε
    F → (E) | id
  2. 对于任意给定的输入串(词法记号流)进行语法分析,递归下降方法实现。
  3. 要有一定的错误处理功能。即对错误能提示,并且能在一定程度上忽略尽量少的记号来进行接下来的分析。可以参考书上介绍的同步记号集合来处理。
    可能的出错情况:idid*id, id**id, (id+id, +id*+id ……
  4. 输入串以#结尾,输出推导过程中使用到的产生式。例如:
    输入:id+id*id#
    输出:E →TE
    T →FT
    F →id
    E →+ TE
    T →FT
    ……

代码

#include<iostream>

using namespace std;

static string ahead="";//当前正待处理的输入记号
static string sub="";//当前待处理记号被处理后的输入
void E();
void E_();//表示E'
void T();
void T_();//表示T'
void F();
void error();
void match(string t);
string nextToken();
int main()
{
    //不用自己输入#
    char a[100]={};//保存用户输入,接收输入,不要超过100个字符,否则getline会设置失效位,接下来的输入(如果有的话)将被阻断,需要的话,可以调用cin.clear()恢复输入
    cin.getline(a,100);//遇见回车表示输入结束
    sub=a;
    sub+='#';
    ahead=nextToken();
    E();//因为E是开始符号
    return 0;
}
void E()
{
    if(ahead=="("||ahead=="id")//First(T)={(,id}
    {
        cout<<"E→TE'"<<endl;
        T();
        E_();
    }
    else if(ahead==")"||ahead=="#")//Follow(E)加入到E的同步记号集合中
    {
       // error();
       //出错,但无须跳过任何记号,跳过E即可,即不作任何处理
        ;
    }
    else//出错,当前记号不在E的同步记号集合中,跳过当前记号
    {
        //error();
        ahead=nextToken();
        E();
    }
}
void E_()
{
    if(ahead=="+")
    {
        cout<<"E'→+TE'"<<endl;
        match("+");
        T();
        E_();
    }
    else if(ahead==")"||ahead=="#")//Follow(E')={),$},这里#代表$
    {
        cout<<"E'→ε"<<endl;
    }
    else//出错,当前记号不在E'的同步记号集合中,跳过当前记号
    {
        //error();
        ahead=nextToken();
        E_();
    }
}
void T()
{
    if(ahead=="("||ahead=="id")//First(F)={(,id}
    {
       cout<<"T→FT'"<<endl;
       F();
       T_();
    }
    else if(ahead=="+"||ahead==")"||ahead=="#")//Follow(T)加入到T的同步记号集合中
    {
        // error();
       //出错,但无须跳过任何记号,跳过T即可,即不作任何处理
        ;
    }
    else//出错,当前记号不在T的同步记号集合中,跳过当前记号
    {
        //error();
        ahead=nextToken();
        T();
    }
}
void T_()
{
    if(ahead=="*")
    {
        cout<<"T'→*FT'"<<endl;
        match("*");
        F();
        T_();
    }
    else if(ahead=="+"||ahead==")"||ahead=="#")//FOllow(T')={+,),$},这里#代表$
    {
        cout<<"T'→ε"<<endl;
    }
    else//出错,当前记号不在T'的同步记号集合中,跳过当前记号
    {
        //error();
        ahead=nextToken();
        T_();
    }
}
void F()
{
    if(ahead=="(")
    {
        cout<<"F→(E)"<<endl;;
        match("(");
        E();
        match(")");
    }
    else if(ahead=="id")
    {
        cout<<"F→id"<<endl;;
         match("id");
    }
    else if(ahead=="+"||ahead=="*"||ahead==")"||ahead=="#")//Follow(F)加入到F的同步记号集合中
    {
         // error();
       //出错,但无须跳过任何记号,跳过 F 即可,即不作任何处理
        ;
    }
    else//出错,当前记号不在 F 的同步记号集合中,跳过当前记号
    {
        //error();
        ahead=nextToken();
        F();
    }
}
void error()
{
    cout<<"匹配失败!!!"<<endl;
}
void match(string t)
{
    if(ahead==t)
    {
        cout<<"匹配"<<ahead<<endl;
        ahead=nextToken();
    }
    else
        error();
}
string nextToken()//获取下一个词法记号
{
    if(sub.substr(0,2)=="id")
    {
         sub=sub.substr(2,sub.size()-2);
         return "id";
    }
    else
    {
        string s=sub.substr(0,1);
        sub=sub.substr(1,sub.size()-1);
        return s;
    }
}

运行结果

在这里插入图片描述

  • 可以与P59表3.2的动作比较一下,发现是一致的
第三次上机—语法分析1 目的:熟练掌握自上而下的语法分析方法,并能用C++程序实现。 要求: 1. 使用的文法如下: E ® TE ¢ E ¢ ® + TE ¢ | e T ® FT ¢ T ¢ ® * FT ¢ | e F ® (E) | id 2. 对于任意给定的输入串(词法记号流)进行语法分析递归下降方法和非递归预测分析方法可以任选其一来实现。 3. 要有一定的错误处理功能。即对错误能提示,并且能在一定程度上忽略尽量少的记号来进行接下来的分析。可以参考书上介绍的同步记号集合来处理。 可能的出错情况:idid*id, id**id, (id+id, +id*+id …… 4. 输入串以#结尾,输出推导过程中使用到的产生式。例如: 输入:id+id*id# 输出:E ® TE ¢ T ® FT ¢ F ® id E ¢ ® + TE ¢ T ® FT ¢ …… 如果输入串有错误,则在输出中要体现是跳过输入串的某些记号了,还是弹栈,弹出某个非终结符或者是终结符了,同时给出相应的出错提示信息。比如: idid*id对应的出错信息是:“输入串跳过记号id,用户多输入了一个id”; id**id对应的出错信息是:“弹栈,弹出非终结符F,用户少输入了一个id” (id+id对应的出错信息是:“弹栈,弹出终结符 ) ,用户少输入了一个右括号(或者说,括号不匹配)” 有余力的同学可进一步考虑如下扩展: 1. 将递归下降方法和非递归预测分析方法都实现 2. 在语法分析的过程中调用第二次上机的结果,即利用词法分析器来返回一个记号给语法分析器。 3. 编写First和Follow函数,实现其求解过程。 测试文法: A->BCDE B->aBA|ε C->F|ε D->b|c|ε E->e|ε F->d|ε
递归下降分析法 一、实验目的: 根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。 二、实验说明 1、递归下降分析法的功能 词法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。 2、递归下降分析法的前提 改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法, 3、递归下降分析法实验设计思想及算法 为G的每个非终结符号U构造一个递归过程,不妨命名为U。 U的产生式的右边指出这个过程的代码结构: (1)若是终结符号,则和向前看符号对照, 若匹配则向前进一个符号;否则出错。 (2)若是非终结符号,则调用与此非终结符对应的过程。当A的右部有多个产生式时,可用选择结构实现。 三、实验要求 (一)准备: 1.阅读课本有关章节, 2.考虑好设计方案; 3.设计出模块结构、测试数据,初步编制好程序。 (二)上课上机: 将源代码拷贝到机上调试,发现错误,再修改完善。第二次上机调试通过。 (三)程序要求: 程序输入/输出示例: 对下列文法,用递归下降分析法对任意输入的符号串进行分析: (1)E->eBaA (2)A->a|bAcB (3)B->dEd|aC (4)C->e|dc 输出的格式如下: (1)递归下降分析程序,编制人:姓名,学号,班级 (2)输入一以#结束的符号串:在此位置输入符号串例如:eadeaa# (3)输出结果:eadeaa#为合法符号串 注意: 1.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好); 2.对学有余力的同学,可以详细的输出推导的过程,即详细列出每一步使用的产生式。 (四)程序思路 0.定义部分:定义常量、变量、数据结构。 1.初始化:从文件将输入符号串输入到字符缓冲区中。 2.利用递归下降分析分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值