1. /*
  2. * 该程序用于计算某个产生式的闭包
  3. * RexfieldVon
  4. * 2013年8月9日16:01:38
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #ifndef bool
  11. # define bool char
  12. #endif
  13.  
  14. #ifndef true
  15. # define true
  16. #endif
  17.  
  18. #ifndef false
  19. # define false
  20. #endif
  21.  
  22. struct Collection
  23. {
  24. char LeftUnterminal; // 左非终结符
  25. char *Expression; // 产生式
  26. char PreviewSymbol; // 前瞻符号
  27. bool Processed; // 是否被处理
  28. struct Collection *next;
  29. };
  30. /* 三级指针
  31. * 第一级指向整个产生式组
  32. * 第二级指向单个产生式
  33. * 第三级指向产生式符号单元
  34. * 约定:①所有的大写字母为非终结符②所有小写字母为终结符③'\377'为eof④'\0'为ε⑤'\376'为占位符·
  35. */
  36. char*** GrammerRule;
  37. /*
  38. * 文法书写约定:
  39. * 每个字符串表示一个单独的产生式
  40. * 第一个字符为产生式左边的非终结符,由初始化引擎进行产生式归并
  41. * 整个文法以 null 结束
  42. */
  43. char *Grammer[] =
  44. {
  45. "GL",
  46. "LLP", "LP",
  47. "P(P)", "P()",
  48. "\0"
  49. };
  50. /*
  51. * 初始化文法序列
  52. */
  53. void InitizationGrammerRule()
  54. {
  55. // 分配表头空间
  56. GrammerRule = (char***)malloc(sizeof(int) * );
  57. memset(GrammerRule, '\0', sizeof(int) * );
  58. // 扫描整个文法记录每个非终结符产生式的个数
  59. int UnterminalOp[], index;
  60. char Unterminal;
  61. memset(UnterminalOp, '\0', * );
  62. for (index = ; (Unterminal = Grammer[index][]) != '\0'; index++)
  63. {
  64. UnterminalOp[Unterminal]++;
  65. }
  66. // 写入产生式
  67. for (index = ; (Unterminal = Grammer[index][]) != '\0'; index++)
  68. {
  69. if(GrammerRule[Unterminal] == NULL)
  70. {
  71. GrammerRule[Unterminal] = (char**)malloc(sizeof(int) * (UnterminalOp[Unterminal] + ));
  72. memset(GrammerRule[Unterminal], '\0', sizeof(int) * (UnterminalOp[Unterminal] + ));
  73. }
  74. // 找到空位
  75. int blank = ;
  76. while (GrammerRule[Unterminal][blank] != '\0') {blank++;}
  77. GrammerRule[Unterminal][blank] = &Grammer[index][];
  78. }
  79. }
  80.  
  81. /*
  82. * 取得终结符数量
  83. * return 终结符的数量
  84. */
  85. int GetTerminalCount()
  86. {
  87. int i, TerminalCount = ;
  88. for (i = ; i < ; i++)
  89. {
  90. if (GrammerRule[i] != NULL)
  91. {
  92. int k = ;
  93. while (GrammerRule[i][k] != NULL)
  94. {
  95. int n = ;
  96. while (GrammerRule[i][k][n] != '\0')
  97. {
  98. char c = GrammerRule[i][k][n];
  99. if (c < 'A' || c > 'Z')
  100. {
  101. TerminalCount++;
  102. }
  103. n++;
  104. }
  105. k++;
  106. }
  107. }
  108. }
  109. return TerminalCount;
  110. }
  111.  
  112. /*
  113. * 递归取得 FIRST 集
  114. * Token : char 需要打印的符号
  115. * FIRST : char* FIRST集
  116. * Ptr : int* FIRST集的位置指针
  117. */
  118. void GetFIRST(char Token, char *FIRST, int *Ptr)
  119. {
  120. if (Token >= 'A' && Token <= 'Z' && GrammerRule[Token] != NULL)
  121. {
  122. int i = ;
  123. while (GrammerRule[Token][i] != NULL)
  124. {
  125. GetFIRST(GrammerRule[Token][i++][], FIRST, Ptr);
  126. }
  127. }
  128. else if (Token < 'A' || Token > 'Z')
  129. {
  130. FIRST[*Ptr] = Token;
  131. *Ptr = *Ptr + ;
  132. }
  133. }
  134.  
  135. /*
  136. * 打印 LR(1) 项
  137. * Item : struct Collection* 需要打印的项
  138. */
  139. void PrintItem(struct Collection *Item)
  140. {
  141. printf("[%c ->", Item->LeftUnterminal);
  142. int i = ;
  143. for(; Item->Expression[i] != '\0'; i++)
  144. {
  145. printf(" ");
  146. switch (Item->Expression[i])
  147. {
  148. case '\377':
  149. printf("<eof>");
  150. break;
  151. case '\376':
  152. printf("<@>");
  153. break;
  154. default:
  155. printf("%c", Item->Expression[i]);
  156. break;
  157. }
  158. }
  159. if (Item->PreviewSymbol == '\377')
  160. {
  161. printf(", <eof>]\n");
  162. }
  163. else
  164. {
  165. printf(", %c]\n", Item->PreviewSymbol);
  166. }
  167. }
  168.  
  169. /*
  170. * 添加项到集合
  171. * S : struct Collection* 项集
  172. * LeftUnterminal : char 左非终结符
  173. * Expression : char* 产生式
  174. * PreviewSymbol : char 前瞻符号
  175. */
  176. void AddItem(struct Collection *S, char LeftUnterminal, char *Expression, char PreviewSymbol)
  177. {
  178. static struct Collection *Tail = NULL;
  179. if (Tail == NULL) {Tail = S;}
  180. while (Tail->next != NULL) {Tail = Tail->next;}
  181. // 检查是否重复
  182. struct Collection *SPtr = S;
  183. for (; SPtr != NULL; SPtr = SPtr->next)
  184. {
  185. if (SPtr->LeftUnterminal == LeftUnterminal &&
  186. SPtr->PreviewSymbol == PreviewSymbol &&
  187. strcmp(SPtr->Expression, Expression) == )
  188. {
  189. return;
  190. }
  191. }
  192. struct Collection *NewItem = (struct Collection*)malloc(sizeof(struct Collection));
  193. NewItem->LeftUnterminal = LeftUnterminal;
  194. NewItem->Expression = strdup(Expression);
  195. NewItem->PreviewSymbol = PreviewSymbol;
  196. NewItem->next = NULL;
  197. NewItem->Processed = false;
  198. Tail->next = NewItem;
  199. Tail = Tail->next;
  200. }
  201.  
  202. /*
  203. * 闭包运算
  204. * S : struct Collection* 项集
  205. * TerminalCount : int 终结符个数
  206. */
  207. void Closure(struct Collection *S, int TerminalCount)
  208. {
  209. bool CollectChanged;
  210. struct Collection *Ptr = S;
  211. do // while (S is still changing)
  212. {
  213. CollectChanged = false;
  214. while (Ptr != NULL) // for each item [A->β·Cζ,α]∈S
  215. {
  216. PrintItem(Ptr);
  217. char *Placeholder = strchr(Ptr->Expression, '\376');
  218. if (Placeholder != NULL && *(Placeholder + ) != '\0') // 占位符不能在产生式尾
  219. {
  220. char Unterminal = *(Placeholder + );
  221. if (Unterminal >= 'A' && Unterminal <= 'Z')
  222. {
  223. int ProductionIndex;
  224. for (ProductionIndex = ; GrammerRule[Unterminal][ProductionIndex] != NULL; ProductionIndex++) // for each production C->γ∈P
  225. {
  226. char *FIRST = (char*)malloc(TerminalCount + ), FirstSymbol = *(Placeholder + );
  227. FirstSymbol = (FirstSymbol != '\0')? FirstSymbol : Ptr->PreviewSymbol;
  228. memset(FIRST, '\0', TerminalCount + );
  229. int FIRSTCount = , i;
  230. GetFIRST(FirstSymbol, FIRST, &FIRSTCount);
  231. for (i = ; i < FIRSTCount; i++) // for each b∈FIRST(ζα)
  232. {
  233. if (FIRST[i] != '\0') // S <- S∪{[C->·γ,b]}
  234. {
  235. char *Expr = (char*)malloc();
  236. Expr[] = '\376';
  237. Expr[] = '\0';
  238. Expr = strcat(Expr, GrammerRule[Unterminal][ProductionIndex]);
  239. AddItem(S, Unterminal, Expr, FIRST[i]);
  240. CollectChanged = true;
  241. }
  242. }
  243. }
  244. }
  245. }
  246. Ptr = Ptr->next;
  247. }
  248. }
  249. while (CollectChanged == true);
  250. }
  251.  
  252. int main(int argc, char **argv)
  253. {
  254. InitizationGrammerRule(); // 初始化文法
  255. int TerminalCount = GetTerminalCount();
  256. struct Collection *S = (struct Collection*)malloc(sizeof(struct Collection));
  257. S->LeftUnterminal = 'G';
  258. S->Expression = "\376L";
  259. S->PreviewSymbol = '\377';
  260. S->next = NULL;
  261. S->Processed = false;
  262. Closure(S, TerminalCount);
  263. return ;
  264. }

简单的闭包运算(Closure)演示程序的更多相关文章

  1. 简单的Goto运算演示程序

    /* * 该程序用于计算某个项集的Goto集 * RexfieldVon * 2013年8月11日2:34:50 */ #include <stdio.h> #include <st ...

  2. 简单的FIRST+集演示程序

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

  3. 简单的FOLLOW集演示程序

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

  4. 简单的FIRST集演示程序

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

  5. Lua 5.3 迭代器的简单示例

    Lua 5.3 迭代器的简单示例 创建"closure"模式的"iterator" function allowrds() local line = io.re ...

  6. LR(1)语法分析器生成器(生成Action表和Goto表)java实现(二)

    本来这次想好好写一下博客的...结果耐心有限,又想着烂尾总比断更好些.于是还是把后续代码贴上.不过后续代码是继续贴在BNF容器里面的...可能会显得有些臃肿.但目前管不了那么多了.先贴上来吧hhh.说 ...

  7. TJI读书笔记14-闭包与回调

      TJI读书笔记14-闭包与回调 闭包与回调 为什么要使用内部类?内部类继承自某个类或者实现某个接口,内部类的代码可以操作外嵌类的对象. 这不是使用内部类的理由. 那么为什么使用内部类呢? 我觉得如 ...

  8. r.js 配置文件 build.js 不完整注释

      -----------------------------------------------------------------------r.js 配置文件 example.build.js ...

  9. 简洁 Abstract Factory模式(3.1)

    镇楼 在某些书中使用了二维图说明抽象工厂模式.非常好,可是yqj2065不喜欢他们的产品族/产品等级,改成品牌/产品类型. 抽象工厂模式(abstract factory pattern)较工厂方法模 ...

随机推荐

  1. String or binary data would be truncated. The statement has been terminated.

    常见的情况为:插入的值大于字段定义的最大长度. String or binary data would be truncated. The statement has been terminated

  2. C# DataTable去除重复,极其简便、简单

    其中sourceDT是获取到的一个DataTable类型的集合对象 去重复使用方式: 实例化一个DataView对象 假设为dv,直接dv.ToTable()即可,ToTable中可为(true,&q ...

  3. linux创建用户

    创建用户   sudo adduser xxx 删除用户   sudo userdel xxx 删除用户和目录  sudo userdel -r xxx

  4. 非常不错的ASP操作数据库类,支持多数据库MSSQL,ACCESS,ORACLE,MYSQL等

    可同时操作多个不同类型的数据库. 完全不用考虑数据类型的差别,再也不用想字符型字段加不加单引号. 调用非常简单,对数据库的主要操作一般只需要一行代码. 支持mssql事务回滚. 可自动生成和输出sql ...

  5. iOS 百度地图监听地图状态

    百度地图提供了地图状态的对象BMKMapStatus ///此类表示地图状态信息 @interface BMKMapStatus : NSObject { float _fLevel; // 缩放比例 ...

  6. 层模型--绝对定位(position:absolute)

    如果想为元素设置层模型中的绝对定位,需要设置position:absolute(表示绝对定位),这条语句的作用将元素从文档流中拖出来,然后使用left.right.top.bottom属性相对于其最接 ...

  7. Linux 添加epel源

    1.epel-release yum install epel-release 这样有些没办法通过yum 安装  可以这样安装(例如redis)

  8. 文字和表单(checkbox/radio)元素垂直对齐方法,兼容Firefox和IE。

    这几天在做表单时总会碰到复选框(checkbox)和单选框(radio)与文字不对齐的问题,要不是checkbox上浮了,要不是文字上浮.在前端开发过程中,单(复)选框和它们后面的提示文字在不进行任何 ...

  9. Linux下ln链接命令详解

    ln是linux中又一个非常重要命令,它的功能是为某一个文件在另外一个位置建立一个不同的链接,这个命令最常用的参数是-s,具体用法是:ln –s 源文件 目标文件. 当我们需要在不同的目录,用到相同的 ...

  10. WCF服务对象实例化基础

    很多情况下,我们都需要控制wcf服务端对象的初始化方式,用来控制wcf实例在服务端的存活时间. Wcf框架提供了三种创建wcf实例的方式. WCF服务对象实例化基础 在普通的WCF请求和相应过程中,将 ...