/*
* 该程序用于计算某个项集的Goto集
* RexfieldVon
* 2013年8月11日2:34:50
*/
#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* 项集
* Tail : struct Collection* 尾部指针
* LeftUnterminal : char 左非终结符
* Expression : char* 产生式
* PreviewSymbol : char 前瞻符号
*/
void AddItem(struct Collection *S, struct Collection **Tail, char LeftUnterminal, char *Expression, char PreviewSymbol)
{
if (Tail == NULL) {Tail = (struct Collection **)malloc(sizeof(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, *Tail = S;
do // while (S is still changing)
{
CollectChanged = false;
while (Ptr != NULL) // for each item [A->β·Cζ,α]∈S
{
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, &Tail, Unterminal, Expr, FIRST[i]);
CollectChanged = true;
}
}
}
}
}
Ptr = Ptr->next;
}
}
while (CollectChanged == true);
} /*
* Goto 运算
* S : struct Collection* 项集
* Symbol : char 前瞻符号
* TerminalCount : int 终结符个数
*/
struct Collection *Goto(struct Collection *S, char Symbol, int TerminalCount)
{
// moved <- 空集
struct Collection *Moved = (struct Collection*)malloc(sizeof(struct Collection));
memset(Moved, '\0', sizeof(struct Collection));
struct Collection *Tail = Moved;
while (S != NULL) // for each item i∈S
{
char *Placeholder = strchr(S->Expression, '\376');
if (Placeholder != NULL && *(Placeholder + ) == Symbol) // if the form of i is [α->β·xζ,a] then
{
char *Expr = strdup(S->Expression);
Placeholder = strchr(Expr, '\376');
*Placeholder = Symbol;
*(Placeholder + ) = '\376';
AddItem(Moved, &Tail, S->LeftUnterminal, Expr, S->PreviewSymbol); // moved <- moved∪{[α->βx·ζ,a]}
}
S = S->next;
}
struct Collection *FreeNode = Moved;
Moved = Moved->next;
free(FreeNode);
Closure(Moved, TerminalCount); // return closure(moved)
return Moved;
} 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);
struct Collection *Moved = Goto(S, '(', TerminalCount);
while (Moved)
{
PrintItem(Moved);
Moved = Moved->next;
}
return ;
}

简单的Goto运算演示程序的更多相关文章

  1. css3 calc():css简单的数学运算-加减乘除

    css3 calc():css简单的数学运算–加减乘除 多好的东西啊,不用js,一个css就解决了. .box{ border:1px solid #ddd; width:calc(100% - 10 ...

  2. Objective-C学习笔记(四)——OC实现最简单的数学运算

    本篇帖子会实现使用OC的最简单的加减乘除运算.学习的知识点包含变量定义.运算方法,格式化输出等概念.主要学习主要的语法,事实上和C语言的语法还是比較相似的. 具体代码仅仅要写在main方法中即可了.具 ...

  3. Java练习 SDUT-4303_简单的复数运算(类和对象)

    简单的复数运算(类和对象) Time Limit: 2000 ms Memory Limit: 65536 KiB Problem Description 设计一个类Complex,用于封装对复数的下 ...

  4. 大爽Python入门教程 1-1 简单的数学运算

    大爽Python入门公开课教案 点击查看教程总目录 1 使用pycharm建立我们的第一个项目 打开pycharm,点击菜单栏,File->New Project 在Location(项目地址) ...

  5. Censored! - POJ 1625(ac自动机+简单dp+高精度运算)

    题目大意:首先给一个字符集合,这个集合有N个字符,然后需要一个长度为M的句子,但是据子里面不能包含的串有P个,每个串里面的字符都是有字符集和里面的字符构成的,现在想知道最多能构造多少个不重复的句子. ...

  6. Oracle 如何对时间进行简单加减运算

    在我们用dbms_job包进行定时Job的时候,需要设置时间间隔,所以需要知道时间的基本加减方法. SQL> alter session set nls_date_format='yyyy-mm ...

  7. 简单的闭包运算(Closure)演示程序

    /* * 该程序用于计算某个产生式的闭包 * RexfieldVon * 2013年8月9日16:01:38 */ #include <stdio.h> #include <stdl ...

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

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

  9. 简单的FOLLOW集演示程序

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

随机推荐

  1. 手势交互之GestureDetector

    GsetureDetector 一.交互过程 触屏的一刹那,触发MotionEvent事件 被OnTouchListener监听,在onTouch()中获得MotionEvent对象 GestureD ...

  2. Nhibernate主子表查询

    假如有AB两表,A为主,B为子:已知A表ID,查B表数据 ICriteria criteriaTotal = session.CreateCriteria<B>().CreateCrite ...

  3. OSG中相机参数的更改

    #pragma comment(lib, "osg.lib") #pragma comment(lib, "osgDB.lib") #pragma commen ...

  4. AbstractFactory 模式

    ///////////////////////Product.h////////////// #ifndef _PRODUCT_H_ #define _PRODUCT_H_ class Abstrac ...

  5. SGU 222.Little Rooks

    题意: 求在n*n(n<10)的棋盘上放k个车(水平竖直行走)的方案数. Solution SGU220的简化版.直接DP 显然当k>n时,ans=0; f[i][j]代表在前n行放了j个 ...

  6. TestNG扩展

    1. TestNG API 本章节将讨论如何使用TestNG API来创建自己的TestNG对象.TestNG的API基本由接口组成,这样做是为了容易模拟TestNG返回的对象. 1.1 org.te ...

  7. 啊哈,yield

    文章出处:http://www.cnblogs.com/winstic/,请保留此连接 在python编程中,我们经常会看到函数中带有yield关键字,但请注意,此时的函数不再是我们熟知的一般函数,而 ...

  8. 屏蔽手势UIGestureRecognizer 先后响应

    在iOS5一下对于手势的识别能力并不强,比如iOS6上面按钮的一个tap事件,最先接收的是uiview,并相应,而不是最上面的button,这时候就需要判断手势所在的位置和手势所在的控制器了 如下例子 ...

  9. MapReduce程序开发之流量求和(八)

    1.分析记录手机流量的日志. 2.拿到日志中的一行数据,切分各个字段,抽取出我们需要的字段:手机号,上行流量,下行流量,然后封装成kv发送出去 3.使用java中的map方法: public clas ...

  10. C# mvc3 mvc4 伪静态及IIS7.5配置

    mvc3 mvc4路由配置 //单独路由 routes.MapRoute(    name: "XXX",    url: "Home/XXX.html/{id}&quo ...