1 /* 2 * 该程序用于计算某个非终结符的 FIRST 集合 3 * RexfieldVon 4 * 2013年6月29日19:53:45 5 * 2013年7月3日22:01:57 修改 GetFIRST 例程以简化驱动例程以及自身结构 6 */ 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 /* 三级指针 12 * 第一级指向整个产生式组 13 * 第二级指向单个产生式 14 * 第三级指向产生式符号单元 15 * 约定:所有的大写字母为非终结符 16 * 假设:无左递归、FIRST集中不会出现重复符号 17 */ 18 char*** GrammerRule; 19 20 /* 21 * 初始化文法序列 22 */ 23 void InitizationGrammerRule() 24 { 25 // 分配表头空间 26 GrammerRule = (char***)malloc(sizeof(int) * 128); 27 memset(GrammerRule, '\0', sizeof(int) * 128); 28 // 分配文法空间并写入产生式 29 // G -> E 30 GrammerRule['G'] = (char**)malloc(sizeof(int) * 2); 31 GrammerRule['G'][0] = (char*)malloc(2); 32 memcpy(GrammerRule['G'][0], "E\0", 2); // E 33 GrammerRule['G'][1] = NULL; 34 // E -> T F 35 GrammerRule['E'] = (char**)malloc(sizeof(int) * 2); 36 GrammerRule['E'][0] = (char*)malloc(3); 37 memcpy(GrammerRule['E'][0], "TF\0", 3); // T F 38 GrammerRule['E'][1] = NULL; 39 // F -> '+' T F | '-' T F | e 40 GrammerRule['F'] = (char**)malloc(sizeof(int) * 4); 41 GrammerRule['F'][0] = (char*)malloc(4); 42 memcpy(GrammerRule['F'][0], "+TF\0", 4); // '+' T F 43 GrammerRule['F'][1] = (char*)malloc(4); 44 memcpy(GrammerRule['F'][1], "-TF\0", 4); // '-' T F 45 GrammerRule['F'][2] = (char*)malloc(1); 46 memcpy(GrammerRule['F'][2], "\0", 1); // e (该产生式存在但是为空) 47 GrammerRule['F'][3] = NULL; 48 // T -> A U 49 GrammerRule['T'] = (char**)malloc(sizeof(int) * 2); 50 GrammerRule['T'][0] = (char*)malloc(3); 51 memcpy(GrammerRule['T'][0], "AU\0", 3); // A U 52 GrammerRule['T'][1] = NULL; 53 // U -> '*' A U | '/' A U | e 54 GrammerRule['U'] = (char**)malloc(sizeof(int) * 4); 55 GrammerRule['U'][0] = (char*)malloc(4); 56 memcpy(GrammerRule['U'][0], "*AU\0", 4); // '*' A U 57 GrammerRule['U'][1] = (char*)malloc(4); 58 memcpy(GrammerRule['U'][1], "/AU\0", 4); // '/' A U 59 GrammerRule['U'][2] = (char*)malloc(1); 60 memcpy(GrammerRule['U'][2], "\0", 1); // e (该产生式存在但是为空) 61 GrammerRule['U'][3] = NULL; 62 // A -> '(' E ')' | d | n 63 GrammerRule['A'] = (char**)malloc(sizeof(int) * 4); 64 GrammerRule['A'][0] = (char*)malloc(4); 65 memcpy(GrammerRule['A'][0], "(E)\0", 4); // '(' E ')' 66 GrammerRule['A'][1] = (char*)malloc(2); 67 memcpy(GrammerRule['A'][1], "d\0", 2); // d 68 GrammerRule['A'][2] = (char*)malloc(2); 69 memcpy(GrammerRule['A'][2], "n\0", 2); // n 70 GrammerRule['A'][3] = NULL; 71 } 72 73 int GetTerminalCount() 74 { 75 int i, TerminalCount = 0; 76 for (i = 0; i < 128; i++) 77 { 78 if (GrammerRule[i] != NULL) 79 { 80 int k = 0; 81 while (GrammerRule[i][k] != NULL) 82 { 83 int n = 0; 84 while (GrammerRule[i][k][n] != '\0') 85 { 86 char c = GrammerRule[i][k][n]; 87 if (c < 'A' || c > 'Z') 88 { 89 TerminalCount++; 90 } 91 n++; 92 } 93 k++; 94 } 95 } 96 } 97 return TerminalCount; 98 } 99 100 /* 101 * 递归取得 FIRST 集 102 * Token : char 需要打印的符号 103 * FIRST : char* FIRST集 104 * Ptr : int* FIRST集的位置指针 105 */ 106 void GetFIRST(char Token, char *FIRST, int *Ptr) 107 { 108 if (Token >= 'A' && Token <= 'Z' && GrammerRule[Token] != NULL) 109 { 110 int i = 0; 111 while (GrammerRule[Token][i] != NULL) 112 { 113 GetFIRST(GrammerRule[Token][i++][0], FIRST, Ptr); 114 } 115 } 116 else if (Token < 'A' || Token > 'Z') 117 { 118 FIRST[*Ptr] = Token; 119 *Ptr = *Ptr + 1; 120 } 121 } 122 123 /* 124 * 打印指定非终结符的 FIRST 集 125 * Token : char 需要打印的符号 126 * TerminalCount : int 终结符数量 127 */ 128 void PrintFIRST(char Token, int TerminalCount) 129 { 130 char *FIRST = (char*)malloc(TerminalCount + 1); 131 memset(FIRST, '\0', TerminalCount + 1); 132 int Ptr = 0, i; 133 GetFIRST(Token, FIRST, &Ptr); 134 printf("FIRST(%c): ", Token); 135 for (i = 0; i < Ptr; i++) 136 { 137 if (FIRST[i] == '\0') 138 { 139 printf("<e> "); 140 } 141 else 142 { 143 printf("%c ", FIRST[i]); 144 } 145 } 146 printf("\n"); 147 } 148 149 int main(int argc, char **argv) 150 { 151 InitizationGrammerRule(); // 初始化文法 152 int TerminalCount = GetTerminalCount(); 153 printf("Terminal Symbol Count: %d\n", TerminalCount); 154 PrintFIRST('E', TerminalCount); 155 PrintFIRST('F', TerminalCount); 156 PrintFIRST('T', TerminalCount); 157 PrintFIRST('U', TerminalCount); 158 PrintFIRST('A', TerminalCount); 159 return 0; 160 }