編譯原理之算術表達式文法的預測分析算法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<stdio.h>

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 ;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章