zoukankan      html  css  js  c++  java
  • 软件构造——实验五 算符优先分析法

    【实验目的】 

    掌握算符优先分析法的原理,利用算符优先分析法将赋值语句进行语法分析。 

    【实验内容】 

    (1)输入一个文法根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否为算符优先文法

     (2)输入一个句子进行分析

    【实验要求】 

    1、根据文法求FIRSTVT集和LASTVT集

    给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的FirstVT 集和LastVT 集。

    可参考算法描述如下:

    /*求 FirstVT 集的算法*/

    PROCEDURE insert(P,a);

    IF not F[P,a] then  

    begin 

            F[P,a] = true; //(P,a)进栈 

    end; 

    Procedure FirstVT;

    Begin

    for 对每个非终结符 P和终结符 a do

       F[P,a] = false

    for 对每个形如 P    a…或 P→Qa…的产生式 do

    Insert(P,a)

    while stack  非空

    begin

    栈顶项出栈,记为(Q,a)

    for  对每条形如 P→Q…的产生式 do

             insert(P,a)

    end;

    end.

    同理,可构造计算LASTVT的算法。

    2、构造算符优先分析表

    依据文法和求出的相应FirstVT和 LastVT 集生成算符优先分析表。

    参考算法描述如下:

    for  每个形如 P->X1X2…Xn的产生式  do

      for i =1 to n-1 do

      begin

            if Xi和Xi+1都是终结符 then 

               Xi   =   Xi+1

            if i<= n-2, Xi和Xi+2 是终结符, 但Xi+1 为非终结符 then

               Xi  = Xi+2

            if Xi为终结符, Xi+1为非终结符 then  

                 for FirstVT 中的每个元素 a do

                      Xi  <  a ;

            if Xi为非终结符, Xi+1为终结符 then

                 for LastVT 中的每个元素 a do

                      a  >  Xi+1 ;

      end

    3、构造控制程序

      参考 算法描述如下:

       stack S;

       k = 1;  //符号栈S的使用深度

       S[k] = ‘#’

       REPEAT

           把下一个输入符号读进a中;

           If S[k]  VT   then  j = k  else  j = k-1;

           While S[j] > a  do

               Begin

               Repeat

                   Q = S[j];

                   if  S[j-1]  VT  then  j = j-1  else   j = j-2

               until  S[j] < Q;

               把S[j+1]…S[k]归约为某个N,并输出归约为哪个符号;

               K = j+1;

               S[k] = N;

               end of while

           if S[j] < a  or  S[j] = a  then

               begin  k = k+1; S[k] = a      end

            else  error //调用出错诊察程序

        until a = ‘#’

    4、对给定的表达式,给出准确与否的分析过程

    5、给出表达式的计算结果。

    【实验结果】 

    图为参考,要求包含firstvt和lastvt集,算符优先表或优先函数表及句子分析过程。

    实验截图:

    代码:

      1 Mian.cpp:
      2 #include <stdio.h>
      3 #include <math.h>
      4 #include <string.h>
      5 #include <stdlib.h>
      6 #include <iostream>
      7 #include <sstream>
      8 #include <algorithm>
      9 #include <set>
     10 #include <queue>
     11 #include <stack>
     12 #include <map>
     13 #include <bitset>
     14 #pragma comment(linker, "/STACK:102400000,102400000")
     15 typedef long long LL;
     16 const int inf = 0x3f3f3f3f;
     17 const double pi = acos(-1.0);
     18 const double esp = 1e-6;
     19 using namespace std;
     20 
     21 const int Maxn = 110;
     22 const int maxn = 20;
     23 char str[maxn][Maxn];//输入文法
     24 char st[maxn];//输入串
     25 char stac[maxn];//模拟栈的数组
     26 char nstr[maxn][maxn];//储存转化文法
     27 char mstr[maxn][maxn];
     28 char fin[maxn];//存储终结符
     29 char firstvt[maxn][maxn], lastvt[maxn][maxn];
     30 char cmp[maxn][maxn];//存储表中的比较符
     31 int firstflag[maxn], lastflag[maxn];//非终结符的firstvt,lastvt是否求出
     32 int fcnt[maxn], lcnt[maxn];//非终结符firsvt和lastvt的个数
     33 int is_fin(char c) { //判断终结符
     34     for (int i = 0; fin[i] != ''; i++) {
     35         if (fin[i] == c)
     36             return 1;
     37     }
     38     return 0;
     39 }
     40 int site(char c) { //求在表中的下标
     41     for (int i = 0; fin[i] != ''; i++) {
     42         if (fin[i] == c)
     43             return i;
     44     }
     45 }
     46 
     47 void get_firstvt(char s, int t) { //求s非终结符的firstvt值
     48     int i, j, ii, jj, tt;
     49     for (i = 0; i<t; i++) {
     50         if (str[i][0] == s)
     51             break;
     52     }
     53     if (!firstflag[i]) {
     54         int k = fcnt[i];
     55         for (j = 0; str[i][j] != ''; j++) {
     56             if (j == 2 || str[i][j] == '|') {
     57                 if (is_fin(str[i][j + 1])) {
     58                     firstvt[i][k++] = str[i][j + 1];
     59                 }
     60                 else {
     61                     if (is_fin(str[i][j + 2])) {
     62                         firstvt[i][k++] = str[i][j + 2];
     63                     }
     64                     if (str[i][j + 1] != s) {
     65                         get_firstvt(str[i][j + 1], t);
     66                         for (ii = 0; ii<t; ii++) {
     67                             if (str[ii][0] == str[i][j + 1])
     68                                 break;
     69                         }
     70                         for (jj = 0; jj<fcnt[ii]; jj++) {
     71                             for (tt = 0; tt<k; tt++) {
     72                                 if (firstvt[i][tt] == firstvt[ii][jj])
     73                                     break;
     74                             }
     75                             if (tt == k) {
     76                                 firstvt[i][k++] = firstvt[ii][jj];
     77                             }
     78                         }
     79                     }
     80                 }
     81             }
     82         }
     83         firstvt[i][k] = '';
     84         fcnt[i] = k;
     85         firstflag[i] = 1;
     86     }
     87 }
     88 
     89 void output_firstvt(int T) { //输出firstvt集
     90     for (int i = 0; i<T; i++) {
     91         get_firstvt(str[i][0], T);
     92     }
     93     for (int i = 0; i<T; i++) {
     94         printf("Firstvt[%c]:", str[i][0]);
     95         for (int j = 0; j<fcnt[i]; j++) {
     96             printf("%c ", firstvt[i][j]);
     97         }
     98         puts("");
     99     }
    100 }
    101 
    102 void get_lastvt(char s, int t) { //求s非终结符的lastvt值
    103     int i, j, ii, jj, tt;
    104     for (i = 0; i<t; i++) {
    105         if (str[i][0] == s)
    106             break;
    107     }
    108     if (!lastflag[i]) {
    109         int k = lcnt[i];
    110         for (j = 0; str[i][j] != ''; j++) {
    111             if (str[i][j + 1] == '|' || str[i][j + 1] == '') {
    112                 if (is_fin(str[i][j])) {
    113                     lastvt[i][k++] = str[i][j];
    114                 }
    115                 else {
    116                     if (is_fin(str[i][j - 1])) {
    117                         lastvt[i][k++] = str[i][j - 1];
    118                     }
    119                     if (str[i][j] != s) {
    120                         get_lastvt(str[i][j], t);
    121                         for (ii = 0; ii<t; ii++) {
    122                             if (str[ii][0] == str[i][j])
    123                                 break;
    124                         }
    125                         for (jj = 0; jj<lcnt[ii]; jj++) {
    126                             for (tt = 0; tt<k; tt++) {
    127                                 if (lastvt[i][tt] == lastvt[ii][jj])
    128                                     break;
    129                             }
    130                             if (tt == k) {
    131                                 lastvt[i][k++] = lastvt[ii][jj];
    132                             }
    133                         }
    134                     }
    135                 }
    136             }
    137         }
    138         lastvt[i][k] = '';
    139         lcnt[i] = k;
    140         lastflag[i] = 1;
    141     }
    142 }
    143 
    144 void output_lastvt(int T) { //输出lastvt集
    145     for (int i = 0; i<T; i++) {
    146         get_lastvt(str[i][0], T);
    147     }
    148     for (int i = 0; i<T; i++) {
    149         printf("Lastvt[%c]:", str[i][0]);
    150         for (int j = 0; j<lcnt[i]; j++) {
    151             printf("%c ", lastvt[i][j]);
    152         }
    153         puts("");
    154     }
    155 }
    156 
    157 void get_table(int T, int cnt) { //得到表
    158     int x = 0, y = 0;
    159     int i, j, ii, jj;
    160     for (i = 0; i<T; i++) {
    161         for (j = 0; str[i][j] != ''; j++) {
    162             if (str[i][j] != '|')
    163                 nstr[x][y++] = str[i][j];
    164             else if (str[i][j] == '|') {
    165                 nstr[x][y] = '';
    166                 x++;
    167                 y = 0;
    168                 nstr[x][y++] = str[i][0];
    169                 nstr[x][y++] = '-';
    170                 nstr[x][y++] = '>';
    171             }
    172         }
    173         nstr[x][y] = '';
    174         x++;
    175         y = 0;
    176     }
    177     //对于S1->#S#;
    178     char a = '#';
    179     cmp[site(a)][site(a)] = '=';
    180     for (i = 0; i<fcnt[0]; i++) {
    181         cmp[site(a)][site(firstvt[0][i])] = '<';
    182     }
    183     for (i = 0; i<lcnt[0]; i++) {
    184         cmp[site(lastvt[0][i])][site(a)] = '>';
    185     }
    186     //对于初始的文法
    187     for (i = 0; i<x; i++) {
    188         for (j = 3; nstr[i][j + 1] != ''; j++) {
    189             if (is_fin(nstr[i][j]) && is_fin(nstr[i][j + 1]))
    190                 cmp[site(nstr[i][j])][site(nstr[i][j + 1])] = '=';
    191             if (is_fin(nstr[i][j]) && !is_fin(nstr[i][j + 1]) && is_fin(nstr[i][j + 2]) && nstr[i][j + 2] != '')
    192                 cmp[site(nstr[i][j])][site(nstr[i][j + 2])] = '=';
    193             if (!is_fin(nstr[i][j]) && is_fin(nstr[i][j + 1])) { //对于非终结符在终结符之前
    194                 for (ii = 0; ii<T; ii++) {
    195                     if (str[ii][0] == nstr[i][j])
    196                         break;
    197                 }
    198                 for (jj = 0; jj<lcnt[ii]; jj++)
    199                     cmp[site(lastvt[ii][jj])][site(nstr[i][j + 1])] = '>';
    200             }
    201             if (is_fin(nstr[i][j]) && !is_fin(nstr[i][j + 1])) { //对于终结符在非终结符之前
    202                 for (ii = 0; ii<T; ii++) {
    203                     if (str[ii][0] == nstr[i][j + 1])
    204                         break;
    205                 }
    206                 for (jj = 0; jj<fcnt[ii]; jj++)
    207                     cmp[site(nstr[i][j])][site(firstvt[ii][jj])] = '<';
    208             }
    209         }
    210     }
    211     for (i = 0; fin[i] != ''; i++)
    212         printf("	%c", fin[i]);
    213     puts("");
    214     for (i = 0; i<cnt; i++) {
    215         printf("%c	", fin[i]);
    216         for (j = 0; j<cnt; j++) {
    217             if (cmp[i][j] != 0)
    218                 printf("%c	", cmp[i][j]);
    219             else
    220                 printf(" 	");
    221         }
    222         puts("");
    223     }
    224 
    225 }
    226 void output(int i, int j, char *str) {
    227     printf("	");
    228     for (int ii = i; ii <= j; ii++)
    229         printf("%c", str[ii]);
    230 }
    231 
    232 int isDX(char c)
    233 {
    234     if (c >= 'A'&&c <= 'Z')
    235         return 1;
    236     return 0;
    237 }
    238 void exchange()
    239 {
    240     int ecnt = 0;
    241     for (int i = 0; i<10; i++) {
    242         int mcnt = 0;
    243         for (int j = 3; nstr[i][j] != ''; j++) {
    244             if (isDX(nstr[i][j]) && strlen(nstr[i]) != 4)
    245                 mstr[ecnt][mcnt++] = 'N';
    246             else if (!isDX(nstr[i][j]))
    247                 mstr[ecnt][mcnt++] = nstr[i][j];
    248             else {
    249                 break;
    250             }
    251         }
    252         mstr[ecnt][mcnt] = '';
    253         if (strlen(mstr[ecnt]) != 0)
    254             ecnt++;
    255     }
    256 }
    257 int get_process(char *st)//
    258 {
    259     exchange();
    260     int len = strlen(st);
    261     int t = 0;//栈内元素的个数
    262     int i = 0, j;
    263     int bz = 1;
    264     stac[0] = '#';
    265     while (st[i] != '') {
    266         if (is_fin(stac[t])) j = t;
    267         else j = t - 1;
    268         int a = site(stac[j]);
    269         int b = site(st[i]);
    270         if (cmp[a][b] == '<' || cmp[a][b] == '=') {
    271             printf("	%d", bz++);
    272             output(0, t, stac);
    273             printf("	%c", cmp[a][b]);
    274             printf("	%c", st[i]);
    275             output(i + 1, len - 1, st);
    276             printf("	移进");
    277             puts("");
    278             t++;
    279             stac[t] = st[i];
    280             i++;
    281         }
    282         else if (cmp[a][b] == '>') {
    283             printf("	%d", bz++);
    284             output(0, t, stac);
    285             printf("	%c", cmp[a][b]);
    286             printf("	%c", st[i]);
    287             output(i + 1, len - 1, st);
    288             printf("	归约");
    289             puts("");
    290             int ii, jj, kk;
    291             int flag = 0;
    292             for (ii = t; ii >= 0; ii--) {
    293                 for (jj = 0; jj<maxn; jj++) {
    294                     int lee = strlen(mstr[jj]);
    295                     int kkn = 0;
    296                     for (kk = lee - 1; kk >= 0; kk--) {
    297                         if (stac[ii] == mstr[jj][kk]) {
    298                             ii--;
    299                             kkn++;
    300                         }
    301                         else
    302                             break;
    303                     }
    304                     if (strlen(mstr[jj]) == kkn) {
    305                         t = ii + 1;
    306                         stac[t++] = 'N';
    307                         stac[t] = '';
    308                         t--;
    309                         flag = 1;
    310                         break;
    311                     }
    312                     else {
    313                         ii = ii + kkn;
    314                     }
    315                 }
    316                 if (!flag) {
    317                     printf("	错误");
    318                     return 0;
    319                 }
    320                 else {
    321                     if (t == 1 && st[i] == '#') {
    322                         printf("	%d", bz++);
    323                         output(0, t, stac);
    324                         printf("	=");
    325                         printf("	%c", st[i]);
    326                         output(i + 1, len, st);
    327                         printf("	接受");
    328                         return 1;
    329                     }
    330                     break;
    331                 }
    332             }
    333         }
    334     }
    335 }
    336 int main() {
    337     int T;
    338     int cnt = 0;//终结符的个数
    339     for (int i = 0; i < 10; i++)
    340         cout << "*********";
    341     cout << endl;
    342     cout << "周博(20173599)" << endl;
    343     for (int i = 0; i < 10; i++)
    344         cout << "*********";
    345     cout << endl;
    346     memset(firstflag, 0, sizeof(firstflag));
    347     memset(lastflag, 0, sizeof(lastflag));
    348     memset(cmp, 0, sizeof(cmp));
    349     cout << "请输入文法规则数:";
    350     cin >> T;
    351     cout << "请输入文法规则:" << endl;
    352     for (int i = 0; i < T; i++) {
    353         cin >> str[i];
    354         fcnt[i] = lcnt[i] = 0;
    355     }
    356     //让输入的格式化
    357     int oo = 0;
    358     int mm = T;
    359     //int column = sizeof(str[0]) / sizeof(char);
    360     char str_str[maxn][Maxn];//输入文法
    361     for (int i = 0; i < maxn; i++) {
    362         for (int j = 0; j<Maxn; j++)
    363         {
    364             str_str[i][j] = '';
    365         }
    366     }
    367     for (int i = 0; i < mm; i++) {
    368         for (int j = 0; str[i][j] != ''; j++)
    369         {
    370             str_str[i][j] = str[i][j];
    371         }
    372     }
    373     int TT = T;
    374     for (int i = 0; i<mm; i++) {
    375         for (int j = 0; str_str[i][j] != ''; j++)
    376         {
    377             int column = 0;
    378             for (column = 0; str_str[i][column] != ''; column++)
    379             {
    380 
    381             }
    382             column += 1;
    383             if (str_str[i][j] == '>')
    384             {
    385                 oo = j;
    386 
    387             }
    388             if (str_str[i][j] == '|')
    389             {
    390                 char str_f[Maxn];
    391                 for (int qq = 0; qq < column; qq++)
    392                 {
    393                     str_f[qq] = str_str[i][qq];
    394                 }
    395                 for (int qq = j; qq < column; qq++)
    396                 {
    397                     str_str[i][qq] = '';
    398                 }
    399 
    400 
    401 
    402                 TT = TT + 1;
    403                 for (int qq = 0; qq < oo + 1; qq++)
    404                 {
    405                     str_str[TT-1][qq] = str_f[qq];
    406                 }
    407                 int mid = oo + 1;
    408                 for (int qq = j + 1; qq < column; qq++)
    409                 {
    410                     str_str[TT - 1][mid] = str_f[qq];
    411                     mid = mid + 1;
    412                 }
    413                 for (int qq = 0; qq < column; qq++)
    414                 {
    415                     cout << str_str[TT - 1][qq];
    416                 }
    417                 break;
    418             }
    419         }
    420 
    421     }
    422     cout << endl;
    423     for (int i = 0; i < TT; i++)
    424     {
    425         cout << i + 1 << ": " << str_str[i] << endl;
    426     }
    427     for (int i = 0; i<T; i++) {
    428         for (int j = 0; str[i][j] != ''; j++) {
    429             if ((str[i][j]<'A' || str[i][j]>'Z') && (str[i][j] != '-'&&str[i][j] != '>') && str[i][j] != '|')
    430                 fin[cnt++] = str[i][j];
    431         }
    432     }
    433     fin[cnt++] = '#';
    434     fin[cnt] = '';
    435     cout << "FIRSTUT集为:" << endl;
    436     output_firstvt(T);
    437     cout << endl;
    438     cout << "LASTUT集为:" << endl;
    439     output_lastvt(T);
    440     cout << "算符优先分析表如下:" << endl;
    441     get_table(T, cnt);
    442     cout << "请输入文法输入符号以#结束:";
    443     //scanf("%s", st);
    444     cin >> st;
    445     get_process(st);
    446     int a;
    447     cin >> a;
    448     return 0;
    449 }
  • 相关阅读:
    ViewPager 滑动页(一)
    Fragment中Button的android:onClick 无法监听相应
    Button的四种Click响应方法
    环形图 自定义(一)
    Progress 自定义(一)-shape
    Button 自定义(一)-shape
    客户机页表遍历
    KVM的ept机制
    linux内核源码中两个重要的宏
    总结
  • 原文地址:https://www.cnblogs.com/smartisn/p/12207412.html
Copyright © 2011-2022 走看看