在本实验中,请根据课本P159中给出的FIRSTOP 构造算法的伪代码编写程序,实现对输入文法中所有变量FIRSTOP 集的求解。用c语言写
时间: 2024-02-18 16:05:26 浏览: 385
好的,根据课本P159中给出的FIRSTOP构造算法的伪代码,下面是C语言的实现代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SYMBOL_NUM 100 // 非终结符的最大数量
#define MAX_STRING_LEN 100 // 产生式右部字符串的最大长度
char nonterminals[MAX_SYMBOL_NUM]; // 存储所有的非终结符
char productions[MAX_SYMBOL_NUM][MAX_STRING_LEN]; // 存储所有的产生式
int n_productions; // 产生式的数量
int first_sets[MAX_SYMBOL_NUM][MAX_SYMBOL_NUM]; // 存储每个非终结符的FIRST集合
int n_nonterminals; // 非终结符的数量
// 判断一个字符是否为非终结符
int is_nonterminal(char c) {
return c >= 'A' && c <= 'Z';
}
// 根据非终结符的名称查找其在nonterminals数组中的下标
int find_nonterminal_index(char c) {
int i;
for (i = 0; i < n_nonterminals; i++) {
if (nonterminals[i] == c) {
return i;
}
}
return -1;
}
// 计算一个非终结符的FIRST集合
void calc_first_set(char symbol) {
int i, j, k, len;
char prod[MAX_STRING_LEN];
int symbol_index = find_nonterminal_index(symbol);
memset(first_sets[symbol_index], 0, sizeof(first_sets[symbol_index])); // 初始化FIRST集合为空集
// 遍历所有的产生式
for (i = 0; i < n_productions; i++) {
if (productions[i][0] == symbol) { // 如果产生式的左部是当前非终结符
// 将右部字符串拷贝到prod数组中,方便遍历每个字符
len = strlen(productions[i]);
for (j = 2, k = 0; j < len; j++, k++) {
prod[k] = productions[i][j];
}
prod[k] = '\0';
// 如果右部第一个字符是终结符,则将其加入FIRST集合中
if (!is_nonterminal(prod[0])) {
first_sets[symbol_index][prod[0]-'a'] = 1;
} else { // 否则计算该终结符的FIRST集合,并将其加入到当前非终结符的FIRST集合中
int nonterminal_index = find_nonterminal_index(prod[0]);
for (j = 0; j < n_nonterminals; j++) {
if (first_sets[nonterminal_index][j] == 1) {
first_sets[symbol_index][j] = 1;
}
}
}
// 如果右部包含空串,则将空串加入FIRST集合中,并继续计算后续终结符的FIRST集合
if (strstr(prod, "e") != NULL) {
first_sets[symbol_index][n_nonterminals] = 1;
for (j = 1; j < strlen(prod); j++) {
if (!is_nonterminal(prod[j])) {
break;
}
int nonterminal_index = find_nonterminal_index(prod[j]);
for (k = 0; k < n_nonterminals; k++) {
if (first_sets[nonterminal_index][k] == 1) {
first_sets[symbol_index][k] = 1;
}
}
if (first_sets[nonterminal_index][n_nonterminals] != 1) {
break;
}
}
}
}
}
}
int main() {
scanf("%d", &n_productions);
int i, j;
char left, arrow, right[MAX_STRING_LEN];
for (i = 0; i < n_productions; i++) {
scanf(" %c %c %s", &left, &arrow, right);
nonterminals[i] = left;
strcpy(productions[i], right);
}
n_nonterminals = i;
// 计算每个非终结符的FIRST集合
for (i = 0; i < n_nonterminals; i++) {
calc_first_set(nonterminals[i]);
}
// 打印每个非终结符的FIRST集合
for (i = 0; i < n_nonterminals; i++) {
printf("FIRST(%c)={", nonterminals[i]);
for (j = 0; j < n_nonterminals+1; j++) {
if (first_sets[i][j] == 1) {
if (j == n_nonterminals) {
printf("e");
} else {
printf("%c", 'a'+j);
}
}
}
printf("}\n");
}
return 0;
}
```
以上是C语言实现的代码,可以编译运行。该程序可以接受如下格式的输入:
```
3
S -> aA | bB
A -> cS | d
B -> cS | e
```
其中第一行是产生式的数量,每个产生式按照 S -> aA 的格式输入。程序会输出每个非终结符的FIRST集合。
阅读全文
相关推荐
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![txt](https://img-home.csdnimg.cn/images/20241231045021.png)
![-](https://img-home.csdnimg.cn/images/20241231045021.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)