软件构造——实验五 算符优先分析法

Posted smartisn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件构造——实验五 算符优先分析法相关的知识,希望对你有一定的参考价值。

【实验目的】 

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

【实验内容】 

(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 }

以上是关于软件构造——实验五 算符优先分析法的主要内容,如果未能解决你的问题,请参考以下文章

软件构造Lab2基本流程指导及重难点分析

软件构造——制作词法分析器

编译原理语法分析之自底向上分析之算符优先分析法

软件构造—— 实验二 lex词法分析

S5-自底向上的语法分析

c ++:强制转换运算符与分配运算符与转换构造函数优先级