算符优先语法分析设计原理与实现

本文详细介绍了如何设计和实现一个算符优先文法分析器,包括构造算符优先关系矩阵、计算FristVT和LastVT集合,以及进行算术表达式的分析。实验要求包含输入串的判断和错误检测,同时提供了词法分析的输入和输出示例。
摘要由CSDN通过智能技术生成

一、实验目的

语法分析的设计方法和实现原理,算符优先文法、最左素短语、算符优先矩阵、优先函 数的基本概念;算符优先文法句型最左素短语的确定;算符优先分析算法的实现;

二、实验内容

[实验项目] 实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。

G[E]:E→E+T∣E-T∣T

T→T*F∣T/F∣F

F→(E)∣i

[设计说明] 终结符号 i 为用户定义的简单变量,即标识符的定义。

[设计要求]

(1)构造该算符优先文法的优先关系矩阵或优先函数;

(2)输入串应是词法 分析的输出二元式序列,即某算术表达式“专题 1”的输出结果。输出为输入串是否为该文 法定义的算术表达式的判断结果。

(3)算符优先分析过程应能发现输入串出错。

(4)设计两 个测试用例(尽可能完备,正确和出错),并给出测试结果;

(5)考虑根据算符优先文法构 造算符优先关系矩阵,包括 FIRSTVT 和 LASTVT 集合,并添加到你的算符优先分析程序中。 3. 任务分析 重点解决算符优先矩阵的构造方法和算符优先算法的实现。

词法分析输入:

词法分析输出:

算符优先文法分析结果:

对词法分析输出的分析:

由输入可知,该语句正常,分析结果正确。

#define  _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<stack>

using namespace std;
char H[200]; //记录非终结符合
char L[200]; //记录终结符号
int num_ll = 3;//记录文法条数
char G_E[100][100] = {
  "E->E+T|E-T|T",
  "T->T*F|T/F|F",
  "F->(E)|i"
};//文法数组
char frist_vt[100][100];//记录fristvt集内容
char last_vt[100][100];//记录lastvt集内容
char relation_table[100][100];//优先关系表
char shizi[500], like[500];//从文件中读取字符串

void openthefile();//打开并读取词法分析文件
int location_H(char c);//判断当前字符是否属于非终结符号
int location_L(char c);//判断当前字符是否属于终结符号
void add_HL(char ll[100][100]);//添加非终结符号与终结符号
void print_result();//输出结果
int check_the_fristvt(char c,int i);//检查Fristvt集中是否有该元素
int check_the_lastvt(char c,int i);//检查Lastvt集中是否有该元素
void find_the_frist(char ll[100][100]);//添加Fristvt集
void find_the_last(char ll[100][100]);//添加Lastvt集
void analysis();//算法优先文法分析函数

void openthefile() {
  cout << "-------------------------------------------------------" << endl;
  cout << "读取文件可知输入语句:" << endl;
  FILE* fp;
  char buf[1000];
  if ((fp = fopen("E:\\desktop\\result.txt", "r")) != NULL) {
    while (fgets(buf, 1000, fp) != NULL)
    {
      int len = strlen(buf);
      printf("%s \n", buf);
      int flag = 0;

      for (int i = 0; i < len; i++) {
        if (buf[i] == '(' && flag == 0) {
          flag = 1;//识别符号
          for (int j = i + 1; j < len; j++) {
            if (buf[j] == ',') {
              shizi[strlen(shizi)] = buf[j + 1];
              if ((buf[j + 1] >= 'a' && buf[j + 1] <= 'z') ||
                (buf[j + 1] >= 'A' && buf[j + 1] <= 'Z')) {
                like[strlen(like)] += 'i';
              }
              else like[strlen(like)] = buf[j + 1];
              i = j + 1;
              break;
            }
          }
        }
        else if (flag == 1 && buf[i] == ')') {
          flag = 0;
        }
      }
    }
  }
  shizi[strlen(shizi)] = '#';
  like[strlen(like)] = '#';
  fclose(fp);
  cout << "-------------------------------------------------------" << endl;
  cout << "输入的语句为:" << shizi << endl;
  cout << "将其转化为:" << like << endl;
  cout << "-------------------------------------------------------" << endl;
}
void add_HL(char ll[100][100]) {
  int H_index = 0;
  int L_index = 0;
  int temp = 0;
  int temp1 = 0;
  for (int i = 0; i < num_ll; i++) {//添加非终结符号
    H[H_index] = ll[i][0];
    H_index++;
  }
  for (int i = 0; i < num_ll; i++) {
    for (int j = 3; j < strlen(ll[i]); j++) {
      //由于文法开始前三个字符必定不为终结符号,所以从三号索引开始
      temp = 0;
      for (int k = 0; k < strlen(H); k++) {
        if (ll[i][j] == H[k] || ll[i][j] == '|' || ll[i][j] == 'N') {
          temp = 1;
          break;
        }
      }
      if (temp == 0) {
        temp1 = 0;
        for (int k = 0; k < strlen(L); k++) {
          //判断该非终结符号是否已经存在
          if (ll[i][j] == L[k]) {
            temp1 = 1;
            break;
          }
        }
        if (temp1 == 0) {
          L[L_index] = ll[i][j];//添加终结符号
          L_index++;
        }
      }
    }
  }
  L[strlen(L)] = '#';
}
int location_H(char c) {
  int location = -1;
  for (int i = 0; i < num_ll; i++) {
    if (c == H[i]) {
      location = i;
      break;
    }
  }
  return location;
}
int location_L(char c) {
  int location = -1;
  for (int i = 0; i < strlen(L); i++) {
    if (c == L[i]) {
      location = i;
      break;
    }
  }
  return location;
}
int check_the_fristvt(char c, int i) {
  int temp = -1;
  for (int j = 0; j < strlen(frist_vt[i]); j++) {
    if (frist_vt[i][j] == c) {
      temp = j;
      break;
    }
  }
  return temp;
}
int check_the_lastvt(char c, int i) {
  int temp = -1;
  for (int j = 0; j < strlen(last_vt[i]); j++) {
    if (last_vt[i][j] == c) {
      temp = j;
      break;
    }
  }
  return temp;
}
void print_result() {
  cout << "------------------20231048 马云霄----------------------" << endl;
  cout << "该文法的非终结符号集为:" << H << endl;
  cout << "该文法的终结符号集为:" << L << endl;
  cout << "-------------------------------------------------------" << endl;
  cout << "当前文法的Fristvt集为:" << endl;
  for (int i = 0; i < num_ll; i++) {
    cout <<H[i]<<": "<< frist_vt[i] << endl;
  }
  cout << "当前文法的Lastvt集为:" << endl;
  for (int i = 0; i < num_ll; i++) {
    cout << H[i] << ": " << last_vt[i] << endl;
  }
  cout << "-------------------------------------------------------" << endl;
  cout << "当前优先关系矩阵为:" << endl;
  cout << " ";
  for (int i = 0; i < strlen(L); i++) {
    cout << "  " << L[i];
  }
  cout << endl;
  for (int i = 0; i < strlen(L); i++) {
    cout << L[i];
    for (int j = 0; j < strlen(L); j++) {
      cout << "  " << relation_table[i][j];
    }
    cout << endl;
  }
}
void find_the_frist(char ll[100][100]) {
  int temp;
  for (int i = 0; i < num_ll; i++) {
    temp = 1;
    for (int j = 3; j < strlen(ll[i]); j++) {
      if (temp == 1) {
        if (location_L(ll[i][j]) != -1) {
          //当前文法的第一个字符为终结符号
          if (check_the_fristvt(ll[i][j], i) == -1) {
            //如果该fristvt集没有该符号
            frist_vt[i][strlen(frist_vt[i])] = ll[i][j];
            //添加该非终结符号到Fristvt集
          }
        }
        else {
          //当前文法的第一个符号不是终结符号
          if (j != strlen(ll[i]) - 1 && ll[i][j + 1] != '|') {
            //如果当前文法还没结束且不是单产生式子
            if (check_the_fristvt(ll[i][j + 1], i) == -1) {
              frist_vt[i][strlen(frist_vt[i])] = ll[i][j + 1];
            }
          }
        }
      }
      temp = 0;
      if (ll[i][j] == '|') {
        temp = 1;//frist集只判断或符号的后面的句子即可
      }
    }
  }
  
  for (int w = 0; w < 2; w++) {
    //为保证这里获取的Fristvt集完全,该部分遍历两遍程序
    for (int i = num_ll - 1; i >= 0; i--) {
      //反向遍历按照第二条规则添加fristvt集
      temp = 1;
      for (int j = 3; j < strlen(ll[i]); j++) {
        if (temp == 1) {
          if (location_H(ll[i][j]) != -1) {
            //文法当前符号为非终结符号
            for (int k = 0; k < strlen(frist_vt[location_H(ll[i][j])]); k++) {
              if (check_the_fristvt(frist_vt[location_H(ll[i][j])][k], i) == -1) {
                //如果该fristvt集没有该符号
                frist_vt[i][strlen(frist_vt[i])] = frist_vt[location_H(ll[i][j])][k];
                //添加该非终结符号到Fristvt集
              }
            }
          }
        }
        temp = 0;
        if (ll[i][j] == '|') {
          temp = 1;
        }
      }
    }
  }
}
void find_the_last(char ll[100][100]) {
  for (int i = 0; i < num_ll; i++) {
    for (int j = 3; j < strlen(ll[i]); j++) {
      if (j==strlen(ll[i])-1 || ll[i][j+1]=='|') {
        if (location_L(ll[i][j]) != -1) {
          //当前文法的字符为终结符号
          if (check_the_lastvt(ll[i][j], i) == -1) {
            //如果该lastvt集没有该符号
            last_vt[i][strlen(last_vt[i])] = ll[i][j];
            //添加该非终结符号到lastvt集
          }
        }
        else {
          //当前文法的符号不是终结符号
          if (location_L(ll[i][j-1])!=-1) {
            //该非终结符号前面是终结符号
            if (check_the_lastvt(ll[i][j-1], i) == -1) {
              last_vt[i][strlen(last_vt[i])] = ll[i][j - 1];
            }
          }
        }
      }
    }
  }
  for (int w = 0; w < 2; w++) {
    //为保证这里获取的Fristvt集完全,该部分遍历两遍程序
    for (int i = num_ll - 1; i >= 0; i--) {
      //反向遍历按照第二条规则添加fristvt集
      for (int j = 3; j < strlen(ll[i]); j++) {
        if (j == strlen(ll[i])-1 || ll[i][j + 1] == '|') {
          if (location_H(ll[i][j]) != -1) {
            //文法当前符号为非终结符号
            for (int k = 0; k < strlen(last_vt[location_H(ll[i][j])]); k++) {
              if (check_the_lastvt(last_vt[location_H(ll[i][j])][k], i) == -1) {
                //如果该fristvt集没有该符号
                last_vt[i][strlen(last_vt[i])] = last_vt[location_H(ll[i][j])][k];
                //添加该非终结符号到Fristvt集
              }
            }
          }
        }
      }
    }
  }
}
void make_relation_table(char ll_1[100][100]) {
  char ll[100][100];
  //为该文法添加开始符号与结束符号
  for (int i = 1; i < num_ll + 1; i++) {
    strcpy(ll[i], ll_1[i - 1]);
  }
  strcpy(ll[0],"S->#E#");
  //优先关系矩阵的初始化
  for (int i = 0; i < strlen(L); i++) {
    for (int j = 0; j < strlen(L); j++) {
      relation_table[i][j] = 'N';
    }
  }
  for (int i = 0; i < num_ll+1; i++) {
    for (int j = 3; j < strlen(ll[i]); j++) {
      //添加等于关系
      if (location_H(ll[i][j]) == -1 && ll[i][j] != '|') {
        //该符号为终结符号
        if (j < strlen(ll[i]) - 1) {
          if (location_H(ll[i][j + 1]) == -1 && ll[i][j] != '|') {
            //如果两个终结符号相连,优先关系相等
            relation_table[location_L(ll[i][j])][location_L(ll[i][j + 1])] = '=';
          }
        }
        if (j < strlen(ll[i]) - 2) {
          if (location_H(ll[i][j + 1]) != -1 && ll[i][j + 2] != '|' && location_H(ll[i][j + 2]) == -1) {
          //如果两个终结符号中间有一个非终结符,优先关系相等
          relation_table[location_L(ll[i][j])][location_L(ll[i][j + 2])] = '=';
          }
        }
      }
      if (j < strlen(ll[i]) - 1) {
        //添加低于优先关系
        if (location_H(ll[i][j]) == -1 && location_H(ll[i][j+1])!=-1 && ll[i][j]!='|') {
          //当前字符为终结符号且后面跟着非终结符号
          for (int k = 0; k < strlen(frist_vt[location_H(ll[i][j + 1])]); k++) {
            relation_table[location_L(ll[i][j])][location_L(frist_vt[location_H(ll[i][j + 1])][k])] = '<';
          }
        }
        //添加高于优先关系
        else if (location_H(ll[i][j]) != -1 && location_H(ll[i][j + 1]) == -1 && ll[i][j+1] != '|') {
          //当前字符为非终结符且后面跟着终结符
          for (int k = 0; k < strlen(last_vt[location_H(ll[i][j])]); k++) {
            relation_table[location_L(last_vt[location_H(ll[i][j])][k])][location_L(ll[i][j+1])] = '>';
          }
        }
      }
    }
  }
}
void analysis() {
  cout << "    分析栈" << "           " << "语句" << endl;
  char a1, a2;
  int like_index = 0;
  char stack[100];//分析栈
  char s[100];//输入语句
  int j;
  char q;
  int lengh;
  int temp=1;
  stack[like_index] = '#';
  stack[1] = '\0';
  for (int i = 0; i < strlen(like); i++) {
    temp = 1;
    if (location_H(stack[strlen(stack)-1]) == -1) {
      j = strlen(stack) - 1;
    }
    else j = strlen(stack) - 2;
    //当前关系为等于,入栈
    if (relation_table[location_L(stack[j])][location_L(like[i])] == '=') {
      like_index = strlen(stack);
      stack[like_index]=like[i];
      stack[like_index + 1] = '\0';
    }
    //低于关系也入栈
    else if (relation_table[location_L(stack[j])][location_L(like[i])] == '<') {
      like_index = strlen(stack);
      stack[like_index] = like[i];
      stack[like_index + 1] = '\0';
    }
    else if (relation_table[location_L(stack[j])][location_L(like[i])] == '>') {
      //寻找句柄进行归约
      for (int y=0;;y++) {
        for (;;) {
          q = stack[j];
          lengh = j;
          if (j >= 1 && location_H(stack[j - 1]) == -1) {
            j--;
          }
          else if (j >= 2) {
            j = j - 2;
          }
          if (relation_table[location_L(stack[j])][location_L(q)] == '<') {
            break;
          }
        }
        stack[j + 1] = '\0';
        like_index = strlen(stack);
        stack[like_index] = 'E';
        stack[like_index + 1] = '\0';
        if (y == 0) {
          for (int u = i; u < strlen(like); u++) {
            s[u - i] = like[u];
            lengh = u - i+1;
          }
          s[lengh] = '\0';
          cout.width(10);
          cout.unsetf(ios::left);
          cout.fill(' ');
          cout << stack;
          cout << "         " << s << endl;
        }
        like_index = strlen(stack);
        stack[like_index] = like[i];
        stack[like_index + 1] = '\0';
        for (int u = i; u < strlen(like); u++) {
          s[u - i] = like[u];
          lengh = u - i + 1;
        }
        cout.width(10);
        cout.unsetf(ios::left);
        cout.fill(' ');
        s[lengh] = '\0';
        cout << stack;
        cout << "         " << s << endl;
        temp = 0;
        if (strlen(stack) <= 2) { break; }
        a1 = stack[strlen(stack) - 1];
        if (location_H(stack[strlen(stack) - 2]) == -1) {
          a2 = stack[strlen(stack) - 2];
        }
        else a2 = stack[strlen(stack) - 3];
        if (relation_table[location_L(a2)][location_L(a1)] == '<' || relation_table[location_L(a2)][location_L(a1)] == '=') {
          break;
        }
      }
    }
    else {
      cout << "分析出错!" << endl;
      break;
    }
    if (temp != 0) {
      for (int u = i; u < strlen(like); u++) {
        s[u - i] = like[u];
        lengh = u - i + 1;
      }
      s[lengh] = '\0';
      cout.width(10);
      cout.unsetf(ios::left);
      cout.fill(' ');
      cout << stack;
      cout<< "         " << s << endl;
    }
  }
  if (strcmp(stack, "#E#") == 0) {
    cout << "分析成功!" << endl;
  }
}
int main(void) {
  add_HL(G_E);//添加终结符号与非终结符号
  find_the_frist(G_E);//寻找Fristvt集
  find_the_last(G_E);//寻找Lastvt集
  make_relation_table(G_E);//构建优先关系表格
  print_result();//输出结果 
  openthefile();//读取词法分析输出文法
  //strcpy(like, "(i+i)*i#");
  analysis();//进行算符优先文法分析
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值