递归下降语法分析

  • 程序功能描述
    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"<

    if(!V())

        return false;

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

        cout<<"="<

        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'"<

    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'"<

 

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

            if(!A())

                return false;

            if(!T())

                return false;

            if(!E1())

                return false;

 

        }

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

            cout<<"E'→ε"<

        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′"<

    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′"<

 

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

            if(!M())

                return false;

            if(!F())

                return false;

            if(!T1())

                return false;

 

        }

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

            cout<<"T'→ε"<

        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)" <

        }

        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 <

    }

    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. 测试结果

你可能感兴趣的:(编译原理)