编译原理本科课程 专题4 算符优先语法分析设计原理与实现

一、程序功能描述

本程序由C/C++编写,实现了:算符优先文法、最左素短语、算符优先矩阵、优先函程序等概念的定义及实例。

以专题 1 词法分析程序的输出为语法分析的输入,实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程:

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

T→T*F∣T/F∣F

F→(E)∣i

二、主要数据结构描述

        关于具体的数据结构,主要使用了C语言的数组,其中字符数组运用最多,主要用于表示和存储Vn、Vt及FirstVt和LastVt的集合:

编译原理本科课程 专题4 算符优先语法分析设计原理与实现_第1张图片

        关于抽象的数据结构,则通过了一维数组实现了分析栈’stack’的数据结构,以用于算符优先的语法分析。此外,还用到了文件读写的相关数据结构及接口。

三、程序结构描述

        除main函数外,本程序共定义了11个函数:

        其中包含6个’find’函数,它们的功能相似,都是返回要查找字符在相应集合中的下标,否则返回-1;或者只是判断字符是否在First集或Last集中,无返回值,通过在数组中标记来维护算法。

        ‘add_to_VnVt’函数负责读取提供的文法规则,将其遍历,添加非终结符号和终结符号:

        ‘make_relation_table’函数负责构建算符优先关系矩阵。根据文法规则,判断终结符之间的关系,进而填充关系矩阵’Prior_rela’。下图的全局变量中,ll_cnt表示文法G[E]的条数,Prior_rela表示优先关系表,equation和alike用于装载从txt文件中读取到的字符串。

        LAUNCH函数意味着数据装载和预处理已经完成,程序正式启动。它会输出一些提示信息,而后输出算符优先语法分析的结果,包括非终结符号集、终结符号集、文法的FirstVt集和LastVt集、优先关系矩阵。

        analysis函数用于进行算符优先语法分析,通过算符优先关系表对输入的表达式进行分析,判断其是否符合文法规则。

四、程序测试

        测试案例展示如下:

        测试用例1:a*b*(c+d)-e+f/g

       编译原理本科课程 专题4 算符优先语法分析设计原理与实现_第2张图片

编译原理本科课程 专题4 算符优先语法分析设计原理与实现_第3张图片

#include
#include
#include
#include
 
using namespace std;
const int N = 500;
char Vn[N]; 
char Vt[N]; 
char First_Vt[N][N];
char Last_Vt[N][N]; 
char G_E[N][N] = {
  "E->E+T|E-T|T",
  "T->T*F|T/F|F",
  "F->(E)|i"
};

int ll_cnt = 3;
char Prior_rela[N][N];
char equation[N], alike[N];

int find_in_Vn(char c);               
int find_in_Vt(char c);               
int find_in_FirstVt(char c,int i);    
int find_in_LastVt(char c,int i);     
void find_in_FirstVt(char ll[N][N]);   
void find_in_LastVt(char ll[N][N]);    

void openFIle();
void make_relation_table(char LLL[N][N]);                      
void add_to_VnVt(char ll[N][N]);           
void LAUNCH();                     
void analysis();
 
void openFIle() {
  cout << "-------------------------------------------------------" << endl;
  cout << "文件内容为:" << endl;
  FILE* fp;
  char buf[1000];
  if ((fp = fopen("test1.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] == ',') {
              equation[strlen(equation)] = buf[j + 1];
              if ((buf[j + 1] >= 'a' && buf[j + 1] <= 'z') ||
                (buf[j + 1] >= 'A' && buf[j + 1] <= 'Z')) {
                alike[strlen(alike)] += 'i';
              }
              else alike[strlen(alike)] = buf[j + 1];
              i = j + 1;
              break;
            }
          }
        }
        else if (flag == 1 && buf[i] == ')') {
          flag = 0;
        }
      }
    }
  }
  equation[strlen(equation)] = '#';
  alike[strlen(alike)] = '#';
  fclose(fp);
  cout << "-------------------------------------------------------" << endl;
  cout << "输入的语句为:" << equation << endl;
  cout << "将其转化为:" << alike << endl;
  cout << "-------------------------------------------------------" << endl;
}
void add_to_VnVt(char ll[N][N]) {
  int Vn_index = 0;
  int Vt_index = 0;
  int temp = 0;
  int temp1 = 0;
  for (int i = 0; i < ll_cnt; i++) {
    Vn[Vn_index] = ll[i][0];
    Vn_index++;
  }
  for (int i = 0; i < ll_cnt; i++) {
    for (int j = 3; j < strlen(ll[i]); j++) {
      
      temp = 0;
      for (int k = 0; k < strlen(Vn); k++) {
        if (ll[i][j] == Vn[k] || ll[i][j] == '|' || ll[i][j] == 'N') {
          temp = 1;
          break;
        }
      }
      if (temp == 0) {
        temp1 = 0;
        for (int k = 0; k < strlen(Vt); k++) {
          
          if (ll[i][j] == Vt[k]) {
            temp1 = 1;
            break;
          }
        }
        if (temp1 == 0) {
          Vt[Vt_index] = ll[i][j];
          Vt_index++;
        }
      }
    }
  }
  Vt[strlen(Vt)] = '#';
}
int find_in_Vn(char c) {
  int location = -1;
  for (int i = 0; i < ll_cnt; i++) {
    if (c == Vn[i]) {
      location = i;
      break;
    }
  }
  return location;
}
int find_in_Vt(char c) {
  int location = -1;
  for (int i = 0; i < strlen(Vt); i++) {
    if (c == Vt[i]) {
      location = i;
      break;
    }
  }
  return location;
}
int find_in_FirstVt(char c, int i) {
  int temp = -1;
  for (int j = 0; j < strlen(First_Vt[i]); j++) {
    if (First_Vt[i][j] == c) {
      temp = j;
      break;
    }
  }
  return temp;
}
int find_in_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 LAUNCH() {
  cout << "*******************************************************" << endl;
  cout << "算符优先语法分析设计" << endl;
  cout << "非终结符号集(Vn)为:" << Vn << endl;
  cout << "终结符号集(Vt)为:" << Vt << endl;
  cout << "*******************************************************" << endl;
  cout << "文法当前的FristVt集为:" << endl;
  for (int i = 0; i < ll_cnt; i++) {
    cout <= 0; i--) {
      temp = 1;
      for (int j = 3; j < strlen(ll[i]); j++) {
        if (temp == 1) {
          if (find_in_Vn(ll[i][j]) != -1) {
            for (int k = 0; k < strlen(First_Vt[find_in_Vn(ll[i][j])]); k++) {
              if (find_in_FirstVt(First_Vt[find_in_Vn(ll[i][j])][k], i) == -1) {
                First_Vt[i][strlen(First_Vt[i])] = First_Vt[find_in_Vn(ll[i][j])][k];
                
              }
            }
          }
        }
        temp = 0;
        if (ll[i][j] == '|') {
          temp = 1;
        }
      }
    }
  }
}
void find_in_LastVt(char ll[N][N]) {
  for (int i = 0; i < ll_cnt; i++) {
    for (int j = 3; j < strlen(ll[i]); j++) {
      if (j==strlen(ll[i])-1 || ll[i][j+1]=='|') {
        if (find_in_Vt(ll[i][j]) != -1) {
          if (find_in_LastVt(ll[i][j], i) == -1) {
            Last_Vt[i][strlen(Last_Vt[i])] = ll[i][j];
          }
        }
        else {
          
          if (find_in_Vt(ll[i][j-1])!=-1) {
            
            if (find_in_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++) {
    
    for (int i = ll_cnt - 1; i >= 0; i--) {
      
      for (int j = 3; j < strlen(ll[i]); j++) {
        if (j == strlen(ll[i])-1 || ll[i][j + 1] == '|') {
          if (find_in_Vn(ll[i][j]) != -1) {
            for (int k = 0; k < strlen(Last_Vt[find_in_Vn(ll[i][j])]); k++) {
              if (find_in_LastVt(Last_Vt[find_in_Vn(ll[i][j])][k], i) == -1) {
                Last_Vt[i][strlen(Last_Vt[i])] = Last_Vt[find_in_Vn(ll[i][j])][k];
              }
            }
          }
        }
      }
    }
  }
}
void make_relation_table(char LLL[N][N]) {
  char ll[N][N];
  for (int i = 1; i < ll_cnt + 1; i++) {
    strcpy(ll[i], LLL[i - 1]);
  }
  strcpy(ll[0],"S->#E#");
  for (int i = 0; i < strlen(Vt); i++) {
    for (int j = 0; j < strlen(Vt); j++) {
      Prior_rela[i][j] = 'N';
    }
  }
  for (int i = 0; i < ll_cnt+1; i++) {
    for (int j = 3; j < strlen(ll[i]); j++) {
      if (find_in_Vn(ll[i][j]) == -1 && ll[i][j] != '|') {
        if (j < strlen(ll[i]) - 1) {
          if (find_in_Vn(ll[i][j + 1]) == -1 && ll[i][j] != '|') {
            Prior_rela[find_in_Vt(ll[i][j])][find_in_Vt(ll[i][j + 1])] = '=';
          }
        }
        if (j < strlen(ll[i]) - 2) {
          if (find_in_Vn(ll[i][j + 1]) != -1 && ll[i][j + 2] != '|' && find_in_Vn(ll[i][j + 2]) == -1) {
          Prior_rela[find_in_Vt(ll[i][j])][find_in_Vt(ll[i][j + 2])] = '=';
          }
        }
      }
      if (j < strlen(ll[i]) - 1) {
        if (find_in_Vn(ll[i][j]) == -1 && find_in_Vn(ll[i][j+1])!=-1 && ll[i][j]!='|') {
          for (int k = 0; k < strlen(First_Vt[find_in_Vn(ll[i][j + 1])]); k++) {
            Prior_rela[find_in_Vt(ll[i][j])][find_in_Vt(First_Vt[find_in_Vn(ll[i][j + 1])][k])] = '<';
          }
        }
        else if (find_in_Vn(ll[i][j]) != -1 && find_in_Vn(ll[i][j + 1]) == -1 && ll[i][j+1] != '|') {
          for (int k = 0; k < strlen(Last_Vt[find_in_Vn(ll[i][j])]); k++) {
            Prior_rela[find_in_Vt(Last_Vt[find_in_Vn(ll[i][j])][k])][find_in_Vt(ll[i][j+1])] = '>';
          }
        }
      }
    }
  }
}
void analysis() {
  cout << "    分析栈" << "           " << "语句" << endl;
  char a1, a2;
  int like_index = 0;
  char stack[N];
  char s[N];
  int j;
  char q;
  int lengh;
  int temp=1;
  stack[like_index] = '#';
  stack[1] = '\0';
  for (int i = 0; i < strlen(alike); i++) {
    temp = 1;
    if (find_in_Vn(stack[strlen(stack)-1]) == -1) {
      j = strlen(stack) - 1;
    }
    else j = strlen(stack) - 2;
    
    if (Prior_rela[find_in_Vt(stack[j])][find_in_Vt(alike[i])] == '=') {
      like_index = strlen(stack);
      stack[like_index]=alike[i];
      stack[like_index + 1] = '\0';
    }
    
    else if (Prior_rela[find_in_Vt(stack[j])][find_in_Vt(alike[i])] == '<') {
      like_index = strlen(stack);
      stack[like_index] = alike[i];
      stack[like_index + 1] = '\0';
    }
    else if (Prior_rela[find_in_Vt(stack[j])][find_in_Vt(alike[i])] == '>') {
      
      for (int y=0;;y++) {
        for (;;) {
          q = stack[j];
          lengh = j;
          if (j >= 1 && find_in_Vn(stack[j - 1]) == -1) {
            j--;
          }
          else if (j >= 2) {
            j = j - 2;
          }
          if (Prior_rela[find_in_Vt(stack[j])][find_in_Vt(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(alike); u++) {
            s[u - i] = alike[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] = alike[i];
        stack[like_index + 1] = '\0';
        for (int u = i; u < strlen(alike); u++) {
          s[u - i] = alike[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 (find_in_Vn(stack[strlen(stack) - 2]) == -1) {
          a2 = stack[strlen(stack) - 2];
        }
        else a2 = stack[strlen(stack) - 3];
        if (Prior_rela[find_in_Vt(a2)][find_in_Vt(a1)] == '<' || Prior_rela[find_in_Vt(a2)][find_in_Vt(a1)] == '=') {
          break;
        }
      }
    }
    else {
      cout << "分析出错!" << endl;
      break;
    }
    if (temp != 0) {
      for (int u = i; u < strlen(alike); u++) {
        s[u - i] = alike[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_to_VnVt(G_E);
  find_in_FirstVt(G_E);
  find_in_LastVt(G_E);
  make_relation_table(G_E);
  LAUNCH();
  openFIle();
  analysis();
  return 0;
}

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