1. /*
  2. * 该程序用于计算某个非终结符的 FIRST+ 集合
  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) * );
  26. memset(GrammerRule, '\0', sizeof(int) * );
  27. // 分配文法空间并写入产生式
  28. // G -> E
  29. GrammerRule['G'] = (char**)malloc(sizeof(int) * );
  30. GrammerRule['G'][] = (char*)malloc();
  31. memcpy(GrammerRule['G'][], "E\0", ); // E
  32. GrammerRule['G'][] = NULL;
  33. // E -> T F
  34. GrammerRule['E'] = (char**)malloc(sizeof(int) * );
  35. GrammerRule['E'][] = (char*)malloc();
  36. memcpy(GrammerRule['E'][], "TF\0", ); // T F
  37. GrammerRule['E'][] = NULL;
  38. // F -> '+' T F | '-' T F | e
  39. GrammerRule['F'] = (char**)malloc(sizeof(int) * );
  40. GrammerRule['F'][] = (char*)malloc();
  41. memcpy(GrammerRule['F'][], "+TF\0", ); // '+' T F
  42. GrammerRule['F'][] = (char*)malloc();
  43. memcpy(GrammerRule['F'][], "-TF\0", ); // '-' T F
  44. GrammerRule['F'][] = (char*)malloc();
  45. memcpy(GrammerRule['F'][], "\0", ); // e (该产生式存在但是为空)
  46. GrammerRule['F'][] = NULL;
  47. // T -> A U
  48. GrammerRule['T'] = (char**)malloc(sizeof(int) * );
  49. GrammerRule['T'][] = (char*)malloc();
  50. memcpy(GrammerRule['T'][], "AU\0", ); // A U
  51. GrammerRule['T'][] = NULL;
  52. // U -> '*' A U | '/' A U | e
  53. GrammerRule['U'] = (char**)malloc(sizeof(int) * );
  54. GrammerRule['U'][] = (char*)malloc();
  55. memcpy(GrammerRule['U'][], "*AU\0", ); // '*' A U
  56. GrammerRule['U'][] = (char*)malloc();
  57. memcpy(GrammerRule['U'][], "/AU\0", ); // '/' A U
  58. GrammerRule['U'][] = (char*)malloc();
  59. memcpy(GrammerRule['U'][], "\0", ); // e (该产生式存在但是为空)
  60. GrammerRule['U'][] = NULL;
  61. // A -> '(' E ')' | d | n
  62. GrammerRule['A'] = (char**)malloc(sizeof(int) * );
  63. GrammerRule['A'][] = (char*)malloc();
  64. memcpy(GrammerRule['A'][], "(E)\0", ); // '(' E ')'
  65. GrammerRule['A'][] = (char*)malloc();
  66. memcpy(GrammerRule['A'][], "d\0", ); // d
  67. GrammerRule['A'][] = (char*)malloc();
  68. memcpy(GrammerRule['A'][], "n\0", ); // n
  69. GrammerRule['A'][] = NULL;
  70. }
  71.  
  72. /*
  73. * 取得终结符数量
  74. */
  75. int GetTerminalCount()
  76. {
  77. int i, TerminalCount = ;
  78. for (i = ; i < ; i++)
  79. {
  80. if (GrammerRule[i] != NULL)
  81. {
  82. int k = ;
  83. while (GrammerRule[i][k] != NULL)
  84. {
  85. int n = ;
  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 = ;
  113. while (GrammerRule[Token][i] != NULL)
  114. {
  115. GetFIRST(GrammerRule[Token][i++][], FIRST, Ptr);
  116. }
  117. }
  118. else if (Token < 'A' || Token > 'Z')
  119. {
  120. FIRST[*Ptr] = Token;
  121. *Ptr = *Ptr + ;
  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 = ;
  134. for (; i < *Ptr; i++)
  135. {
  136. if (FOLLOW[i] == NewItem)
  137. {
  138. return ;
  139. }
  140. }
  141. FOLLOW[*Ptr] = NewItem;
  142. *Ptr = *Ptr + ;
  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 = ; RuleIndex < ; RuleIndex++)
  157. {
  158. if (GrammerRule[RuleIndex] == NULL)
  159. {
  160. continue;
  161. }
  162. // 搜索整个文法找到指定的非终结符
  163. for (ExprIndex = ; GrammerRule[RuleIndex][ExprIndex] != ; ExprIndex++)
  164. {
  165. for (TokenIndex = ; GrammerRule[RuleIndex][ExprIndex][TokenIndex] != '\0'; TokenIndex++)
  166. {
  167. if (GrammerRule[RuleIndex][ExprIndex][TokenIndex] == Unterminal)
  168. {
  169. char nc = GrammerRule[RuleIndex][ExprIndex][TokenIndex + ];
  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 + );
  177. memset(FIRST, '\0', TerminalCount + );
  178. int FIRSTPtr = , InsertPtr;
  179. GetFIRST(nc, FIRST, &FIRSTPtr);
  180. for (InsertPtr = ; 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. void GetFIRSTPlus(char Unterminal, int Index, char *FIRSTPlus, int *Ptr, int TerminalCount)
  203. {
  204. if (GrammerRule[Unterminal][Index] != NULL)
  205. {
  206. GetFIRST(GrammerRule[Unterminal][Index][], FIRSTPlus, Ptr);
  207. int i = ;
  208. while (i < *Ptr)
  209. {
  210. if (FIRSTPlus[i++] == '\0')
  211. {
  212. FIRSTPlus[*Ptr] = '\377';
  213. *Ptr = *Ptr + ;
  214. GetFOLLOW(Unterminal, FIRSTPlus, Ptr, TerminalCount);
  215. break;
  216. }
  217. }
  218. }
  219. }
  220.  
  221. /*
  222. * 打印指定非终结符的 FIRST+ 集
  223. * Unterminal : char 需要打印的非终结符
  224. * TerminalCount : int 终结符数量
  225. */
  226. void PrintUnterminalFIRSTPlus(char Unterminal, int TerminalCount)
  227. {
  228. char *FIRSTPlus = (char*)malloc(TerminalCount + );
  229. memset(FIRSTPlus, '\0', TerminalCount + );
  230. int Ptr, Index = , i;
  231. for (; GrammerRule[Unterminal][Index] != NULL; Index++)
  232. {
  233. Ptr = ;
  234. GetFIRSTPlus(Unterminal, Index, FIRSTPlus, &Ptr, TerminalCount);
  235. printf("FIRST+(%c, %c): ", Unterminal, GrammerRule[Unterminal][Index][]);
  236. for (i = ; i < Ptr; i++)
  237. {
  238. if (FIRSTPlus[i] == '\377')
  239. {
  240. printf("<eof> ");
  241. }
  242. else if (FIRSTPlus[i] == '\0')
  243. {
  244. printf("<e> ");
  245. }
  246. else
  247. {
  248. printf("%c ", FIRSTPlus[i]);
  249. }
  250. }
  251. printf("\n");
  252. }
  253. }
  254.  
  255. int main(int argc, char **argv)
  256. {
  257. InitizationGrammerRule(); // 初始化文法
  258. int TerminalCount = GetTerminalCount();
  259. PrintUnterminalFIRSTPlus('E', TerminalCount);
  260. PrintUnterminalFIRSTPlus('F', TerminalCount);
  261. PrintUnterminalFIRSTPlus('T', TerminalCount);
  262. PrintUnterminalFIRSTPlus('U', TerminalCount);
  263. PrintUnterminalFIRSTPlus('A', TerminalCount);
  264. return ;
  265. }

简单的FIRST+集演示程序的更多相关文章

  1. 简单的FOLLOW集演示程序

    /* * 该程序用于计算某个非终结符的 FOLLOW 集合 * RexfieldVon * 2013年6月30日16:02:47 */ #include <stdio.h> #includ ...

  2. 简单的FIRST集演示程序

    /* * 该程序用于计算某个非终结符的 FIRST 集合 * RexfieldVon * 2013年6月29日19:53:45 * 2013年7月3日22:01:57 修改 GetFIRST 例程以简 ...

  3. POJ 2524 (简单并查集) Ubiquitous Religions

    题意:有编号为1到n的学生,然后有m组调查,每组调查中有a和b,表示该两个学生有同样的宗教信仰,问最多有多少种不同的宗教信仰 简单并查集 //#define LOCAL #include <io ...

  4. poj1611 简单并查集

    The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 32781   Accepted: 15902 De ...

  5. 1213 How Many Tables(简单并查集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1213 简单并查集,统计单独成树的数量. 代码: #include <stdio.h> #i ...

  6. 【简单并查集】Farm Irrigation

    Farm Irrigation Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Tot ...

  7. RocketMQ 简单梳理 及 集群部署笔记【转】

    一.RocketMQ 基础知识介绍Apache RocketMQ是阿里开源的一款高性能.高吞吐量.队列模型的消息中间件的分布式消息中间件. 上图是一个典型的消息中间件收发消息的模型,RocketMQ也 ...

  8. 搭建简单的hadoop集群(译文)

    本文翻译翻译自http://hadoop.apache.org/docs/r2.8.0/hadoop-project-dist/hadoop-common/ClusterSetup.html 具体的实 ...

  9. ACM_“打老虎”的背后(简单并查集)

    “打老虎”的背后 Time Limit: 2000/1000ms (Java/Others) Problem Description: “习大大”自担任国家主席以来大力反腐倡廉,各地打击贪腐力度也逐步 ...

随机推荐

  1. 浅谈Android系统的图标设计规范

    http://homepage.yesky.com/89/11620089.shtml 目前移动平台的竞争日益激烈,友好的用户界面可以帮助提高用户体验满意度,图标Icon是用户界面中一个重要的组成部分 ...

  2. HTTP could not register URL http://+:8000/.... Your process does not have access rights to this namespace

    windows 7, Visual Studio 2013 在托管 Windows 服务中承载 WCF 服务时报错: HTTP could not register URL http://+:8000 ...

  3. c#wiform中KeyDown事件

    当首次按下键盘上某个键时发生事件. 例如 private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Ke ...

  4. 实现Bootstrap Carousel Fade Transition 淡入淡出效果

    html代码: <div id="carousel" class="carousel slide carousel-fade" data-ride=&qu ...

  5. mysql数据库中编码问题(续)

    其实之前的数据库中文乱码问题并没有彻底的解决,虽然在网页上显示正常,但是在数据库中却是乱码,虽然用户看起来没问题,但是自己就遭罪了,而且也是个极大的问题 究其原因,是没注意到一点,就是数据库中表的结构 ...

  6. tbody 滚动条

    ARRIVALS TO BRISTOL - ENGLAND FLIGHT CODE FROM STA ETA Notes T3 4264 ISLE OF MAN 11:40 11:42 LANDED ...

  7. 关于alarm函数

    #include<unistd.h> #include<signal.h> void handler() { printf("Hello\n"); sign ...

  8. [转载]ecshop 实现订单导出功能 指定订单导出 EXCEL 数据文件

    当下很多功能都觉得理所当然,但是实际作为2012年停更的ECSHOP来说,很多功能其实都是缺少的,好比今天的要说的功能 订单导出 这个功能对于现在的产品设计来说,应该属于一个比较常规的功能,但是ECS ...

  9. Tomcat环境变量的配置

    Tomcat web服务器 支持全部JSP以及Servlet规范 主要作用 是提供了一个可以让Jsp和Servlet运行的平台 tomcat环境变量设置 CATALINA_HOME : D:\bran ...

  10. Drupal7安装完整教程

    Drupal7 史前准备工作(安装 AppServ)AppServ 是 PHP 网页架站工具组合包,作者将一些网络上免费的架站资源重新包装成单一的安装程序,以方便初学者快速完成架站,AppServ 所 ...