编译原理之算术表达式文法的预测分析算法c实现

    预测分析法是一种确定的自顶向下的分析方法,一个文法能否用预测分析法进行分析,关键看其是否为LL(1)文法,一个预测分析器由三个部分组成:

    #预测分析程序

    #先进后出栈

    #预测分析表

下面我们以一个具体的实例来看预测分析器的实现算法,其他文法可照推:

已知表达式文法:(只含*、+、)、(、i算术表达式的判断文法)

       E->E+T|T

       T->T*F|F

       F->i|(E)

设计预测分析程序。

由于文法中含有左递归,所以必须先消除左递归,消除后为:

      E->TE'

      E'->+TE'|e

      T->FT'

      T'->*FT'|e

      F->i|(E)

**说明:e代表空串**

进一步可得如下预测分析表:

 

i

+

*

(

)

#

E

TE’

 

 

TE’

 

 

E’

 

+TE’

 

 

e

e

T

FT’

 

 

FT’

 

 

T’

 

e

*FT’

 

e

e

F

i

 

 

(E)

 

 

预测分析程序如下:

/*构造表达式文法的预测分析器

将表达式各字符编码,再进行表达式文法的预测分析 */

#include

typedef int Mat[5][6][3];//定义三维数组Mat,用于存储编码后的表达式文法的预测分析表

void ForecastAnalysisDevice(char *expressions,Mat forecasttable);//表达式文法的预测分析器

int main(){

      Mat forecasttable = {2,1,9,9,9,9,9,9,9,2,1,9,9,9,9,9,9,9, 

                                         9,9,9,22,2,1,9,9,9,9,9,9,8,9,9,8,9,9,

                                         4,3,9,9,9,9,9,9,9,4,3,9,9,9,9,9,9,9,

                                         9,9,9,8,9,9,33,4,3,9,9,9,8,9,9,8,9,9,

                                         11,9,9,9,9,9,9,9,9,44,0,55,9,9,9,9,9,9};

      //编码表:0=E,1=E',2=T,3=T',4=F,11=i,22=+,33=*,44=(,55=),66=#,8=空串,9=栈顶空

      char expressions[100]; //表达式

      printf("###################################\n");

      printf("请输入算术表达式...\nExpressions= ");

      scanf("%s",expressions);

      printf("-\n");

      ForecastAnalysisDevice(expressions,forecasttable); //进行表达式文法的预测分析

      printf("-----------------------------------\n");

      printf("###################################\n");

      return 0;

}

void ForecastAnalysisDevice(char *expressions,Mat forecasttable){

      //表达式文法的预测分析器,expressions为表达式,forecasttable为表达式文法的预测分析表

      char string[5] = {'i','+','*','(',')'}; //表达式字符集

      int i = 0,j = 0,k,l;

      int indexx,indexy,semp,sum;

      int integer[100];

      while(expressions[i] != '\0'){ //对表达式进行归一化编码转换

             switch (expressions[i]){

             case 105:integer[j++] = 0;break;

             case 43:integer[j++] = 1;break;

             case 42:integer[j++] = 2;break;

             case 40:integer[j++] = 3;break;

             case 41:integer[j++] = 4;break;

             case 35:integer[j++] = 5;break;

             }

             i++;

      }

      integer[i++] = 5;

      sum = i;

      j = 0;

      int temp[12] = {9,9,9,9,9,9,9,9,9,9,9,0};//初始化预测分析栈

      while(temp[11] != 9){

             for(i = 0;i < 12;i++){ //找到栈顶

                    if(temp[i] != 9)

                           break;

             }

             if(temp[i] == 55){ //)”匹配

                    printf("\")\"匹配\n");

                    temp[i] = 9;

                    i = i+1;

                    j = j+1;

             }

             indexx = temp[i]; //预测分析表x下标,即第一纬下标

             indexy = integer[j]; //预测分析表y下标,即第二纬下标

             if(forecasttable[indexx][indexy][0] != 11 && forecasttable[indexx][indexy][0] != 22 && forecasttable[indexx][indexy][0] != 33 && forecasttable[indexx][indexy][0] != 44 && forecasttable[indexx][indexy][0] != 55 && forecasttable[indexx][indexy][0] != 66 && forecasttable[indexx][indexy][0] != 9 && forecasttable[indexx][indexy][0] != 8){

                    //产生式推导仍为非终结符

                    k = 2;

                   l = i;

                    while(k >= 0){

                           if(forecasttable[indexx][indexy][k] != 9){

                                  if(forecasttable[indexx][indexy][k] > 9){ //大编码变形,转化为预测分析表列下标

                                         semp = forecasttable[indexx][indexy][k]/10;

                                         semp *= 10+1;

                                         temp[l] = forecasttable[indexx][indexy][k] - semp;

                                         l--;

                                  }else{

                                         temp[l] = forecasttable[indexx][indexy][k];

                                         l--;

                                  }

                           }

                           k--;

                    }

             }

             else if(forecasttable[indexx][indexy][0] == 9){ //出错处理

                    printf("...\n分析意外终止...\n输入的串\"%s\"不可接受!\n",expressions);

                    return ;

             }

             else if(forecasttable[indexx][indexy][0] == 8) //产生式推导为空

                    temp[i] = 9;

             else{ //产生式推导出终结符

                    k = 2;

                    l = i;

                    while(k >= 0){

                           if(forecasttable[indexx][indexy][k] != 9){

                                  temp[l] = forecasttable[indexx][indexy][k];

                                  l--;

                           }

                          k--;

                    }

                    l++;

                    temp[l] -= (temp[l]/10)*10;

                    printf("\"%c\"匹配\n",string[temp[l]-1]); //打印匹配字符

                    temp[l] = 9;

                    if(j < sum-1) //避免表达式遍历越界

                           j++;

             }

      }

      printf("---------\n");

      printf("Congratulation!\n输入的串\"%s\"可接受!\n",expressions);//表达式满足给定文法规则

      return ;

}

 

你可能感兴趣的:(算法,编译原理)