1 /* 2 * 该程序用于计算某个非终结符的 FOLLOW 集合 3 * RexfieldVon 4 * 2013年6月30日16:02:47 5 */ 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 /* 三级指针 11 * 第一级指向整个产生式组 12 * 第二级指向单个产生式 13 * 第三级指向产生式符号单元 14 * 约定:所有的大写字母为非终结符 15 * 假设:无左递归、FIRST集中不会出现重复符号 16 */ 17 char*** GrammerRule; 18 19 /* 20 * 初始化文法序列 21 */ 22 void InitizationGrammerRule() 23 { 24 // 分配表头空间 25 GrammerRule = (char***)malloc(sizeof(int) * 128); 26 memset(GrammerRule, '\0', sizeof(int) * 128); 27 // 分配文法空间并写入产生式 28 // G -> E 29 GrammerRule['G'] = (char**)malloc(sizeof(int) * 2); 30 GrammerRule['G'][0] = (char*)malloc(2); 31 memcpy(GrammerRule['G'][0], "E\0", 2); // E 32 GrammerRule['G'][1] = NULL; 33 // E -> T F 34 GrammerRule['E'] = (char**)malloc(sizeof(int) * 2); 35 GrammerRule['E'][0] = (char*)malloc(3); 36 memcpy(GrammerRule['E'][0], "TF\0", 3); // T F 37 GrammerRule['E'][1] = NULL; 38 // F -> '+' T F | '-' T F | e 39 GrammerRule['F'] = (char**)malloc(sizeof(int) * 4); 40 GrammerRule['F'][0] = (char*)malloc(4); 41 memcpy(GrammerRule['F'][0], "+TF\0", 4); // '+' T F 42 GrammerRule['F'][1] = (char*)malloc(4); 43 memcpy(GrammerRule['F'][1], "-TF\0", 4); // '-' T F 44 GrammerRule['F'][2] = (char*)malloc(1); 45 memcpy(GrammerRule['F'][2], "\0", 1); // e (该产生式存在但是为空) 46 GrammerRule['F'][3] = NULL; 47 // T -> A U 48 GrammerRule['T'] = (char**)malloc(sizeof(int) * 2); 49 GrammerRule['T'][0] = (char*)malloc(3); 50 memcpy(GrammerRule['T'][0], "AU\0", 3); // A U 51 GrammerRule['T'][1] = NULL; 52 // U -> '*' A U | '/' A U | e 53 GrammerRule['U'] = (char**)malloc(sizeof(int) * 4); 54 GrammerRule['U'][0] = (char*)malloc(4); 55 memcpy(GrammerRule['U'][0], "*AU\0", 4); // '*' A U 56 GrammerRule['U'][1] = (char*)malloc(4); 57 memcpy(GrammerRule['U'][1], "/AU\0", 4); // '/' A U 58 GrammerRule['U'][2] = (char*)malloc(1); 59 memcpy(GrammerRule['U'][2], "\0", 1); // e (该产生式存在但是为空) 60 GrammerRule['U'][3] = NULL; 61 // A -> '(' E ')' | d | n 62 GrammerRule['A'] = (char**)malloc(sizeof(int) * 4); 63 GrammerRule['A'][0] = (char*)malloc(4); 64 memcpy(GrammerRule['A'][0], "(E)\0", 4); // '(' E ')' 65 GrammerRule['A'][1] = (char*)malloc(2); 66 memcpy(GrammerRule['A'][1], "d\0", 2); // d 67 GrammerRule['A'][2] = (char*)malloc(2); 68 memcpy(GrammerRule['A'][2], "n\0", 2); // n 69 GrammerRule['A'][3] = NULL; 70 } 71 72 /* 73 * 取得终结符数量 74 */ 75 int GetTerminalCount() 76 { 77 int i, TerminalCount = 0; 78 for (i = 0; i < 128; i++) 79 { 80 if (GrammerRule[i] != NULL) 81 { 82 int k = 0; 83 while (GrammerRule[i][k] != NULL) 84 { 85 int n = 0; 86 while (GrammerRule[i][k][n] != '\0') 87 { 88 char c = GrammerRule[i][k][n]; 89 if (c < 'A' || c > 'Z') 90 { 91 TerminalCount++; 92 } 93 n++; 94 } 95 k++; 96 } 97 } 98 } 99 return TerminalCount; 100 } 101 102 /* 103 * 递归取得 FIRST 集 104 * Token : char 需要打印的符号 105 * FIRST : char* FIRST集 106 * Ptr : int* FIRST集的位置指针 107 */ 108 void GetFIRST(char Token, char *FIRST, int *Ptr) 109 { 110 if (Token >= 'A' && Token <= 'Z' && GrammerRule[Token] != NULL) 111 { 112 int i = 0; 113 while (GrammerRule[Token][i] != NULL) 114 { 115 GetFIRST(GrammerRule[Token][i++][0], FIRST, Ptr); 116 } 117 } 118 else if (Token < 'A' || Token > 'Z') 119 { 120 FIRST[*Ptr] = Token; 121 *Ptr = *Ptr + 1; 122 } 123 } 124 125 /* 126 * 添加符号到 FOLLOW 集 127 * FOLLOW : char* FOLLOW集 128 * Ptr : int* FOLLOW集的位置指针 129 * NewItem : char 将加入的符号 130 */ 131 void AddFOLLOWItem(char *FOLLOW, int *Ptr, char NewItem) 132 { 133 int i = 0; 134 for (; i < *Ptr; i++) 135 { 136 if (FOLLOW[i] == NewItem) 137 { 138 return ; 139 } 140 } 141 FOLLOW[*Ptr] = NewItem; 142 *Ptr = *Ptr + 1; 143 } 144 145 /* 146 * 取得 FOLLOW 集 147 * Unterminal : char 需要打印的非终结符 148 * FOLLOW : char* FOLLOW集 149 * Ptr : int* FOLLOW集的位置指针 150 * TerminalCount : int 终结符数量 151 */ 152 void GetFOLLOW(char Unterminal, char *FOLLOW, int *Ptr, int TerminalCount) 153 { 154 int RuleIndex, ExprIndex, TokenIndex; 155 // 开始遍历整个文法 156 for (RuleIndex = 0; RuleIndex < 128; RuleIndex++) 157 { 158 if (GrammerRule[RuleIndex] == NULL) 159 { 160 continue; 161 } 162 // 搜索整个文法找到指定的非终结符 163 for (ExprIndex = 0; GrammerRule[RuleIndex][ExprIndex] != 0; ExprIndex++) 164 { 165 for (TokenIndex = 0; GrammerRule[RuleIndex][ExprIndex][TokenIndex] != '\0'; TokenIndex++) 166 { 167 if (GrammerRule[RuleIndex][ExprIndex][TokenIndex] == Unterminal) 168 { 169 char nc = GrammerRule[RuleIndex][ExprIndex][TokenIndex + 1]; 170 if (nc == '\0' && RuleIndex != Unterminal) // 情形三:反复计算:将FOLLOW(P)加入FOLLOW(U) 171 { 172 GetFOLLOW((char)RuleIndex, FOLLOW, Ptr, TerminalCount); 173 } 174 else if (nc >= 'A' && nc <= 'Z') // 情形二:间接计算:将FIRST(P)加入FOLLOW(U) 175 { 176 char *FIRST = (char*)malloc(TerminalCount + 1); 177 memset(FIRST, '\0', TerminalCount + 1); 178 int FIRSTPtr = 0, InsertPtr; 179 GetFIRST(nc, FIRST, &FIRSTPtr); 180 for (InsertPtr = 0; InsertPtr < FIRSTPtr; InsertPtr++) 181 { 182 if (FIRST[InsertPtr] != '\0') 183 { 184 AddFOLLOWItem(FOLLOW, Ptr, FIRST[InsertPtr]); 185 } 186 else // 对于 P->... U B,FOLLOW ← FIRST(B) - <e> + FOLLOW(P) 187 { 188 GetFOLLOW((char)RuleIndex, FOLLOW, Ptr, TerminalCount); 189 } 190 } 191 } 192 else if (nc != '\0') // 情形一:直接计算:将终结符加入FOLLOW(U) 193 { 194 AddFOLLOWItem(FOLLOW, Ptr, nc); 195 } 196 } 197 } 198 } 199 } 200 } 201 202 /* 203 * 打印指定非终结符的 FOLLOW 集 204 * Unterminal : char 需要打印的非终结符 205 * TerminalCount : int 终结符数量 206 */ 207 void PrintUnterminalFOLLOW(char Unterminal, int TerminalCount) 208 { 209 char *FOLLOW = (char*)malloc(TerminalCount + 1); 210 memset(FOLLOW, '\0', TerminalCount + 1); 211 int Ptr = 0, i; 212 FOLLOW[Ptr++] = '\377'; // 初始化第一个符号为 EOF 213 GetFOLLOW(Unterminal, FOLLOW, &Ptr, TerminalCount); 214 printf("FOLLOW(%c): ", Unterminal); 215 for (i = 0; i < Ptr; i++) 216 { 217 if (FOLLOW[i] == '\377') 218 { 219 printf("<eof> "); 220 } 221 else 222 { 223 printf("%c ", FOLLOW[i]); 224 } 225 } 226 printf("\n"); 227 } 228 229 int main(int argc, char **argv) 230 { 231 InitizationGrammerRule(); // 初始化文法 232 int TerminalCount = GetTerminalCount(); 233 PrintUnterminalFOLLOW('E', TerminalCount); 234 PrintUnterminalFOLLOW('F', TerminalCount); 235 PrintUnterminalFOLLOW('T', TerminalCount); 236 PrintUnterminalFOLLOW('U', TerminalCount); 237 PrintUnterminalFOLLOW('A', TerminalCount); 238 return 0; 239 }