一、实验项目要求
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*/