实验九 LL(1)分析

一、实验目的

学习和掌握LL(1)文法的判定和LL(1)分析方法。

二、实验任务

(1)存储文法的LL(1)分析表;
(2)根据LL(1)分析表判断文法是否LL(1)文法;
(3)实现LL(1)分析过程。

三、实验内容

(1)确定LL(1)分析表的文件存储格式。要求为3个以上测试文法准备好相应LL(1)分析表的存储文件。
(2)根据LL(1)分析表判断文法是否LL(1)文法。看每个表项是否最多只有一条候选式,如是该文法是LL(1)文法。
(3)实现LL(1)分析过程。当(2)判断出该文法是LL(1)文法时,要求给出3个以上输入串的LL(1)分析过程,并判断输入串是否该文法的合法句子。

四、测试结果

文法一:

E -> TY
Y -> +TY | e
T -> FZ
Z -> *FZ | e
F -> (E) | i

测试结果1:

这里写图片描述
这里写图片描述

测试结果2:

这里写图片描述

文法二:

S -> T
T -> (S)ST | a

测试结果一:

这里写图片描述

测试结果二:

这里写图片描述

文法三:

S -> iEtST | a
T -> bS | e
E -> c

测试结果:
这里写图片描述

完整代码

/*
  in
      test1  i+i*i
      test2  +i*+i

  in1
      test1  (a)aa
      test2  (a)aaa
*/
#include<iostream>
#include<string>
#include<fstream>
#include<map>
#include<set>
#include<iomanip>
#define filename "in.txt"
using namespace std;
ifstream input(filename);
map<char,set<char>>first; //first集合
map<char,set<char>>follow; //follow集合
map<char,set<char>>first_temp;
map<char,set<char>>follow_temp;
map<char,set<string>>string_temp;
set<char>table; //终结符号
set<char>no_end; //非终结符
string s[10][10]; //分析表
map<char,int>xlab;
map<char,int>ylab;
void First(){
    string temp;
    while(getline(input,temp)){
         int len = temp.length();
         if(first.find(temp[0])==first.end()){
            int l=5;
            while(temp[l]!='|'&&l<len) l++;
                 if(!(temp[5]>='A'&&temp[5]<='Z'))
                     first[temp[0]].insert(temp[5]);
                 else
                     first_temp[temp[0]].insert(temp[5]);
                 if(l<len&&temp[l]=='|'){
                    if(!(temp[l+2]>='A'&&temp[l+2]<='Z'))
                         first[temp[0]].insert(temp[l+2]);
                    else first_temp[temp[0]].insert(temp[l+2]);
               }
         }
    }
    map<char,set<char>>::iterator it=first_temp.begin();
    while(first_temp.size()!=0){
        set<char>::iterator ij=it->second.begin();
        while(ij!=it->second.end()){
             if(first.find(*ij)!=first.end()){
                set<char>::iterator ik=first[*ij].begin();
                while(ik!=first[*ij].end())
                      first[it->first].insert(*ik),ik++;
                it->second.erase(ij++);
             }
             else ij++;
        }
        if(it->second.size()==0)
           first_temp.erase(it++);
        else
           it++;
        if(it==first_temp.end())
           it=first_temp.begin();
    }
    input.close();
}

void Follow(){
     input.open(filename);
     string temp;
     table.insert('$');
     while(getline(input,temp)){
           int l=5,len=temp.length();
           no_end.insert(temp[0]);
           while(l<len-1&&temp[l+1]!=' '){
                 if(!(temp[l]>='A'&&temp[l]<='Z')&&temp[l]!='e')
                     table.insert(temp[l]);
                 if(temp[l]>='A'&&temp[l]<='Z') {
                    follow[temp[l]].insert('$');
                    if(!(temp[l+1]>='A'&&temp[l+1]<='Z'))
                         follow[temp[l]].insert(temp[l+1]);
                    else{
                         int ok=1;
                         set<char>::iterator it=first[temp[l+1]].begin();
                         while(it!=first[temp[l+1]].end()){
                               if(*it!='e')
                               follow[temp[l]].insert(*it);
                               else ok=0;
                               it++;
                         if(!ok)
                            follow_temp[temp[l]].insert(temp[0]);
                        }
                    }

                }
            l++;
          }
          int k=0;
          while(temp[k+5]!='\0'&&temp[k+5]!='|')
                k++;
          if(temp[k+5]=='\0')
              string_temp[temp[0]].insert(temp.substr(5,k));
          else
              string_temp[temp[0]].insert(temp.substr(5,k-1));
          if(temp[k+5]=='|'){
             int y=0;
             while(temp[k+5+y]!='\0')
                   y++;
             string_temp[temp[0]].insert(temp.substr(k+7,y));
          }
          if(l<len&&temp[l]>='A'&&temp[l]<='Z')
             follow_temp[temp[l]].insert(temp[0]);
         while(l<len) {
              if(!(temp[l]>='A'&&temp[l]<='Z')&&temp[l]!=' '&&temp[l]!='|'&&temp[l]!='e')
                   table.insert(temp[l]);
              l++;
         }
     }
    map<char,set<char>>::iterator it=follow_temp.begin();
    while(follow_temp.size()!=0){
        set<char>::iterator ij=it->second.begin();
        while(ij!=it->second.end()){
             if(follow.find(*ij)!=follow.end()){
                set<char>::iterator ik=follow[*ij].begin();
                while(ik!=follow[*ij].end())
                      follow[it->first].insert(*ik),ik++;
                it->second.erase(ij++);
             }
             else
                ij++;
        }
        if(it->second.size()==0)
           follow_temp.erase(it++);
        else
           it++;
        if(it==follow_temp.end())
           it=follow_temp.begin();
    }
    input.close();
}


void show_first(){ //打印FIRST集合
     cout<<"FIRST集合为:"<<endl;
     map<char,set<char>>::iterator it=first.begin();
     while(it!=first.end()){
           cout<<"FIRST"<<"("<<it->first<<")"<<"={ ";
           set<char>::iterator ij=it->second.begin();
           int l=0,len=it->second.size();
           while(ij!=it->second.end()){
            cout<<*ij;ij++;
            if(l<=len-2)
               cout<<" , ";
            l++;
        }
        it++;
        cout<<" }"<<endl;
    }
}

void show_follow(){ //打印FOLLOW集合
     cout<<"FOLLOW集合为:"<<endl;
     map<char,set<char>>::iterator it=follow.begin();
     while(it!=follow.end()){
          cout<<"FOLLOW"<<"("<<it->first<<")"<<"={ ";
          set<char>::iterator ij=it->second.begin();
          int l=0,len=it->second.size();
          while(ij!=it->second.end()){
                cout<<*ij;ij++;
                if(l<=len-2)
                   cout<<" , ";
                l++;
          }
        it++;
        cout<<" }"<<endl;
    }
}

bool show_table(){  //打印并存储LL1分析表
    cout<<"LL1分析表为:"<<endl;
    cout<<"---------------------------------------------------"<<endl;
    cout<<"        ";
    set<char>::iterator it=table.begin();
    int k=0;
    while(it!=table.end()){
        ylab[*it]=k++;
        cout<<*it<<"         ";it++;
    }
    cout<<endl;
    it = no_end.begin();
    int l=0;
    while(it!=no_end.end()){
         cout<<*it<<"       ";
         set<char>::iterator ij=table.begin();
         int j=0;
         while(ij!=table.end()){
               set<string>::iterator ik=string_temp[*it].begin();
               int ok=0;
               while(ik!=string_temp[*it].end()){
                    string temp=*ik;
                    if(first[temp[0]].count(*ij)!=0||temp[0]==*ij){
                       if(s[l][j]!=" "){
                          cout<<endl;
                          cout<<"在第"<<l+1<<"行"<<"第"<<j+1<<"列处发生冲突:";
                          cout<<*it<<"->"<<temp<<" 与 "<<*it<<"->"<<s[l][j]<<endl;
                           return 0;
                       }
                       ok=1;cout<<*it<<"->"<<temp;
                       s[l][j]=temp;
                       for(int x=temp.length()+3;x<10;x++) cout<<" ";
                     }
                      if(first[temp[0]].count('e')!=0||(*ik)[0]=='e'){
                          if(follow[*it].count(*ij)!=0){
                             if(s[l][j]!=" "){
                                cout<<endl;
                                cout<<"在第"<<l+1<<"行"<<"第"<<j+1<<"列处发生冲突:";
                                cout<<*it<<"->"<<temp<<" 与 "<<*it<<"->"<<s[l][j]<<endl;
                                return 0;
                             }
                             ok=1;cout<<*it<<"->"<<temp;
                             s[l][j]=temp;
                             for(int x=temp.length()+3;x<10;x++)
                                 cout<<" ";
                          }
                    }
                    ik++;
                }
               if(!ok)
                  cout<<"          ",s[l][j]=" ";
               ij++;
               j++;
          }
         cout<<endl;
         xlab[*it]=l;
         it++;
         l++;
    }
    return 1;
}

bool juge(){  //识别字符串
     cout<<"请输入字符串:"<<endl;
     string temp;
     cin>>temp;
     cout<<"已匹配         ";
     cout<<"栈             ";
     cout<<"输入 ";
     cout<<"动作           "<<endl;
     string sta;
     sta+='E';
     string match;
     string action;
     string act1="输出 ";
     string act2="匹配 ";
     string action1;
     int l=0;
     while(sta.size()!=0){
            if(temp[0]=='e') temp.erase(0,1);
           cout<<match<<" ";
           cout<<setw(15-match.length())<<sta<<"$ ";
           cout<<setw(15)<<temp<<"$ ";
           if(temp[0]==sta[0]) {
              action=act2+temp[0];
              match=match+temp[0];
              temp.erase(0,1);
              sta.erase(0,1);
           }
           else if(temp.size()!=0&&(table.count(temp[0])==0||s[xlab[sta[0]]][ylab[temp[0]]]==" ")){
                   cout<<"error"<<endl;
                   return 0;
                 }
           else {
                if(temp.size()!=0){
                   string act=s[xlab[sta[0]]][ylab[temp[0]]];
                   action=act1+sta[0]+"->"+act;
                   sta.erase(0,1);
                if(act[act.length()-1]==' ')
                   act.erase(act.length()-1,1);
                if(act[0]!='e')
                   sta = act+sta;
                }
                else{
                    action=act1+sta[0]+"->"+'e';
                    sta.erase(0,1);
                }
           }
           cout<<action1<<endl;
           action1=action;
           l++;
     }
     cout<<match<<" ";
     cout<<setw(15-match.length())<<sta<<"$ ";
     cout<<setw(15)<<temp<<"$ ";
     if(sta.size()==0&&temp.size()!=0){
        cout<<"error"<<endl;
        return 0;
     }
     cout<<action1<<endl;
     return 1;
}
int main(){
    for(int x=0;x<10;x++)
        for(int y=0;y<10;y++)
           s[x][y]=" ";
    First(); //求first集合
    show_first(); //打印first集合
    Follow(); //求follow集合
    show_follow(); //打印follo集合
    if(!show_table()){
        cout<<"该文法不是LL(1)文法!!!"<<endl;
        return 0;
    }
    if(juge())
        cout<<"Accept!!!!"<<endl;
    else
       cout<<"error!!!!!!"<<endl;
}
阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 4
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
本程序的所用的存储结构都是string类型的,最主要的存储文法的数据结构为自定义结构,里面包括一个产生式的左部,右部以及select集合,至于非终结符的first和follow集合,则是定义了一个string类型的数组进行存储。 本程序的求first,follow,select集合的算法即为书上所介绍的方法,即求first的集合时,只看本产生式,求follow集合时,要进行递归查找一个非终结符的所有后跟字符,求select其实就是对first与follow集合的运算,最终根据所有的select集合,便可以判断此文法是否LL(1)文法。 对于不是LL(1)文法的产生式,本程序在判断后进行转换,先进行消除左递归,然后提取左公因子,在这两步的每一步结束之后,都要对产生式进行整合,去掉空存储,去掉无法到达的产生式,将select全部置空。 每进行一次非LL(1)到LL(1)的转换之后,都要对其文法性质进行判断,如果是LL(1),则跳出,不是则继续,但是当循环一定次数之后仍不是,程序判定其无法转换,也要跳出。 其中还有对第一个非终结字符的右部替换与否进行选择,原因是,有些通过替换就可以很方便的进行转换,这个要通过人为进行输入。 提取公因子中也有上一段所说的类似的判断机制,目的是为了防止文法的左公因子无法提取完的情况出现。 最终有三种结果,一种是是LL(1)文法,一种是不是LL(1),但是经过转换变成了LL(1),还有一种是经过转换也无法变成LL(1)。 输入文本格式样例: A A->ad A->Bc B->aA B->bB

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

计算机的小粽子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值