• 语法分析:算术表达式预测分析程序设计


    1、实验目的:
    (1)掌握自上而下语法分析的要求与特点。
    (2)掌握LL(1)语法分析的基本原理和方法。
    (3)掌握相应数据结构的设计方法。

    2、实验内容:
    编程实现给定算术表达式的分析器。
    算术表达式文法如下:
    E-->E+T|T
    T-->T*F|F
    F-->(E)|i

    3、设计说明:
    首先改写文法为LL(1)文法;构造LL(1)分析表,然后编写预测分析程序。

    4、设计分析与步骤
    (1)将原算术表达式方法改写为LL(1)文法为:
    E-->TE'
    E'-->+TE'|ε
    T-->FT'
    T'-->*FT'|ε
    F-->(E)|i

    (2)计算文法中每一个非终结符的FIRST集和FOLLOW集


    FIRST

    FOLLOW

    E

    { (,i }

    { $,) }

    E’

    { +,ε }

    { ),$ }

    T

    { (,i }

    { ),+,$ }

    T’

    { *,ε }

    { ),+,$ }

    F

    { (,i }

    { * }


    (3)构造预测分析表
    1、对于规则E-->TE’,因为有E的FIRST(TE’)={(,i},所以可以置M[E,(]=E-->TE’,M[E,i]=E-->TE’
    2、 对规则E’-->+TE’,有FIRST(+TE’)={+},所以有M[E’,+]=E’-->+TE’
    3、对规则E’-->ε,有FOLLOW(E’)={), $},所以有M[E’, )]=E’-->ε,M[E’, $]=E’-->ε
    4、对于规则T-->FT’,因为有FT’的FIRST(FT’)={(,i},所以可以置M[T,(]=T-->FT’,M[T,i]=T-->FT’
    5、对规则T-->*FT’,有FIRST(*FT’)={*},所以有M[T,*]=T-->*FT’
    6、对规则F-->(E),有FIRST((E))={(},所以有M[F,(]=F-->(E)
    7、对规则F-->ε,有FOLLOW(F)={*},所以有M[F,*]=F-->ε


    I

    (

    )

    +

    *

    $

    E

    E-->TE’

    E-->TE’





    E



    E’-->ε

    E’-->+TE’


    E’-->ε

    T

    T-->FT’

    T-->FT’





    T



    T’-->ε

    T’-->ε

    T’-->*FT’

    T’-->ε

    F

    F-->i

    F-->(E)







    (4)程序设计
    用vector<char>定义的S和Stc分别作为分析栈和用户输入栈,用string类型的STC获取用户输入的原始字符串。用string类型的二维数组存储预测分析表。
    1,$和E进分析栈S,$和倒序用户输入串压入用户栈Stc
    2,判断S和Stc栈顶不同时为$,如果是则下一步,如果不是则跳出判断
    3,根据S和Stc栈顶元素查分析表查找规则
    (1)如果查到一般规则,则进行相应的S的弹栈与压栈并比较两栈顶元素,如果相等则都弹栈
    (2)如果查到含空串的规则,则S弹栈并比较两栈顶元素,如果相等则都弹栈
    (3)如果查表越界则显示错误
    4,重复3直到两栈顶都是$元素显示分析成功
    5,提示用户输入0继续分析下一条,其它输入退出程序。

    //源程序代码
    #include<iostream>
    #include<vector>
    #include<string>
    using namespace std;
    int main()
    {
    string sheet[5][6]={{"TA","TA","","","",""}, //预测分析表
    {"","","e","+TA","","e"}, /行:E,A(代表 E1),T,B(代表 T1),F
    {"FB","FB","","","",""}, //列:i,(,),+,*,$
    {"","","e","e","*FB","e"}, //e代表空串
    {"i","(E)","","","",""}};
    vector<char> S;
    vector<char> Stc;
    vector<char> SOS;
    string STC;
    int YourChoice;
    do{
    cout<<endl;
    S=SOS; //S代表分析栈,每次执行用空的SOS初始化
    S.push_back('$');
    S.push_back('E');
    STC=""; //STC代表用户的表达式
    cout<<"请输入您要分析的字符串:";
    cin>>STC;
    STC.resize(STC.size()+1);
    STC[STC.size()-1]='$';
    Stc=SOS; //Stc是将STC+$倒序压入的用户输入栈
    for(int x=STC.size()-1;x>=0;--x)
    Stc.push_back(STC[x]);
    string YY="EATBF";
    string XX="i()+*$";
    while(!(S[S.size()-1]=='$'&&Stc[Stc.size()-1]=='$'))
    {
    int i=0,j=0;
    ////////////////////查表找到相应规则////////////////////
    for(i=0;i<5;++i)
    if(YY[i]==S[S.size()-1])
    break;
    for(j=0;j<6;++j)
    if(XX[j]==Stc[Stc.size()-1])
    break;
    if(i>=5||j>=6) //如果查找超出表
    {
    cout<<"出错啦!"<<endl;
    break;
    }
    else if(sheet[i][j]=="") //如果查到的为空规则
    {
    cout<<"出错啦!"<<endl;
    break;
    }
    else
    {
    ///////////////分析栈里的压栈与弹栈////////////////////
    S.pop_back();
    for(int k=sheet[i][j].size()-1;k>=0;--k)
    S.push_back(sheet[i][j][k]);
    if(S[S.size()-1]==Stc[Stc.size()-1]) //一般规则
    {
    S.pop_back();
    Stc.pop_back();
    }
    else if(S[S.size()-1]=='e') //含空串的规则
    {
    S.pop_back();
    if(S[S.size()-1]!='$'&&Stc[Stc.size()-1]!='$'&&S[S.size()-1]==Stc[Stc.size()-1])
    {
    S.pop_back();
    Stc.pop_back();
    }
    }
    }
    }

    if(S[S.size()-1]=='$'&&Stc[Stc.size()-1]=='$')
    cout<<"分析成功!"<<endl;
    cout<<"输入0继续,其它退出";
    }while(cin>>YourChoice&&YourChoice==0);

    return 0;
    }


    测试用例
    (1)输入i,预期显示分析成功
    (2)输入iii,预期显示出错
    (3)输入a,预期显示出错
    (4)输入(i),预期显示分析成功
    (5)输入(a),预期显示出错
    (6)输入(i+i),预期显示分析成功
    (7)输入(i+i,预期显示出错
    (8)输入((i*i)+i)*i,预期显示分析成功
    (9)输入((((i+i*i)))),预期显示分析成功
    (10)输入(i+ia,预期显示出错
    (11)输入i+i*i+i*a,预期显示出错
  • 相关阅读:
    vue-lazy-component
    vue修饰符sync
    vue-router-auto动态生成路由插件
    我的第一个WebAPI程序
    GitHub界面初识
    新闻API接口
    childNodes属性 和 nodeType属性
    接口测试总结
    网站被k
    js声明引入和变量声明和变量类型、变量
  • 原文地址:https://www.cnblogs.com/mazhuang/p/1641660.html
Copyright © 2020-2023  润新知