递归下降语法分析

  • 程序功能描述
    1. 程序目标

实现 LL(1)分析中控制程序( 表驱动程序),根据给定赋值语句的 LL(1)文法,完成分析过程。

输入:词法分析的二元式序列,输入结构如下:

typedef struct Dual

{

    int Identifier;

    char Character;

}

输出:输入串是否为该文法定义的算术表达式(bool)。

      1. 正则文法

    G[S]:   S→V=E

            E→TE′

            E′→ ATE′|ε

            T→FT′

            T′→ MFT′|ε

            F→ (E)|i

            A→+|-

            M→*|/

            V→i

(1) 递归下降分析程序应能发现简单的语法错误。

    1. 运行环境

语言:C++语言

编辑器:codeblocks

txt文件:用于保存词法分析结果,并作为语法分析的输入。

  • 程序结构描述
    1. 设计方法

字符类型及字符串类型的识别使用穷举法搜索法。穷举搜索法是按某种顺序对所有可能的值进行逐个验证,从中找出符合条件的解。此方需要多重循环,简单易行,并且适合词法分析程序的查表原则。

正则文法的分析使用穷举搜索法及回溯法。穷举回溯法与以上同理,即对规则进行逐一的验证。回溯法主要用于/* */标记的注释的回溯,当无法匹配*/时,需要进行回溯,从/*标记的后一位重新开始进行扫描分析。

    1. 预处理

在程序中,由于没有编写产生FIRST集和FOLLOW集的函数,因此需要对文法进行预处理,得到其FIRST集和FOLLOW集,本程序的FIRST集和FOLLOW集如下:

元素

FIRST集

FOLLOW集

S→V=E

i,

#

E→TE′

(,i

),#

E′→ ATE′|ε

ε,+,-

),#

T→FT′

(,i

+,-,),#

T′→ MFT′|ε

*,/,ε

+,-,),#

F→ (E)|i

(,i

*,/,+,-,),#

A→+|-

+,-

(,i

M→*|/

*,/

(,i

V→i

i

=

    1. 函数定义
      1. 主函数

函数原型:int main()

参数:无

返回值:0(default)

功能说明:程序的入口,首先调用读文件程序读入文件,然后调用语法分析入口程序开始语法分析,若语法分析正确,最终输出结果将由主函数输出,否则将在中间环节返回错误信息。

      1. 读取文件函数

函数原型:bool ReadFile()

参数:无

返回值:是否正确读取文件内容

功能说明:将文件内容读入,并放入指定的数据结构中

      1. 游标移动函数

函数原型:void advance()

参数:无

返回值:无

功能说明:移动游标

      1. 各语句实现函数

函数原型:bool S();

bool E();

bool E1();

bool T();

bool T1();

bool F();

bool A();

bool M();

bool V();

参数:无

返回值:符合文法规则返回true,否则返回false

功能说明:分别定义各语句的文法规则,通过互相调用实现递归算法。

      1. 错误输出

函数原型:void error_report(string Wrong)

参数:错误位置信息

返回值:无

功能说明:若产生输入串与语法规则不符,则将被其他函数调用以输出错误信息

    1. 函数具体实现
      1. 主函数
        1. 源码:

int main()

{

    if(ReadFile())

    {

        cout << "file input:";

        for(current = listdual.begin(); current != listdual.end(); ++current)

        {

            cout << (*current).Character  <<" " ;

        }

        cout <<"\n";

        current = listdual.begin();

 

        cout << "analysis:" << endl;

        //从起始符号开始,自顶向下分析

        if(S())

            cout << "The result is Right!" << endl;

        else

            error_report("input");

    }

    else

    {

        error_report("ReadFile()");

    }

 

    return 0;

}

        1. 逻辑关系图:

图1  main函数调用逻辑关系图

      1. 文件识别函数
        1. 源码:

         bool ReadFile()

{

    DUAL temp;

    inFile.open("right.txt");

    while(!inFile.eof())

    {

        inFile >> temp.Identifier >> temp.Character;

        listdual.push_back(temp);

    }

    inFile.close();

    return true;

}

      1. 游标移动函数
        1. 源码:

void advance()

{

    current++;

}

      1. 错误输出函数
        1. 源码:

void error_report(string Wrong)

{

    cout <<"ERROR:"<< Wrong << "  error"<< endl;

}

      1. 产生式相关函数

// S->V=E

bool S()

{

    if(current == listdual.end())

    {

        error_report("S() read file");

        return false;

    }

    cout<<"S->V=E"<<endl;

    if(!V())

        return false;

    if((*current).Character == '='){

        cout<<"="<<endl;

        advance();

    }else  return false;

    if(!E())

        return false;

 

    return true;

}

 

 

//E→TE′

bool E(){

    if(current == listdual.end())

    {

        error_report("E() read file");

        return false;

    }

    cout<<"E->TE'"<<endl;

    if(!T())

        return false;

    if(!E1())

        return false;

    return true;

}

// E′→ ATE′|ε

bool E1(){

    if(current == listdual.end())

    {

        error_report("E1() read file");

        return false;

    }

    else

    {

        if((*current).Character == '+' || (*current).Character == '-' )

        {

            cout<<"E'→ATE'"<<endl;

 

            //按照匹配的候选式进行递归。

            if(!A())

                return false;

            if(!T())

                return false;

            if(!E1())

                return false;

 

        }

        else if((*current).Character == ')' || (*current).Character == '#')

            cout<<"E'→ε"<<endl;

        else

        {

            error_report("E1()");

            return false;

        }

    }

    return true;

}

// T→FT′

bool T(){

    if(current == listdual.end())

    {

        error_report("T() read file");

        return false;

    }

    cout<<"T→FT′"<<endl;

    if(!F())

        return false;

    if(!T1())

        return false;

    return true;

}

//T′→ MFT′|ε

bool T1(){

    if(current == listdual.end())

    {

        error_report("E1() read file");

        return false;

    }

    else

    {

        if((*current).Character == '*' || (*current).Character == '/' )

        {

            cout<<"T′→ MFT′"<<endl;

 

            //按照匹配的候选式进行递归。

            if(!M())

                return false;

            if(!F())

                return false;

            if(!T1())

                return false;

 

        }

        else if((*current).Character == ')' || (*current).Character == '#'||(*current).Character == '+'||(*current).Character == '-')

            cout<<"T'→ε"<<endl;

        else

        {

            error_report("E1()");

            return false;

        }

    }

    return true;

 

}

// F→ (E)|i

bool F()

{

     if(current == listdual.end())

    {

        error_report("F() read file");

        return false;

    }

 

    if((*current).Character == '(')

    {

        advance();

        if(!E())

            return false;

        else if((*current).Character == ')')

        {

            advance();

            cout << "F->(E)" <<endl;

        }

        else

            return false;

    }

    if((*current).Character == 'i')

    {

        cout << "F->i" << endl;

        advance();

    }

    return true;

}

 

// A→+|-

bool A()

{

    if(current == listdual.end())

    {

        error_report("A() read file");

        return false;

    }

 

    if((*current).Character == '+'||(*current).Character == '-')

    {

        cout<<"A→"<< (*current).Character <<endl;

    }

    else

    {

        error_report("A()");

        return false;

    }

    advance();

    return true;

}

// M→*|/

bool M()

{

    if(current == listdual.end())

    {

        error_report("M() read file");

        return false;

    }

 

    if((*current).Character == '*' || (*current).Character == '/')

    {

        cout << "M->" << (*current).Character << endl;

        advance();

    }

    else

    {

        error_report("M()");

        return false;

    }

    return true;

}

 

// V→i

bool V(){

        if(current == listdual.end())

    {

        error_report("V() read file");

        return false;

    }

    if((*current).Character == 'i'){

        cout << "V->" << (*current).Character << endl;

        advance();

    }

    else{

        error_report("V()");

        return false;

    }

    return true;

}

 

  • 程序测试
    1. 测试用例
      1. 测试用例一:正确输入串

1 i

2 =

3 (

4 i

5 +

6 i

7 )

8 /

9 i

10 #

测试结果:

测试用例二:错误输入串

1 i

2 +

3 i

4 (

3 i

4 #

    1. 测试结果

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下降分析法 一、实验目的: 根据某一文法编制调试下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对下降分析法的理解。 二、实验说明 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.利用下降分析分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值