编译原理实验《预测分析法设计与实现》

预测分析法设计与实现

目录

预测分析法设计与实现

任务描述

相关知识

自上而下的语法分析器

预测分析法

实验步骤

目标语言的语法规则

求解预测分析方法需要的符号集和分析表

编程要求

测试说明


任务描述

本关任务:加深对语法分析器工作过程的理解;加强对预测分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。

相关知识

为了完成本关任务,你需要掌握:用预测分析法编制语法分析程序。

自上而下的语法分析器

语法分析在编译中是一个重要的环节,语法分析可以分为自上而下分析和自下而上分析两种方式。

自上而下分析法是从文法开始符号开始,不断进行推导,直到推导所得的符号串与输入串相同为止。简单来解释这句话:我们有一个既定的文法,和一个需要分析的符号串。接下来我们从文法的开始符号出发,反复地使用文法规定的一些产生式匹配符号串的每一个符号,直到所得的符号串和待分析的符号串相同,则为分析成功,反之匹配不成功。

下面我们举例来进行说明: 我们有文法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)分析法的一种实现方法,它通过一张表来关联非终结符和终结符,这张表就是预测分析表,预测分析表可以说是预测分析法的核心部分。我们在进行该方法时,首先要构建预测分析表。

首先介绍一下预测分析表的结构,简单来说他就是一张表,表的两个属性分别是非终结符和终结符(包括‘#’),形如:

,


其中对应的内容是产生式的形式,若是没有产生式则可以写入标记来表示其匹配不到具体的产生式,进入报错处理程序。

在根据文法构造预测分析表时需要扫描全部产生式:

  1. 计算产生式的右部的FIRST集合,如果求出来的FIRST集合中包含终结符,那么就把这条产生式放入对应非终结符和终结符的格子中
  2. 如果ε在FIRST集合中,则计算该非终结符的FOLLOW集合,如果求出来的FOLLOW集合中包含终结符,那么就把这条产生式放入对应的非终结符和终结符的格子中

当预测分析表构造完成后,我们便可以运用预测分析法进行语法分析了。我们使用用一个栈来存放过程数据,主要步骤如下:

  1. 获取栈顶的元素A,获取输入串目前指针指向的元素a
  2. 若A = ‘#’ ,a = ‘#’ 则匹配成功
  3. 若A = a 但是A和a不为’#’,则pop栈顶元素,输入串指针+1
  4. 若A为非终结符,这查询预测分析表,把由A和a确定的产生式的右部从右往左依次压入到栈中,若右部是ε,那就不做操作
  5. 查找预测分析表得到预设的出错字符则调用error()
实验步骤

根据语法分析器的一般功能,我们的程序应具有如下的要求及实验步骤:

  1. 定义目标语言的语法规则;
  2. 求解预测分析方法需要的符号集和分析表;
  3. 依次读入测试用例,根据预测分析的方法进行语法分析,直到源程序结束;该部分具体见上。
  4. 对遇到的语法错误做出错误处理。

下面我们对步骤1,2进行说明。

目标语言的语法规则

该部分重点在于消除文法的二义性,消除左递归,提取左公共因子。想要让程序自动地消除左递归,具体的做法如下: 1.把文法的所有非终结符进行排序S = [‘A’,‘B’,…] 2.做一个嵌套循环: 其中S[k]为排在S[j]之后的非终结符,bunch_i为非终结符和终结符组成的串

 
  1. for j in range(len(s)):
  2. for k in range(j):
  3. 原产生式中:S[j]→S[k]bunch_1的S[k]用其对应的产生式代替
  4. S[k]→bunch_2|bunch_3|...
  5. 推出:S[j]→bunch_2 bunch_1|bunch_3 bunch_1|...
  6. 如此,做完循环后该文法若有间接左递归,就将其转换成直接左递归了
  7. 消除直接左递归,具体做法见上文
  8. 循环结束后删除无用产生式
求解预测分析方法需要的符号集和分析表

符号集主要是构造FIRST集和FOLLOW集,其主要目的是为了消除回溯,也就是选择候选式的时候能够更加准确,当然,这些集合在别的地方也有用处。

构造FIRST集: 扫描所有的产生式,对于每一个X,连续使用以下规则,直至每个集合的FIRST集合不再增大为止,每一遍扫描所有产生式如果有FIRST集合变化则重新扫描:

  1. 如果X是终结符,则FIRST(X) = {X}.
  2. 如果X是非终结符 ,且有产生式 X → a… 则把a加入到FIRST集合中. 若 X → ε也是其中一条产生式,则把ε也加入到FIRST集合中.
  3. 如果X是非终结符,且 X → Y… 是一条产生式,其中Y是非终结符,那么则把FIRST(Y) \ {ε}(即FIRST集合去除ε)加入到FIRST(X)中.

构造FOLLOW集: 扫描所有产生式.对于文法G的每一个非终结符A构造FOLLOW(A)可以连续使用以下规则,直至每一个FOLLOW集合不在增大为止:

  1. 对于文法的开始符号S,置 # 于FOLLOW(S)中.
  2. 若有产生式 A → αBβ,其中α和β是非终结符和终结符构成的串,B为非终结符,则把FIRST(β) \ {ε}加入到FOLLOW(B)中.
  3. 若有产生式 A → αB 或 A → αBβ ε∈FIRST(β) ,则把FOLLOW(A)加入到FOLLOW(B)中.

分析表的构成见上所述。

编程要求

根据提示,在右侧编辑器补充代码,运行程序,进行结果对比。

测试说明

测试输入的格式为:

  1. E T F
  2. + * ( ) i
  3. E->E+T|T
  4. T->T*F|F
  5. F->(E)|i
  6. (i)*i
  7. (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;
}

 如有错误,敬请指正!

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

源来在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值