预测分析法设计与实现
目录
任务描述
本关任务:加深对语法分析器工作过程的理解;加强对预测分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
相关知识
为了完成本关任务,你需要掌握:用预测分析法编制语法分析程序。
自上而下的语法分析器
语法分析在编译中是一个重要的环节,语法分析可以分为自上而下分析和自下而上分析两种方式。
自上而下分析法是从文法开始符号开始,不断进行推导,直到推导所得的符号串与输入串相同为止。简单来解释这句话:我们有一个既定的文法,和一个需要分析的符号串。接下来我们从文法的开始符号出发,反复地使用文法规定的一些产生式匹配符号串的每一个符号,直到所得的符号串和待分析的符号串相同,则为分析成功,反之匹配不成功。
下面我们举例来进行说明: 我们有文法G(E): E→aF F→b|c 以及待输入的字符 ab,从文法开始符号E出发,E→aF,a匹配成功后,指针指向F,找非终结符F的产生式合适的候选式 b匹配,于是匹配成功。
想要对一个文法进行自上而下的分析,要消除文法的二义性,消除左递归,提取左公共因子,计算FIRST集合和FOLLOW集合,判断文法是否为LL(1)型文法,一个文法经过这些步骤,并且是LL(1)文法,则可以用LL(1)分析法的具体实现去分析。我们在后续的实验步骤中会进行该过程的一一实验。
预测分析法
预测分析法是LL(1)分析法的一种实现方法,它通过一张表来关联非终结符和终结符,这张表就是预测分析表,预测分析表可以说是预测分析法的核心部分。我们在进行该方法时,首先要构建预测分析表。
首先介绍一下预测分析表的结构,简单来说他就是一张表,表的两个属性分别是非终结符和终结符(包括‘#’),形如:
其中对应的内容是产生式的形式,若是没有产生式则可以写入标记来表示其匹配不到具体的产生式,进入报错处理程序。
在根据文法构造预测分析表时需要扫描全部产生式:
- 计算产生式的右部的FIRST集合,如果求出来的FIRST集合中包含终结符,那么就把这条产生式放入对应非终结符和终结符的格子中
- 如果ε在FIRST集合中,则计算该非终结符的FOLLOW集合,如果求出来的FOLLOW集合中包含终结符,那么就把这条产生式放入对应的非终结符和终结符的格子中
当预测分析表构造完成后,我们便可以运用预测分析法进行语法分析了。我们使用用一个栈来存放过程数据,主要步骤如下:
- 获取栈顶的元素A,获取输入串目前指针指向的元素a
- 若A = ‘#’ ,a = ‘#’ 则匹配成功
- 若A = a 但是A和a不为’#’,则pop栈顶元素,输入串指针+1
- 若A为非终结符,这查询预测分析表,把由A和a确定的产生式的右部从右往左依次压入到栈中,若右部是ε,那就不做操作
- 查找预测分析表得到预设的出错字符则调用error()
实验步骤
根据语法分析器的一般功能,我们的程序应具有如下的要求及实验步骤:
- 定义目标语言的语法规则;
- 求解预测分析方法需要的符号集和分析表;
- 依次读入测试用例,根据预测分析的方法进行语法分析,直到源程序结束;该部分具体见上。
- 对遇到的语法错误做出错误处理。
下面我们对步骤1,2进行说明。
目标语言的语法规则
该部分重点在于消除文法的二义性,消除左递归,提取左公共因子。想要让程序自动地消除左递归,具体的做法如下: 1.把文法的所有非终结符进行排序S = [‘A’,‘B’,…] 2.做一个嵌套循环: 其中S[k]为排在S[j]之后的非终结符,bunch_i为非终结符和终结符组成的串
for j in range(len(s)):
for k in range(j):
原产生式中:S[j]→S[k]bunch_1的S[k]用其对应的产生式代替
S[k]→bunch_2|bunch_3|...
推出:S[j]→bunch_2 bunch_1|bunch_3 bunch_1|...
如此,做完循环后该文法若有间接左递归,就将其转换成直接左递归了
消除直接左递归,具体做法见上文
循环结束后删除无用产生式
求解预测分析方法需要的符号集和分析表
符号集主要是构造FIRST集和FOLLOW集,其主要目的是为了消除回溯,也就是选择候选式的时候能够更加准确,当然,这些集合在别的地方也有用处。
构造FIRST集: 扫描所有的产生式,对于每一个X,连续使用以下规则,直至每个集合的FIRST集合不再增大为止,每一遍扫描所有产生式如果有FIRST集合变化则重新扫描:
- 如果X是终结符,则FIRST(X) = {X}.
- 如果X是非终结符 ,且有产生式 X → a… 则把a加入到FIRST集合中. 若 X → ε也是其中一条产生式,则把ε也加入到FIRST集合中.
- 如果X是非终结符,且 X → Y… 是一条产生式,其中Y是非终结符,那么则把FIRST(Y) \ {ε}(即FIRST集合去除ε)加入到FIRST(X)中.
构造FOLLOW集: 扫描所有产生式.对于文法G的每一个非终结符A构造FOLLOW(A)可以连续使用以下规则,直至每一个FOLLOW集合不在增大为止:
- 对于文法的开始符号S,置 # 于FOLLOW(S)中.
- 若有产生式 A → αBβ,其中α和β是非终结符和终结符构成的串,B为非终结符,则把FIRST(β) \ {ε}加入到FOLLOW(B)中.
- 若有产生式 A → αB 或 A → αBβ ε∈FIRST(β) ,则把FOLLOW(A)加入到FOLLOW(B)中.
分析表的构成见上所述。
编程要求
根据提示,在右侧编辑器补充代码,运行程序,进行结果对比。
测试说明
测试输入的格式为:
E T F
+ * ( ) i
E->E+T|T
T->T*F|F
F->(E)|i
(i)*i
(i)*iii
测试运行如下:
实验代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#ifndef success
#define success 1
#endif
#define MAX_AMOUNT 20
//定义非终结符
typedef struct NOterminal
{
char character;
int first_number; //FIRST集的判定,初始为0
int follow_number; //FOLLOW集的判定,初始为0
char* FIRST; //FIRST 集合
char* FOLLOW; //FOLLOW集合
struct NOterminal* next;
} noterminal;
//定义终结符
typedef struct Terminal
{
char character; //当前的字符
struct Terminal* next;
} terminal;
//定义产生式
typedef struct PRODUCTION
{
char source; //产生的开始
char* result; //产生的结果
struct PRODUCTION* next; //指向下一条
} production;
int amount = 0;
char TEST_STACK[20];
char* TEST_LIST[10];
char terminal_all[10] = { 0 };
terminal TERMINAL_HEAD, * current_terminal = &TERMINAL_HEAD;
noterminal NOTERMINAL_HEAD, * current_noterminal = &NOTERMINAL_HEAD;
production PRODUCTION_HEAD, * current_production = &PRODUCTION_HEAD;
//函数申明
size_t read(void);
size_t test(void);
size_t write(void);
void Test_read(void);
size_t STACK_FULL();
void STACK_POP(void);
size_t STACK_EMPTY();
void init_stack(void);
void prediction(void);
void test_follow(void);
void emergency(int model);
void prediction_table(void);
void STACK_PUSH(char source);
void insert_to_terminal(char get);
void insert_to_noterminal(char get);
void eliminate_left_recursion(void);
void combine(char* destinction, char* source);
size_t is_appeared(char tobejudged, char* source);
void insert_to_production(char source, char* result);
size_t find_first(noterminal* this_noterminal, production* this_production);
size_t find_follow(noterminal* this_noterminal, production* this_production);
int main(void)
{
TERMINAL_HEAD.next = NULL;
NOTERMINAL_HEAD.next = NULL;
PRODUCTION_HEAD.next = NULL;
read();
Test_read();
printf("\n消除左递归\n\n");
eliminate_left_recursion();
Test_read();
printf("\n求FIRST集\n\n");
prediction();
printf("\n求FOLLOW集\n\n");
test_follow();
prediction_table();
emergency(0);
return 0;
}
//读文件
size_t read(void)
{
int line = 0, model = 0, old_line = 0;
int number = 0;
char current_get = 0, read_temp[10] = { 0 };
FILE* read_stream = fopen("/data/workspace/myshixun/test.txt", "r");
if (!read_stream)
{
printf("error in open file ,can`t open file\n");
exit(EXIT_FAILURE);
}
insert_to_terminal('#'); //插入栈底元素,以#表示栈底
insert_to_terminal('^'); //插入空串元素,以^表示栈底
while (!feof(read_stream))
{
current_get = fgetc(read_stream);
while (current_get == ' ')
current_get = fgetc(read_stream); //忽略空格
while (current_get == '\n')
{
current_get = fgetc(read_stream);
line++; //跳过换行
}
switch (line)
{
case 0:
insert_to_noterminal(current_get);
break;
case 1:
insert_to_terminal(current_get);
break;
case 3:
ungetc(current_get, read_stream);
old_line = 1;
break;
default:
perror("error in format of program \n");
emergency(0);
break;
}
if (old_line)
break;
}
while (!feof(read_stream))
{
memset(read_temp, 0, sizeof(read_temp));
old_line = line;
current_get = fgetc(read_stream);
while (current_get == ' ')
current_get = fgetc(read_stream); //忽略空格
while (current_get == '\n')
{
current_get = fgetc(read_stream);
line++; //跳过换行
}
model = ((line - old_line) > model) ? (line - old_line) : model;
switch (model)
{
case 0:
case 1:
fscanf(read_stream, "%s", read_temp);
insert_to_production(current_get, read_temp);
break;
case 2:
ungetc(current_get, read_stream);
TEST_LIST[number] = (char*)malloc(20);
memset(TEST_LIST[number], 0, 20);
fscanf(read_stream, "%s", TEST_LIST[number++]);
break;
default:
perror("error in format of program \n");
emergency(1);
break;
}
}
fclose(read_stream);
return success;
}
//测试
size_t test(void)
{
noterminal* TEMP_NOTERMINAL = NOTERMINAL_HEAD.next;
for (; TEMP_NOTERMINAL != NULL; TEMP_NOTERMINAL = TEMP_NOTERMINAL->next)
{
printf("%c\tfirst number=%d\tfirst=%s\n",
TEMP_NOTERMINAL->character,
TEMP_NOTERMINAL->first_number,
TEMP_NOTERMINAL->FIRST);
}
printf("\n");
return success;
}
/******Begin******/
//求FIRST集合
size_t find_first(noterminal* this_noterminal, production* this_production)
{
noterminal* this_noterminal_temp;
char temp[2] = { 0 };
char* TEMP2, * help;
while (this_production->source != this_noterminal->character)
this_production = this_production->next; //移向下一个产生式
//查看是否是第一次,如果是,分配空间
if (this_noterminal->first_number == 0)
{
this_noterminal->FIRST = (char*)malloc(MAX_AMOUNT + 1);
memset(this_noterminal->FIRST, 0, MAX_AMOUNT + 1);
}
while (this_production && this_production->source == this_noterminal->character)
{
TEMP2 = this_production->result;
while (*TEMP2)
{
if (is_appeared(*TEMP2, terminal_all))
{
temp[0] = this_production->result[0];
combine(this_noterminal->FIRST, temp);
break;
}
else
{
this_noterminal_temp = NOTERMINAL_HEAD.next;
while (this_noterminal_temp->character != *TEMP2)
this_noterminal_temp = this_noterminal_temp->next;
if (this_noterminal_temp->first_number == 0) //没求first集
find_first(this_noterminal_temp, PRODUCTION_HEAD.next);
combine(this_noterminal->FIRST, this_noterminal_temp->FIRST);
help = this_noterminal->FIRST;
while (*help && *help != '^')
help++;
if (*help && *(TEMP2 + 1)) //包含'^'
{
while (*help)
{
*help = *(help + 1);
help++;
}
}
else break;
TEMP2++;
}
}
this_production = this_production->next;
}
this_noterminal->first_number = strlen(this_noterminal->FIRST);
return success;
}
/******End******/
/******Begin******/
//求FOLLOW集合
size_t find_follow(noterminal* this_noterminal, production* this_production)
{
char* help = NULL;
char* temp_result;
int symbol = 0;
char terminal_array[2] = { 0 };
noterminal* FOLLOW_TEMP, * FOLLOW_HELP;
if (this_noterminal->follow_number == 0)
{
this_noterminal->FOLLOW = (char*)malloc(MAX_AMOUNT + 1);
memset(this_noterminal->FOLLOW, 0, MAX_AMOUNT + 1);
}
//第一个非终结符包含有#
if (this_noterminal == NOTERMINAL_HEAD.next)
*this_noterminal->FOLLOW = '#';
while (this_production)
{
temp_result = this_production->result;
//一个产生式未结尾
while (*temp_result)
{
if (*temp_result != this_noterminal->character)
{
temp_result++;
continue;
}
temp_result++;
if (!*temp_result)
symbol = 1;
while (*temp_result)
{
if (is_appeared(*temp_result, terminal_all))
{
terminal_array[0] = *temp_result;
combine(this_noterminal->FOLLOW, terminal_array);
}
else
{
FOLLOW_TEMP = NOTERMINAL_HEAD.next;
while (FOLLOW_TEMP->character != *temp_result)
FOLLOW_TEMP = FOLLOW_TEMP->next;
combine(this_noterminal->FOLLOW, FOLLOW_TEMP->FIRST);
help = this_noterminal->FOLLOW;
while (*help && *help != '^')
help++;
if (*help)//包含'^'
{
while (*help)
{
*help = *(help + 1);
help++;
}
symbol = 1;
}
else
{
symbol = 0;
break;
}
}
temp_result++;
}
if (symbol && this_production->source != this_noterminal->character)
{
FOLLOW_HELP = NOTERMINAL_HEAD.next;
while (FOLLOW_HELP->character != this_production->source)
FOLLOW_HELP = FOLLOW_HELP->next;
if (FOLLOW_HELP->follow_number == 0)
find_follow(FOLLOW_HELP, PRODUCTION_HEAD.next);
combine(this_noterminal->FOLLOW, FOLLOW_HELP->FOLLOW);
symbol = 0;
}
}
this_production = this_production->next;
}
this_noterminal->follow_number = strlen(this_noterminal->FOLLOW);
return success;
}
/******End******/
//紧急退出
void emergency(int model)
{
current_noterminal = NOTERMINAL_HEAD.next;
current_terminal = TERMINAL_HEAD.next;
current_production = PRODUCTION_HEAD.next;
while (current_noterminal)
{
NOTERMINAL_HEAD.next = current_noterminal->next;
free(current_noterminal->FIRST);
free(current_noterminal->FOLLOW);
free(current_noterminal);
current_noterminal = NOTERMINAL_HEAD.next;
}
while (current_terminal)
{
TERMINAL_HEAD.next = current_terminal->next;
free(current_terminal);
current_terminal = TERMINAL_HEAD.next;
}
while (current_production)
{
PRODUCTION_HEAD.next = current_production->next;
free(current_production->result);
free(current_production);
current_production = PRODUCTION_HEAD.next;
}
printf("退出成功\n");
exit(0);
}
//插入到终结符
void insert_to_terminal(char get)
{
terminal* Temp_terminal = (terminal*)malloc(sizeof(terminal));
if (!Temp_terminal)
{
perror("can`t malloc for this program\n");
emergency(0);
}
Temp_terminal->character = get;
Temp_terminal->next = NULL;
current_terminal->next = Temp_terminal;
current_terminal = Temp_terminal; //移向下一个节点
return;
}
//插入到非终结符
void insert_to_noterminal(char get)
{
noterminal* Temp_noterminal = (noterminal*)malloc(sizeof(noterminal));
if (!Temp_noterminal)
{
perror("can`t malloc for this program\n");
emergency(0);
}
Temp_noterminal->character = get;
Temp_noterminal->next = NULL;
Temp_noterminal->FIRST = NULL;
Temp_noterminal->FOLLOW = NULL;
Temp_noterminal->first_number = 0;
Temp_noterminal->follow_number = 0;
current_noterminal->next = Temp_noterminal;
current_noterminal = Temp_noterminal; //移向下一个节点
return;
}
//插入到产生式
void insert_to_production(char source, char* result)
{
char TEMP[20] = { 0 };
int COUNT = 0, number = 0, length = 0, exit_condition = strlen(result);
production* Temp_production;
for (COUNT = 0; COUNT != exit_condition + 1; COUNT++)
{
if (*result == '-' && *(result + 1) == '>')
{
result += 2;
COUNT += 2;
}
if ((*result != '|') && (*result))
TEMP[number++] = *result;
else
{
Temp_production = (production*)malloc(sizeof(production));
length = strlen(TEMP) + 1;
Temp_production->result = (char*)malloc(length);
memset(Temp_production->result, 0, length);
strncpy(Temp_production->result, TEMP, length - 1);
memset(TEMP, 0, sizeof(TEMP));
Temp_production->source = source;
Temp_production->next = NULL;
current_production->next = Temp_production;
current_production = Temp_production;
number = 0;
}
result++;
}
return;
}
/******Begin******/
//消除左递归
void eliminate_left_recursion(void)
{
int number = 0;
char new_char[3] = { 0 }, TEMP_RESULT[20], temp_empty[3] = { '^',0,0 };
production* Temp_production = PRODUCTION_HEAD.next;
production* Temp_FREE;
terminal* temp = TERMINAL_HEAD.next;
while (Temp_production)
{
if (Temp_production->source == Temp_production->result[0])
{
memset(TEMP_RESULT, 0, sizeof(TEMP_RESULT));
new_char[0] = Temp_production->source - 'A' + 'a';
//复制到新的产生式
strcat(TEMP_RESULT, Temp_production->result + 1);
strcat(TEMP_RESULT, new_char);
insert_to_noterminal(new_char[0]);
insert_to_production(new_char[0], TEMP_RESULT);
insert_to_production(new_char[0], temp_empty);
//修改当前的产生式
memset(TEMP_RESULT, 0, sizeof(TEMP_RESULT));
strcat(TEMP_RESULT, Temp_production->next->result);
strcat(TEMP_RESULT, new_char);
memset(Temp_production->result, 0, strlen(Temp_production->result));
strncpy(Temp_production->result, TEMP_RESULT, strlen(TEMP_RESULT));
Temp_FREE = Temp_production->next;
Temp_production->next = Temp_production->next->next;
free(Temp_FREE);
continue;
}
Temp_production = Temp_production->next;
}
while (temp)
{
terminal_all[number++] = temp->character;
temp = temp->next;
}
return;
}
/******End******/
void Test_read(void)
{
int number = 1;
production* TEMP_PRODUCTION = PRODUCTION_HEAD.next;
terminal* TEMP_TERMINAL = TERMINAL_HEAD.next;
noterminal* TEMP_NOTERMINAL = NOTERMINAL_HEAD.next;
printf("\n产生式\n");
for (number = 1; TEMP_PRODUCTION != NULL; TEMP_PRODUCTION = TEMP_PRODUCTION->next, number++)
{
printf("%d\t%c\t%s\n", number, TEMP_PRODUCTION->source, TEMP_PRODUCTION->result);
}
printf("\n终结符\n");
for (; TEMP_TERMINAL != NULL; TEMP_TERMINAL = TEMP_TERMINAL->next)
{
printf("%c\t", TEMP_TERMINAL->character);
}
printf("\n");
printf("\n非终结符\n");
for (; TEMP_NOTERMINAL != NULL; TEMP_NOTERMINAL = TEMP_NOTERMINAL->next)
{
printf("%c\t", TEMP_NOTERMINAL->character);
}
printf("\n读取测试\n%s\n%s\n", TEST_LIST[0], TEST_LIST[1]);
printf("\n");
return;
}
size_t is_appeared(char tobejudged, char* source)
{
size_t length = strlen(source), counts = 0;
while ((counts != length) && (*source != tobejudged))
{
counts++;
source++;
}
return counts == length ? !success : success;
}
void combine(char* destinction, char* source)
{
char temp[2] = { 0 };
while (*source)
{
if (!is_appeared(*source, destinction))
{
temp[0] = *source;
strcat(destinction, temp);
}
source++;
}
return;
}
void prediction(void)
{
noterminal* TEMP_NOTERMINAL = NOTERMINAL_HEAD.next;
while (TEMP_NOTERMINAL != NULL)
{
find_first(TEMP_NOTERMINAL, PRODUCTION_HEAD.next);
TEMP_NOTERMINAL = TEMP_NOTERMINAL->next;
}
test();
TEMP_NOTERMINAL = NOTERMINAL_HEAD.next;
while (TEMP_NOTERMINAL != NULL)
{
find_follow(TEMP_NOTERMINAL, PRODUCTION_HEAD.next);
TEMP_NOTERMINAL = TEMP_NOTERMINAL->next;
}
return;
}
void test_follow(void)
{
noterminal* TEMP_NOTERMINAL = NOTERMINAL_HEAD.next;
for (; TEMP_NOTERMINAL != NULL; TEMP_NOTERMINAL = TEMP_NOTERMINAL->next)
{
printf("%c\tfollow number=%d\tfollow=%s\n",
TEMP_NOTERMINAL->character,
TEMP_NOTERMINAL->follow_number,
TEMP_NOTERMINAL->FOLLOW);
}
printf("\n");
return;
}
/******Begin******/
//生成预测分析表
void prediction_table(void)
{
int line = 0, row = 0, current_character = 0, number = 0;
char* FIRST_CLUM, * test_exper;
noterminal* temp_noterminal = NOTERMINAL_HEAD.next, * temp_noterminal21;
terminal* temp_terminal = TERMINAL_HEAD.next;
production* temp_production = PRODUCTION_HEAD.next;
char hah[5][7];
memset(hah, 0, sizeof(hah));
for (line = 0; line < 5; line++)
{
for (row = 0; row < 7; row++)
hah[line][row] = 0;
}
line = 0;
while (temp_production)
{
row = 0;
if (is_appeared(*temp_production->result, terminal_all) && (*temp_production->result != '^'))
{
while (terminal_all[row] != *temp_production->result)
row++;
hah[current_character][row] = line + 1;
}
else
{
temp_noterminal = NOTERMINAL_HEAD.next;
if (*temp_production->result == '^')
{
while (temp_noterminal->character != temp_production->source)
temp_noterminal = temp_noterminal->next;
FIRST_CLUM = temp_noterminal->FOLLOW;
if (is_appeared('#', FIRST_CLUM))
{
row = 0;
while (terminal_all[row] != '#')
row++;
hah[current_character][row] = line + 1;
}
while (*FIRST_CLUM)
{
row = 0;
while (terminal_all[row] != *FIRST_CLUM)
row++;
hah[current_character][row] = line + 1;
FIRST_CLUM++;
}
if (temp_production->next && temp_production->source != temp_production->next->source)
current_character++;
temp_production = temp_production->next;
line++;
continue;
}
//是非终结符
while (temp_noterminal->character != *temp_production->result)
temp_noterminal = temp_noterminal->next;
FIRST_CLUM = temp_noterminal->FIRST;
while (*FIRST_CLUM)
{
row = 0;
while (terminal_all[row] != *FIRST_CLUM)
row++;
hah[current_character][row] = line + 1;
FIRST_CLUM++;
}
temp_noterminal21 = NOTERMINAL_HEAD.next;
while (temp_noterminal21->character != temp_production->source)
temp_noterminal21 = temp_noterminal21->next;
if (is_appeared('^', temp_noterminal->FIRST) && is_appeared('#', temp_noterminal21->FOLLOW))
{
row = 0;
while (terminal_all[row] != *FIRST_CLUM)
row++;
hah[line][row] = line + 1;
FIRST_CLUM++;
}
}
if (temp_production->next && temp_production->source != temp_production->next->source)
current_character++;
temp_production = temp_production->next;
line++;
}
printf("\n预测分析表\n\n");
printf(" \t");
for (temp_terminal = TERMINAL_HEAD.next; temp_terminal; temp_terminal = temp_terminal->next)
printf("%c\t", temp_terminal->character);
temp_noterminal = NOTERMINAL_HEAD.next;
for (line = 0; line < 5; line++)
{
printf("\n%c\t", temp_noterminal->character);
for (row = 0; row < 7; row++)
printf("%c\t", hah[line][row] == 0 ? ' ' : (hah[line][row] - 0 + '0'));
temp_noterminal = temp_noterminal->next;
}
printf("\n\n");
system("pause");
printf("\n\n");
memset(TEST_STACK, 0, sizeof(TEST_STACK));
init_stack();
test_exper = TEST_LIST[0];
test_exper[strlen(test_exper)] = '#';
STACK_PUSH(NOTERMINAL_HEAD.next->character);
while (!STACK_EMPTY())
{
printf("分析栈\t");
for (number = 0; number <= amount; number++)
printf("%c", TEST_STACK[number]);
printf("\t剩余字符串\t%s\n", test_exper);
if (TEST_STACK[amount] == *test_exper)
{
STACK_POP();
test_exper++;
}
else
{
line = 0;
row = 0;
temp_noterminal = NOTERMINAL_HEAD.next;
while (temp_noterminal->character != TEST_STACK[amount])
{
temp_noterminal = temp_noterminal->next;
line++;
}
while (terminal_all[row] != *test_exper)
row++;
row = hah[line][row];
if (!row)
break;
temp_production = PRODUCTION_HEAD.next;
while (--row)
temp_production = temp_production->next;
FIRST_CLUM = temp_production->result;
current_character = strlen(FIRST_CLUM);
FIRST_CLUM = FIRST_CLUM + current_character - 1;
STACK_POP();
while (current_character)
{
if (*FIRST_CLUM != '^')
STACK_PUSH(*FIRST_CLUM);
FIRST_CLUM--;
current_character--;
}
}
}
printf("分析栈\t");
for (number = 0; number <= amount; number++)
printf("%c", TEST_STACK[number]);
printf("\t剩余字符串\t%s\n", test_exper);
if (STACK_EMPTY() && *test_exper == '#')
printf("\n合法输入\n");
else
printf("\n不合法输入\n");
return;
}
/******End******/
void STACK_POP(void)
{
if (STACK_EMPTY())
{
printf("栈空\n");
emergency(2);
}
amount--;
return;
}
size_t STACK_EMPTY()
{
return amount == 0 ? success : !success;
}
size_t STACK_FULL()
{
return amount == 19 ? success : !success;
}
void STACK_PUSH(char source)
{
if (STACK_FULL())
{
printf("栈满\n");
emergency(2);
}
TEST_STACK[++amount] = source;
return;
}
void init_stack(void)
{
amount = 0;
TEST_STACK[amount] = '#';
return;
}
如有错误,敬请指正!