• 大小: 461KB
    文件类型: .7z
    金币: 2
    下载: 1 次
    发布日期: 2021-07-18
  • 语言: C/C++
  • 标签: LR1  分析表  c++  

资源简介

LR1分析表生成程序 c++,注释完整。

资源截图

代码片段和文件信息

//0806580227 刘驰
//给定文法产生式构造LR(1)项目集和DFA并对输入的句子进行语法分析
//产生式存放在d:\syntax.txt
//句子存放在d:\test.txt
//项目集存放在d:\items_set
//DFA存放在d:\dfa.txt

#include“iostream“
#include“fstream“
#include“stack“
#include“utility“
using namespace std;

char G[20][20];     //存放文法,不超过20条产生式,每条产生式长度不超过20,用@表示空,以$结束
int  length[20];    //每条产生式的长度
int  number = 0; //产生式条数
bool tempofinput[150];  //记录文法中有哪些Vt和Vn,用ASCII码对应位标记true表示
char str_vn[20];        //存放所有Vn
int  size_vn = 0; //Vn个数
char str_vt[150];       //存放所有Vt
int  size_vt = 0; //Vt个数
bool first_vn[30][150]; //记录每个非终结符的FIRST集,用位示图法
char buffer[50];        //用来存放生成CLOSURE(I)时需要的FIRST集也用来读入用户的输入串^_^
int  bsize = 0;

struct thri{
    int beg; //起始状态号
    int nex; //下一状态号
    char ch; //接收的字符
}trans[200]; //用来在go()函数中记录状态间转换
int  size_trans = 0;
 
//定义项目集的形式
struct proj{
    int formula_numb; //产生式序号
    int part; //产生式中.的位置
    char expc; //希望接受的字符
}items[100][100];
int     Ccount = 0; //项目集个数
int     size_item[100]; //每个项目集中产生式的条数
 
//状态转换表
struct action{
    char    ch; //接受字符
    int     nxt_sta; //下一状态号
}action_table[100][100];//不超过100个状态集;从每个状态出发的状态转换不超过100条
int size_act_table[100];//每个项目集状态转换边数
 
ifstream  G_ifile; //文法输入文件流
ifstream  input_ifile; //表达式输入文件流
ofstream  items_ofile; //项目集输出文件流
ofstream  act_ofile; //状态转换表输出文件流
 
//读取产生式
void Read_G()
{
    G_ifile >> number;   //读取产生式条数
    for(int i = 1; i <= number; i++){
        char temp;
        int j = 0;
        G_ifile >> temp;
        while(temp != ‘$‘){ //循环读到每条产生式末尾$
            tempofinput[temp] = true; //tempofinput[150]中读入字符ASCII码对应值的位置记为true
            G[i][j++] = temp;
            G_ifile >> temp;
        }
        length[i] = j; //length[i]记录每条产生式长度
    }
   
    G[0][0] = ‘S‘;
    G[0][1] = G[1][0];
    length[0] = 2; //G[0]定义拓展文法S->E
   
    for(int i = 0; i < 64; i++)
        if(tempofinput[i])
           str_vt[size_vt++] = i; //标记Vt
    for(int i = 91; i < 128; i++)
        if(tempofinput[i])
           str_vt[size_vt++] = i; //标记Vt
    for(int i = 65; i < 91; i++)
        if(tempofinput[i])
           str_vn[size_vn++] = i; //标记Vn
}


//计算每一个Vn的FIRST:
//先设置 flag1表示本轮扫描 first_vn 中有没有新增加的内容。要是有,还要进行下一次扫描。
//每一轮扫描所有的产生式,在扫描每一个产生式的时候,设置一个下标指针 t 用来保证不会扫过本产生式.
//还设置 flag2 表示 t 的位置是否是一个可以推导出ε的非终结符。是的话,还要进行下一个 t 位置的检查。
//如果 t走到产生式的最后位置的下一个位置,则表明ε属于此产生式左边非终结符的FIRST 集合
void get_first(){
    bool flag1;
    do{
        flag1 = false;
        for(int i = 1; i <= number; i++){
           int t = 1; //每条产生式中的指针
           bool flag2;
           do{
               flag2 = false;
               if (G[i][t] >= ‘A‘ && G[i][t] <= ‘Z‘){ //t当前位置是一个非终结符
                      for(int k = 0; k < 64; k++)
  if(first_vn[G[i][t]-‘A‘][k]==true&& !first_vn[G[i][0]-‘A‘][k]){
 first_vn[G[i][0]-‘A‘][k] = true;
 flag1 = true;
  }
                      for(int k = 91; k < 128; k++)
  if(first_vn[G[i][t]-‘A‘][k]==true&& !

评论

共有 条评论