一、实验项目要求
1.实验目的
根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对预测分析LL(1)分析法的理解。
2.实验要求
对下列文法,用LL(1)分析法对任意输入的符号串进行分析:
(1)E->TG
(2)G->+TG|—TG
(3)G->ε
(4)T->FS
(5)S->*FS|/FS
(6)S->ε
(7)F->(E)
(8)F->i
输出的格式如下:
(1)LL(1)分析程序,编制人:姓名,学号,班级
(2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串
(3)输出过程如下:
步骤 | 分析栈 | 剩余输入串 | 所用产生式 |
1 | E | i+i*i# | E->TG |
(4)输入符号串为非法符号串(或者为合法符号串)
备注:
(1)在“所用产生式”一列中如果对应有推导则写出所用产生式;如果为匹配终结符则写明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。
(2)在此位置输入符号串为用户自行输入的符号串。
(3)上述描述的输出过程只是其中一部分的。
注意:
1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#;
2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);
二、理论分析或算法分析
1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。
2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。
3.程序编写
(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);
(3)控制部分:从键盘输入一个表达式符号串;
(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
三、实验方法
程序流程图如图所示:
四、实验结果分析
实验结果图
遇到的问题
(1)遇到如图所示的问题
解决办法
(1)在程序最前面加#define _CRT_SECURE_NO_WARNINGS后可以解决;
在本次实验中,不仅使我编译原理的知识更加巩固,而且可以使理论与实践相结合,更好的掌握所学知识。我也发现自己的不足之处,以后会多加改正。
五、代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dos.h>
char A[20];/*分析栈*/
char B[20];/*剩余串*/
char v1[20] = { 'i','+','-','*','/','(',')','#' };/*终结符 */
char v2[20] = { 'E','G','T','S','F' };/*非终结符 */int j = 0, b = 0, top = 0, l;/*L为输入串长度 */typedef struct type/*产生式类型定义 */
{char origin;/*大写字符 */char array[5];/*产生式右边字符 */int length;/*字符个数 */
}type;type e, t, g, g1, g2, s, s2, s1, f, f1;/*结构体变量 */
type C[10][10];/*预测分析表 */void print()/*输出分析栈 */
{int a;/*指针*/for (a = 0; a <= top + 1; a++)printf("%c", A[a]);printf("\t\t");
}/*print*/void print1()/*输出剩余串*/
{int j;for (j = 0; j < b; j++)/*输出对齐符*/printf(" ");for (j = b; j <= l; j++)printf("%c", B[j]);printf("\t\t\t");
}/*print1*/void main()
{int m, n, k = 0, flag = 0, finish = 0;char ch, x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin = 'E';strcpy(e.array, "TG");e.length = 2;t.origin = 'T';strcpy(t.array, "FS");t.length = 2;g.origin = 'G';strcpy(g.array, "+TG");g.length = 3;g1.origin = 'G';strcpy(g1.array, "-TG");g1.length = 3;g2.origin = 'G';g2.array[0] = '^';g2.length = 1;/s.origin = 'S';strcpy(s.array, "*FS");s.length = 3;s1.origin = 'S';strcpy(s1.array, "/FS");s1.length = 3;s2.origin = 'S';s2.array[0] = '^';s2.length = 1;f.origin = 'F';strcpy(f.array, "(E)");f.length = 3;f1.origin = 'F';f1.array[0] = 'i';f1.length = 1;for (m = 0; m <= 4; m++)/*初始化分析表*/for (n = 0; n <= 5; n++)C[m][n].origin = 'N';/*全部赋为空*//*填充分析表*/
//char v1[20]={'i','+','-','*','/','(',')','#'};/*终结符 */
//char v2[20]={'E','G','T','S','F'};/*非终结符 */C[0][0] = e; C[0][5] = e;C[1][1] = g; C[1][2] = g1; C[1][3] = C[1][4] = C[1][7] = g2;C[2][0] = t; C[2][3] = t; C[2][5] = t;C[3][1] = C[3][2] = s2; C[3][3] = s; C[3][4] = s1; C[3][6] = C[3][7] = s2;C[4][0] = f1; C[4][5] = f;printf("LL(1)分析程序,编制人:孙志英,27号,1920542班\n");printf("输入一以#结束的符号串(包括+ - * / () i #):");do/*读入分析串*/{scanf("%c", &ch);if ((ch != 'i') && (ch != '+') && (ch != '-') && (ch != '*') && (ch != '/') && (ch != '(') && (ch != ')') && (ch != '#')){printf("输入串中有非法字符\n");exit(1);}B[j] = ch;j++;} while (ch != '#');l = j;/*分析串长度*/ch = B[0];/*当前分析字符*/A[top] = '#'; A[++top] = 'E';/*'#','E'进栈*/printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n");do{x = A[top--];/*x为当前栈顶字符*/printf("%d", k++);printf("\t\t");for (j = 0; j <= 7; j++)/*判断是否为终结符*/if (x == v1[j]){flag = 1;break;}if (flag == 1)/*如果是终结符*/{if (x == '#'){finish = 1;/*结束标记*/printf("acc!\n");/*接受 */getchar();getchar();exit(1);}/*if*/if (x == ch){print();print1();printf("%c匹配\n", ch);ch = B[++b];/*下一个输入字符*/flag = 0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n", ch);/*输出出错终结符*/exit(1);}/*else*/}/*if*/else/*非终结符处理*/{for (j = 0; j <= 4; j++)if (x == v2[j]){m = j;/*行号*/break;}for (j = 0; j <= 7; j++)if (ch == v1[j]){n = j;/*列号*/break;}cha = C[m][n];if (cha.origin != 'N')/*判断是否为空*/{print();print1();printf("%c->", cha.origin);/*输出产生式*/for (j = 0; j < cha.length; j++)printf("%c", cha.array[j]);printf("\n");for (j = (cha.length - 1); j >= 0; j--)/*产生式逆序入栈*/A[++top] = cha.array[j];if (A[top] == '^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n", x);/*输出出错非终结符*/exit(1);}/*else*/}/*else*/} while (finish == 0);
}/*main*/