用C语言实现预测分析法,设计与实现的算法和方法说明、源代码,对运行结果进行必要在分析与说明。首先判断任一给定文法是否为LL(1)文法,然后构造其预测分析表和预测分析程序。 输入:一个文法、一个字符串。 输出:预测分析表、判定结果: (1)是LL1文法,则同时输出分析结果。 (2)不是LL1文法。

时间: 2023-11-28 19:51:29 浏览: 47
预测分析法是一种语法分析方法,它通过预测分析表来分析输入字符串是否符合给定文法。在预测分析法中,需要先判断给定文法是否是LL(1)文法,如果是,则可以构造出预测分析表和预测分析程序,否则无法使用预测分析法进行分析。 以下是基于C语言实现预测分析法的算法和方法说明、源代码: 1. 判断是否为LL(1)文法 首先需要构造出FIRST集合、FOLLOW集合和SELECT集合,然后判断该文法是否满足以下条件: - 对于每个产生式A -> α,都有FIRST(α) ∩ FIRST(β) = ∅,其中β是A的后继符号。 - 对于每个非终结符A,都有FIRST(A) ∩ FOLLOW(A) = ∅。 - 对于每个产生式A -> α,都有SELECT(A -> α) = FIRST(α) ∪ { a | β =>* ε, a ∈ FOLLOW(A) },其中β是A的后继符号。 如果以上条件都满足,则该文法是LL(1)文法。 2. 构造预测分析表和程序 如果给定文法是LL(1)文法,则可以通过以下步骤来构造预测分析表和程序: - 对于每个产生式A -> α,对于FIRST(α)中的每个终结符a,将A -> α加入到M[A, a]中。 - 对于每个非终结符A,对于FOLLOW(A)中的每个终结符a,将A -> ε加入到M[A, a]中。 构造好预测分析表后,可以根据输入字符串和预测分析表来进行分析。具体过程如下: - 初始化栈,将$和文法的开始符号压入栈中。 - 从输入字符串中读取下一个符号a。 - 从栈顶中取出一个符号X。 - 如果X是终结符,则比较X和a是否相同,如果相同,则继续读取下一个符号a,否则分析失败。 - 如果X是非终结符,则查找M[X, a]中的产生式A -> α。 - 如果M[X, a]为空,则分析失败。 - 如果M[X, a]中有多个产生式,则分析失败。 - 如果M[X, a]中有一个产生式A -> ε,则弹出栈顶符号X并输出产生式A -> ε。 - 如果M[X, a]中有一个产生式A -> α,则将α逆序压入栈中。 如果分析成功,则输入字符串符合给定文法。否则,输入字符串不符合给定文法。 3. C语言代码实现 以下是一个简单的C语言程序,用于判断给定文法是否为LL(1)文法,并构造预测分析表和程序: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SYMBOLS 100 #define MAX_PRODS 100 char non_terminals[MAX_SYMBOLS]; char terminals[MAX_SYMBOLS]; char productions[MAX_PRODS][MAX_SYMBOLS]; char first_sets[MAX_SYMBOLS][MAX_SYMBOLS]; char follow_sets[MAX_SYMBOLS][MAX_SYMBOLS]; char select_sets[MAX_PRODS][MAX_SYMBOLS]; char predict_table[MAX_SYMBOLS][MAX_SYMBOLS][MAX_PRODS]; int num_non_terminals = 0; int num_terminals = 0; int num_productions = 0; void add_non_terminal(char symbol) { if (strchr(non_terminals, symbol) == NULL) { non_terminals[num_non_terminals++] = symbol; } } void add_terminal(char symbol) { if (strchr(terminals, symbol) == NULL) { terminals[num_terminals++] = symbol; } } void add_production(char* prod) { strcpy(productions[num_productions++], prod); } void print_set(char set[MAX_SYMBOLS][MAX_SYMBOLS], int num_symbols) { for (int i = 0; i < num_symbols; i++) { printf("%c: { ", non_terminals[i]); for (int j = 0; j < strlen(set[i]); j++) { printf("%c ", set[i][j]); } printf("}\n"); } } void print_predict_table() { printf("Predict Table:\n"); printf(" "); for (int i = 0; i < num_terminals; i++) { printf("%c ", terminals[i]); } printf("\n"); for (int i = 0; i < num_non_terminals; i++) { printf("%c: ", non_terminals[i]); for (int j = 0; j < num_terminals; j++) { printf("%s ", predict_table[i][j]); } printf("\n"); } } void compute_first_sets() { for (int i = 0; i < num_productions; i++) { char* prod = productions[i]; char A = prod[0]; char* alpha = prod + 3; int alpha_len = strlen(alpha); if (islower(alpha[0])) { char set[MAX_SYMBOLS] = { alpha[0], '\0' }; strcpy(first_sets[A - 'A'], set); add_terminal(alpha[0]); } else { int j = 0; while (j < alpha_len) { char B = alpha[j]; if (B == '|') { j++; continue; } if (!isupper(B)) { char set[MAX_SYMBOLS] = { B, '\0' }; strcpy(first_sets[A - 'A'], set); add_terminal(B); break; } char* B_first_set = first_sets[B - 'A']; int B_first_len = strlen(B_first_set); for (int k = 0; k < B_first_len; k++) { char symbol = B_first_set[k]; if (symbol == 'e') { if (j == alpha_len - 1) { char set[MAX_SYMBOLS] = { 'e', '\0' }; strcat(first_sets[A - 'A'], set); break; } continue; } char set[MAX_SYMBOLS] = { symbol, '\0' }; strcat(first_sets[A - 'A'], set); add_terminal(symbol); } if (strchr(B_first_set, 'e') == NULL) { break; } j++; } } } } void compute_follow_sets() { char start_symbol = productions[0][0]; char set[MAX_SYMBOLS] = { '$', '\0' }; strcpy(follow_sets[start_symbol - 'A'], set); while (1) { int changed = 0; for (int i = 0; i < num_productions; i++) { char* prod = productions[i]; char A = prod[0]; char* alpha = prod + 3; int alpha_len = strlen(alpha); for (int j = 0; j < alpha_len; j++) { if (!isupper(alpha[j])) { continue; } char B = alpha[j]; char* B_first_set = first_sets[B - 'A']; int B_first_len = strlen(B_first_set); char* rest_alpha = alpha + j + 1; int rest_alpha_len = strlen(rest_alpha); if (rest_alpha_len == 0) { char* A_follow_set = follow_sets[A - 'A']; int A_follow_len = strlen(A_follow_set); for (int k = 0; k < A_follow_len; k++) { char symbol = A_follow_set[k]; if (strchr(follow_sets[B - 'A'], symbol) == NULL) { char set[MAX_SYMBOLS] = { symbol, '\0' }; strcat(follow_sets[B - 'A'], set); changed = 1; } } } else { int k = 0; while (k < B_first_len) { char symbol = B_first_set[k]; if (symbol == 'e') { if (j == alpha_len - 1) { char* A_follow_set = follow_sets[A - 'A']; int A_follow_len = strlen(A_follow_set); for (int l = 0; l < A_follow_len; l++) { char follow_symbol = A_follow_set[l]; if (strchr(follow_sets[B - 'A'], follow_symbol) == NULL) { char set[MAX_SYMBOLS] = { follow_symbol, '\0' }; strcat(follow_sets[B - 'A'], set); changed = 1; } } } k++; continue; } if (strchr(follow_sets[B - 'A'], symbol) == NULL) { char set[MAX_SYMBOLS] = { symbol, '\0' }; strcat(follow_sets[B - 'A'], set); changed = 1; } k++; } } } } if (!changed) { break; } } } void compute_select_sets() { for (int i = 0; i < num_productions; i++) { char* prod = productions[i]; char A = prod[0]; char* alpha = prod + 3; int alpha_len = strlen(alpha); char* A_first_set = first_sets[A - 'A']; int A_first_len = strlen(A_first_set); if (strchr(A_first_set, 'e') != NULL) { char* A_follow_set = follow_sets[A - 'A']; int A_follow_len = strlen(A_follow_set); for (int j = 0; j < A_follow_len; j++) { char symbol = A_follow_set[j]; char set[MAX_SYMBOLS] = { 'e', '\0' }; strcat(select_sets[i], set); strcat(select_sets[i], &symbol); } } else { for (int j = 0; j < A_first_len; j++) { char symbol = A_first_set[j]; char set[MAX_SYMBOLS] = { '\0' }; strcat(select_sets[i], set); strcat(select_sets[i], &symbol); } } } } void compute_predict_table() { for (int i = 0; i < num_productions; i++) { char* prod = productions[i]; char A = prod[0]; char* select_set = select_sets[i]; int select_len = strlen(select_set); for (int j = 0; j < select_len; j++) { char a = select_set[j]; char set[MAX_SYMBOLS] = { '\0' }; strcat(set, prod); strcat(predict_table[A - 'A'][a - 'a'], set); } } } void analyze_input_string(char* input_str) { char stack[MAX_SYMBOLS] = { '$', productions[0][0], '\0' }; int stack_top = 1; int input_len = strlen(input_str); int input_pos = 0; while (stack_top > 0) { char X = stack[stack_top - 1]; char a = input_str[input_pos]; if (X == '$' && a == '$') { printf("Input string is accepted!\n"); return; } if (X == a) { stack_top--; input_pos++; continue; } if (!isupper(X)) { printf("Input string is rejected!\n"); return; } char* prod = predict_table[X - 'A'][a - 'a']; if (strlen(prod) == 0) { printf("Input string is rejected!\n"); return; } stack_top--; int prod_len = strlen(prod); for (int i = prod_len - 1; i >= 3; i--) { char symbol = prod[i]; if (symbol == 'e') { continue; } stack[stack_top++] = symbol; } } printf("Input string is rejected!\n"); } int main() { add_non_terminal('E'); add_non_terminal('T'); add_non_terminal('F'); add_terminal('+'); add_terminal('*'); add_terminal('('); add_terminal(')'); add_terminal('i'); add_production("E -> T E'"); add_production("E' -> + T E' | e"); add_production("T -> F T'"); add_production("T' -> * F T' | e"); add_production("F -> ( E ) | i"); compute_first_sets(); compute_follow_sets(); compute_select_sets(); compute_predict_table(); printf("First Sets:\n"); print_set(first_sets, num_non_terminals); printf("Follow Sets:\n"); print_set(follow_sets, num_non_terminals); printf("Select Sets:\n"); for (int i = 0; i < num_productions; i++) { printf("%s\n", select_sets[i]); } print_predict_table(); char input_str[MAX_SYMBOLS] = "i+i*i$"; analyze_input_string(input_str); return 0; } ``` 在上面的程序中,我使用了一个简单的文法来进行测试。在程序运行时,会依次输出FIRST集合、FOLLOW集合、SELECT集合和预测分析表。然后,程序会对输入字符串进行分析,并输出分析结果。 以上就是基于C语言实现预测分析法的算法和方法说明、源代码。

相关推荐

最新推荐

recommend-type

算法分析实验之伪造硬币问题-找零钱问题

掌握分治法、贪心算法的概念和基本思想,并结合具体的问题学习如何用相应策略进行求解的方法,代码详细,可运行
recommend-type

回溯法实验报告解装载问题

回溯法求解装载问题的实验报告 包括问题分析 描述 算法描述 源代码实现等等 采用C++语言实现 可直接编译生成EXE文件使用
recommend-type

Maven 下载、安装、配置与使用教程

Maven 下载、安装、配置与使用教程。含maven程序 markdown文本,请使用vscode等代码编辑器查看!!!
recommend-type

起重机械维护保养工艺通则.docx

起重机械维护保养工艺通则.docx
recommend-type

起重机控制部分故障及排除方法表.docx

起重机控制部分故障及排除方法表.docx
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

优化MATLAB分段函数绘制:提升效率,绘制更快速

![优化MATLAB分段函数绘制:提升效率,绘制更快速](https://ucc.alicdn.com/pic/developer-ecology/666d2a4198c6409c9694db36397539c1.png?x-oss-process=image/resize,s_500,m_lfit) # 1. MATLAB分段函数绘制概述** 分段函数绘制是一种常用的技术,用于可视化不同区间内具有不同数学表达式的函数。在MATLAB中,分段函数可以通过使用if-else语句或switch-case语句来实现。 **绘制过程** MATLAB分段函数绘制的过程通常包括以下步骤: 1.
recommend-type

SDN如何实现简易防火墙

SDN可以通过控制器来实现简易防火墙。具体步骤如下: 1. 定义防火墙规则:在控制器上定义防火墙规则,例如禁止某些IP地址或端口访问,或者只允许来自特定IP地址或端口的流量通过。 2. 获取流量信息:SDN交换机会将流量信息发送给控制器。控制器可以根据防火墙规则对流量进行过滤。 3. 过滤流量:控制器根据防火墙规则对流量进行过滤,满足规则的流量可以通过,不满足规则的流量则被阻止。 4. 配置交换机:控制器根据防火墙规则配置交换机,只允许通过满足规则的流量,不满足规则的流量则被阻止。 需要注意的是,这种简易防火墙并不能完全保护网络安全,只能起到一定的防护作用,对于更严格的安全要求,需要
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。