简单的闭包运算(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)较工厂方法模 ...
随机推荐
- 为什么选择Typescript
上一节,我简单介绍了Typescript,并将Typescript和JavaScript进行了对比,有些网友提出了一些疑问,可能有些网友对于这个Typescript还不是特别的熟悉,这节,我做一些演示 ...
- weChat聊天发送图片带有小尖角的实现
weChat聊天发送图片带有小尖角的实现 1.#import <UIKit/UIKit.h>2.3.@interface JKShapeImage : UIView4.5.@propert ...
- javascript——闭包
<script type="text/javascript"> //什么是闭包: //是指语法域位于某个特定的区域,具有持续参照(读写)位于该区域内自身范围之外的执行域 ...
- jQuery--效果和遍历
七.jQuery效果 (1)jQuery隐藏和显示 //隐藏 $("#hide").click(function(){ $("p").hide(1000); } ...
- js文字向上滚动代码
js文字向上滚动代码 <style>.pczt_pingfen_jhxs_news1{ width:397px; background:#edfafd; padding-top:2px; ...
- 百度的一个Ajax跨域方法 JavaScript是没有域的限制
baidu的通行证处理都是在二级域名passport.baidu.com中处理的,但是baidu很多地方登录都好像是用ajax处理的,他是怎么做的呢?研究了一下,发现一个小技巧. 在http://zh ...
- SAE flask及其扩展 bug指南
1. ImportError: No moudle named ext.bootstrap 导入依赖包失败 SAE会提供一种机制通过导入virtualenv.bundle来解决 此处有坑:官网文档中说 ...
- uboot环境变量分析
uboot的环境变量在程序的运行和调试过程中都发挥着比较重要的作用. 一.环境变量 可以理解为全局变量,但是他的生命周期比全局变量要长,当程序已经结束运行时,全局变量就会消亡,但是环境变量在下次上电运 ...
- MySQL 执行计划explain详解
MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但 ...
- [bug]Syntax error, unrecognized expression: input#ctl00$ContentPlaceHolder1$Pager_input
1.在ie10上浏览页面的时候,突然发现在使用Aspnetpager的页面会有一个bug. 2. 3.查了很多解决方案,最后将vs2013中, 将该勾取消,再次浏览,你会发现就正常了,虽然该功能很强大 ...