简单的闭包运算(Closure)演示程序
- /*
- * 该程序用于计算某个产生式的闭包
- * RexfieldVon
- * 2013年8月9日16:01:38
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #ifndef bool
- # define bool char
- #endif
- #ifndef true
- # define true
- #endif
- #ifndef false
- # define false
- #endif
- struct Collection
- {
- char LeftUnterminal; // 左非终结符
- char *Expression; // 产生式
- char PreviewSymbol; // 前瞻符号
- bool Processed; // 是否被处理
- struct Collection *next;
- };
- /* 三级指针
- * 第一级指向整个产生式组
- * 第二级指向单个产生式
- * 第三级指向产生式符号单元
- * 约定:①所有的大写字母为非终结符②所有小写字母为终结符③'\377'为eof④'\0'为ε⑤'\376'为占位符·
- */
- char*** GrammerRule;
- /*
- * 文法书写约定:
- * 每个字符串表示一个单独的产生式
- * 第一个字符为产生式左边的非终结符,由初始化引擎进行产生式归并
- * 整个文法以 null 结束
- */
- char *Grammer[] =
- {
- "GL",
- "LLP", "LP",
- "P(P)", "P()",
- "\0"
- };
- /*
- * 初始化文法序列
- */
- void InitizationGrammerRule()
- {
- // 分配表头空间
- GrammerRule = (char***)malloc(sizeof(int) * );
- memset(GrammerRule, '\0', sizeof(int) * );
- // 扫描整个文法记录每个非终结符产生式的个数
- int UnterminalOp[], index;
- char Unterminal;
- memset(UnterminalOp, '\0', * );
- for (index = ; (Unterminal = Grammer[index][]) != '\0'; index++)
- {
- UnterminalOp[Unterminal]++;
- }
- // 写入产生式
- for (index = ; (Unterminal = Grammer[index][]) != '\0'; index++)
- {
- if(GrammerRule[Unterminal] == NULL)
- {
- GrammerRule[Unterminal] = (char**)malloc(sizeof(int) * (UnterminalOp[Unterminal] + ));
- memset(GrammerRule[Unterminal], '\0', sizeof(int) * (UnterminalOp[Unterminal] + ));
- }
- // 找到空位
- int blank = ;
- while (GrammerRule[Unterminal][blank] != '\0') {blank++;}
- GrammerRule[Unterminal][blank] = &Grammer[index][];
- }
- }
- /*
- * 取得终结符数量
- * return 终结符的数量
- */
- int GetTerminalCount()
- {
- int i, TerminalCount = ;
- for (i = ; i < ; i++)
- {
- if (GrammerRule[i] != NULL)
- {
- int k = ;
- while (GrammerRule[i][k] != NULL)
- {
- int n = ;
- while (GrammerRule[i][k][n] != '\0')
- {
- char c = GrammerRule[i][k][n];
- if (c < 'A' || c > 'Z')
- {
- TerminalCount++;
- }
- n++;
- }
- k++;
- }
- }
- }
- return TerminalCount;
- }
- /*
- * 递归取得 FIRST 集
- * Token : char 需要打印的符号
- * FIRST : char* FIRST集
- * Ptr : int* FIRST集的位置指针
- */
- void GetFIRST(char Token, char *FIRST, int *Ptr)
- {
- if (Token >= 'A' && Token <= 'Z' && GrammerRule[Token] != NULL)
- {
- int i = ;
- while (GrammerRule[Token][i] != NULL)
- {
- GetFIRST(GrammerRule[Token][i++][], FIRST, Ptr);
- }
- }
- else if (Token < 'A' || Token > 'Z')
- {
- FIRST[*Ptr] = Token;
- *Ptr = *Ptr + ;
- }
- }
- /*
- * 打印 LR(1) 项
- * Item : struct Collection* 需要打印的项
- */
- void PrintItem(struct Collection *Item)
- {
- printf("[%c ->", Item->LeftUnterminal);
- int i = ;
- for(; Item->Expression[i] != '\0'; i++)
- {
- printf(" ");
- switch (Item->Expression[i])
- {
- case '\377':
- printf("<eof>");
- break;
- case '\376':
- printf("<@>");
- break;
- default:
- printf("%c", Item->Expression[i]);
- break;
- }
- }
- if (Item->PreviewSymbol == '\377')
- {
- printf(", <eof>]\n");
- }
- else
- {
- printf(", %c]\n", Item->PreviewSymbol);
- }
- }
- /*
- * 添加项到集合
- * S : struct Collection* 项集
- * LeftUnterminal : char 左非终结符
- * Expression : char* 产生式
- * PreviewSymbol : char 前瞻符号
- */
- void AddItem(struct Collection *S, char LeftUnterminal, char *Expression, char PreviewSymbol)
- {
- static struct Collection *Tail = NULL;
- if (Tail == NULL) {Tail = S;}
- while (Tail->next != NULL) {Tail = Tail->next;}
- // 检查是否重复
- struct Collection *SPtr = S;
- for (; SPtr != NULL; SPtr = SPtr->next)
- {
- if (SPtr->LeftUnterminal == LeftUnterminal &&
- SPtr->PreviewSymbol == PreviewSymbol &&
- strcmp(SPtr->Expression, Expression) == )
- {
- return;
- }
- }
- struct Collection *NewItem = (struct Collection*)malloc(sizeof(struct Collection));
- NewItem->LeftUnterminal = LeftUnterminal;
- NewItem->Expression = strdup(Expression);
- NewItem->PreviewSymbol = PreviewSymbol;
- NewItem->next = NULL;
- NewItem->Processed = false;
- Tail->next = NewItem;
- Tail = Tail->next;
- }
- /*
- * 闭包运算
- * S : struct Collection* 项集
- * TerminalCount : int 终结符个数
- */
- void Closure(struct Collection *S, int TerminalCount)
- {
- bool CollectChanged;
- struct Collection *Ptr = S;
- do // while (S is still changing)
- {
- CollectChanged = false;
- while (Ptr != NULL) // for each item [A->β·Cζ,α]∈S
- {
- PrintItem(Ptr);
- char *Placeholder = strchr(Ptr->Expression, '\376');
- if (Placeholder != NULL && *(Placeholder + ) != '\0') // 占位符不能在产生式尾
- {
- char Unterminal = *(Placeholder + );
- if (Unterminal >= 'A' && Unterminal <= 'Z')
- {
- int ProductionIndex;
- for (ProductionIndex = ; GrammerRule[Unterminal][ProductionIndex] != NULL; ProductionIndex++) // for each production C->γ∈P
- {
- char *FIRST = (char*)malloc(TerminalCount + ), FirstSymbol = *(Placeholder + );
- FirstSymbol = (FirstSymbol != '\0')? FirstSymbol : Ptr->PreviewSymbol;
- memset(FIRST, '\0', TerminalCount + );
- int FIRSTCount = , i;
- GetFIRST(FirstSymbol, FIRST, &FIRSTCount);
- for (i = ; i < FIRSTCount; i++) // for each b∈FIRST(ζα)
- {
- if (FIRST[i] != '\0') // S <- S∪{[C->·γ,b]}
- {
- char *Expr = (char*)malloc();
- Expr[] = '\376';
- Expr[] = '\0';
- Expr = strcat(Expr, GrammerRule[Unterminal][ProductionIndex]);
- AddItem(S, Unterminal, Expr, FIRST[i]);
- CollectChanged = true;
- }
- }
- }
- }
- }
- Ptr = Ptr->next;
- }
- }
- while (CollectChanged == true);
- }
- int main(int argc, char **argv)
- {
- InitizationGrammerRule(); // 初始化文法
- int TerminalCount = GetTerminalCount();
- struct Collection *S = (struct Collection*)malloc(sizeof(struct Collection));
- S->LeftUnterminal = 'G';
- S->Expression = "\376L";
- S->PreviewSymbol = '\377';
- S->next = NULL;
- S->Processed = false;
- Closure(S, TerminalCount);
- return ;
- }
简单的闭包运算(Closure)演示程序的更多相关文章
- 简单的Goto运算演示程序
/* * 该程序用于计算某个项集的Goto集 * RexfieldVon * 2013年8月11日2:34:50 */ #include <stdio.h> #include <st ...
- 简单的FIRST+集演示程序
/* * 该程序用于计算某个非终结符的 FIRST+ 集合 * RexfieldVon * 2013年6月30日16:02:47 */ #include <stdio.h> #includ ...
- 简单的FOLLOW集演示程序
/* * 该程序用于计算某个非终结符的 FOLLOW 集合 * RexfieldVon * 2013年6月30日16:02:47 */ #include <stdio.h> #includ ...
- 简单的FIRST集演示程序
/* * 该程序用于计算某个非终结符的 FIRST 集合 * RexfieldVon * 2013年6月29日19:53:45 * 2013年7月3日22:01:57 修改 GetFIRST 例程以简 ...
- Lua 5.3 迭代器的简单示例
Lua 5.3 迭代器的简单示例 创建"closure"模式的"iterator" function allowrds() local line = io.re ...
- LR(1)语法分析器生成器(生成Action表和Goto表)java实现(二)
本来这次想好好写一下博客的...结果耐心有限,又想着烂尾总比断更好些.于是还是把后续代码贴上.不过后续代码是继续贴在BNF容器里面的...可能会显得有些臃肿.但目前管不了那么多了.先贴上来吧hhh.说 ...
- TJI读书笔记14-闭包与回调
TJI读书笔记14-闭包与回调 闭包与回调 为什么要使用内部类?内部类继承自某个类或者实现某个接口,内部类的代码可以操作外嵌类的对象. 这不是使用内部类的理由. 那么为什么使用内部类呢? 我觉得如 ...
- r.js 配置文件 build.js 不完整注释
-----------------------------------------------------------------------r.js 配置文件 example.build.js ...
- 简洁 Abstract Factory模式(3.1)
镇楼 在某些书中使用了二维图说明抽象工厂模式.非常好,可是yqj2065不喜欢他们的产品族/产品等级,改成品牌/产品类型. 抽象工厂模式(abstract factory pattern)较工厂方法模 ...
随机推荐
- String or binary data would be truncated. The statement has been terminated.
常见的情况为:插入的值大于字段定义的最大长度. String or binary data would be truncated. The statement has been terminated
- C# DataTable去除重复,极其简便、简单
其中sourceDT是获取到的一个DataTable类型的集合对象 去重复使用方式: 实例化一个DataView对象 假设为dv,直接dv.ToTable()即可,ToTable中可为(true,&q ...
- linux创建用户
创建用户 sudo adduser xxx 删除用户 sudo userdel xxx 删除用户和目录 sudo userdel -r xxx
- 非常不错的ASP操作数据库类,支持多数据库MSSQL,ACCESS,ORACLE,MYSQL等
可同时操作多个不同类型的数据库. 完全不用考虑数据类型的差别,再也不用想字符型字段加不加单引号. 调用非常简单,对数据库的主要操作一般只需要一行代码. 支持mssql事务回滚. 可自动生成和输出sql ...
- iOS 百度地图监听地图状态
百度地图提供了地图状态的对象BMKMapStatus ///此类表示地图状态信息 @interface BMKMapStatus : NSObject { float _fLevel; // 缩放比例 ...
- 层模型--绝对定位(position:absolute)
如果想为元素设置层模型中的绝对定位,需要设置position:absolute(表示绝对定位),这条语句的作用将元素从文档流中拖出来,然后使用left.right.top.bottom属性相对于其最接 ...
- Linux 添加epel源
1.epel-release yum install epel-release 这样有些没办法通过yum 安装 可以这样安装(例如redis)
- 文字和表单(checkbox/radio)元素垂直对齐方法,兼容Firefox和IE。
这几天在做表单时总会碰到复选框(checkbox)和单选框(radio)与文字不对齐的问题,要不是checkbox上浮了,要不是文字上浮.在前端开发过程中,单(复)选框和它们后面的提示文字在不进行任何 ...
- Linux下ln链接命令详解
ln是linux中又一个非常重要命令,它的功能是为某一个文件在另外一个位置建立一个不同的链接,这个命令最常用的参数是-s,具体用法是:ln –s 源文件 目标文件. 当我们需要在不同的目录,用到相同的 ...
- WCF服务对象实例化基础
很多情况下,我们都需要控制wcf服务端对象的初始化方式,用来控制wcf实例在服务端的存活时间. Wcf框架提供了三种创建wcf实例的方式. WCF服务对象实例化基础 在普通的WCF请求和相应过程中,将 ...