LR(1)表生成算法演示程序
/*
* LR 转换表
* + Goto 记录表
* + 状态转换表
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include "Common.h"
#include "Closure.h"
#include "LRCal.h"
#include "LRMigrate.h" extern char *Grammer[];
extern char ***GrammerRule; /*
* 创建Goto记录表
*/
struct Record *CreateRecordTable()
{
struct Record *RecordTable = (struct Record *)malloc(sizeof(struct Record));
memset(RecordTable, '\0', sizeof(struct Record));
RecordTable->RecordRow = -;
RecordTable->RecordRowMax = ;
RecordTable->Record = (int **)malloc(sizeof(int) * );
memset(RecordTable->Record, '\0', sizeof(int) * ); return RecordTable;
} /*
* 记录 Goto[CCi, symbol]->CCj
* RecordTable : struct Record* 记录表
* CCi : int 当前项集 ID
* Symbol : unsigned char 转移符号
* CCj : int 转移目的项集 ID
*/
void Record(struct Record *RecordTable, int CCi, unsigned char Symbol, int CCj)
{
// [CCi, Symbol] -> CCj
if (RecordTable->RecordRow < CCi) // 新请求的位置大于最大项位,需要更新项位
{
// 一次分配 32 条记录空间
if (RecordTable->RecordRowMax <= CCi) // 新请求的位置超过最大可使用项数,追加新的项表空间
{
int NewSize = ((int)(CCi / ) + ) * ;
int** NewRecordTable = (int**)malloc(NewSize * sizeof(int));
memset(NewRecordTable, '\0', NewSize * sizeof(int));
memcpy(NewRecordTable, RecordTable->Record, RecordTable->RecordRowMax * sizeof(int));
RecordTable->RecordRowMax = NewSize;
RecordTable->Record = NewRecordTable;
}
RecordTable->RecordRow = CCi; int *tmp_spc = (int*)malloc(sizeof(int) * );
memset(tmp_spc, '\0', sizeof(int) * );
RecordTable->Record[CCi] = tmp_spc;
}
if (RecordTable->Record[CCi][Symbol] == CCj)
{
// printf("Find Repeat.\n");
}
else if (RecordTable->Record[CCi][Symbol] != )
{
printf("Find Conflict.\n");
}
else
{
RecordTable->Record[CCi][Symbol] = CCj;
printf("[CC%d, %c] -> CC%d\n", CCi, Symbol, CCj);
}
} /*
* 查找产生式序号
* s : unsigned char* 要查找的产生式
*/
int FindGrammer(unsigned char *s)
{
int i;
for (i = ; Grammer[i][] != '\0'; i++)
{
if (strcmp((char*)Grammer[i], (char*)s) == )
{
return i;
}
}
return -;
} /*
* 检查产生式是否为最终接受
* s : unsigned char* 要检查的产生式
*/
bool CheckIsAccept(unsigned char *s)
{
// 默认第一行语法产生式左非终结符为起始符号
int l = strlen((char*)s);
return (Grammer[][] == s[] && s[l - ] == SYM_PLACEHOLDER && s[l - ] == SYM_EOF);
} /*
* 添加转换项
* LRTable : struct LRElement** LR转换表
* StateID : int 状态ID
* Symbol : unsigned int 转换符号
* Action : enum ActionEnum 转换动作
* ActionValue : int 动作值
*/
void AddState(struct LRElement **LRTable, int StateID, unsigned int Symbol, enum ActionEnum Action, int ActionValue)
{
if (LRTable[StateID] != NULL)
{
// 不存在 None 和 Accept 参与的冲突
if (LRTable[StateID][Symbol].Action == None)
{
LRTable[StateID][Symbol].Action = Action;
LRTable[StateID][Symbol].ActionValue = ActionValue;
}
else if (!(LRTable[StateID][Symbol].Action == Action && LRTable[StateID][Symbol].ActionValue == ActionValue))
{
int ConflictType = (int)(LRTable[StateID][Symbol].Action) + (int)Action;
switch (ConflictType)
{
case : // 移进-归约
printf("Found Shift-Reduce Conflicting.\n");
if (Action == Shift)
{
LRTable[StateID][Symbol].Action = Action;
LRTable[StateID][Symbol].ActionValue = ActionValue;
}
break;
case : // 归约-归约
printf("Found Reduce-Reduce Conflicting.\n");
break;
default:
printf("Found Undefined Conflicting.\n");
break;
}
}
}
} /*
* 通过生成的核心项集 CC 填充状态转移表
* CC : struct CoreCollection* 核心项集
* CoreCollectionCount : int 核心项集个数
* RecordTable : struct Record* Goto记录表
*/
struct LRElement **LRFillTable(struct CoreCollection *CC, int CoreCollectionCount, struct Record *RecordTable)
{
// 虽然 Action 表和 Goto 表的表项存在一定的差异,但是还是可以使用同一个结构体作为元素结构
// 因为每个核心项集生成一项 LR 转移项,所以 LR 转移表的项数和核心项集的个数是一样的
// Goto 表不会使用 Action 字段,因为 ActionValue 字段的值必须为正整数
struct LRElement **LRTable = (struct LRElement**)malloc(sizeof(int) * CoreCollectionCount);
int LRIndex = ;
while (LRIndex < CoreCollectionCount)
{
LRTable[LRIndex] = (struct LRElement*)malloc(sizeof(struct LRElement) * );
memset(LRTable[LRIndex], '\0', sizeof(struct LRElement) * );
LRIndex++;
} struct CoreCollection *CCPtr;
for (CCPtr = CC; CCPtr != NULL; CCPtr = CCPtr->next) // for each CCi∈CC
{
struct Collection *SPtr;
for (SPtr = CCPtr->S; SPtr != NULL; SPtr = SPtr->next) // for each item I∈CCi
{
unsigned char *Placeholder = (unsigned char*)strchr((char*)SPtr->Expression, SYM_PLACEHOLDER);
unsigned char PrevSymbol = *(Placeholder + ); if (*(Placeholder + ) != '\0' && *(Placeholder + ) != '\0' &&
(PrevSymbol < 'A' || PrevSymbol > 'Z') &&
RecordTable->RecordRow >= CCPtr->id && RecordTable->Record[CCPtr->id][PrevSymbol] != ) // if I is [A -> β·cγ, α] and goto(CCi, c) = CCj then
{
// Action[i, c] <- "shift j"
AddState(LRTable, CCPtr->id, PrevSymbol, Shift, RecordTable->Record[CCPtr->id][PrevSymbol]);
}
else if (CheckIsAccept(SPtr->Expression) == true) // else if I is [S' -> S·, eof] then
{
// Action[i, eof] <- "accept"
AddState(LRTable, CCPtr->id, SYM_EOF, Accept, );
}
else if (*(Placeholder + ) != '\0' && *(Placeholder + ) == '\0') // else if I is [A -> β·, α] then
{
// Action[i, α] <- "reduce A -> β"
int i = ;
unsigned char *SExpr = SPtr->Expression;
unsigned char *Expr = (unsigned char*)malloc(strlen((char*)SExpr));
while (*SExpr != '\0')
{
if (*SExpr != SYM_PLACEHOLDER)
{
Expr[i++] = *SExpr;
}
SExpr++;
}
Expr[--i] = '\0'; AddState(LRTable, CCPtr->id, PrevSymbol, Reduce, FindGrammer(Expr) + );
}
}
int NTPtr;
for (NTPtr = ; NTPtr < ; NTPtr++)
{
if (GrammerRule[NTPtr] != NULL) // for each n∈NT
{
if (RecordTable->Record[CCPtr->id] != NULL) // if goto(CCi, n) = CCj then
{
LRTable[CCPtr->id][NTPtr].ActionValue = RecordTable->Record[CCPtr->id][NTPtr]; // Goto[i, n] <- j
}
}
}
}
return LRTable;
} /*
* 打印状态转移表
* LRMigrateTable : struct LRElement** LR状态转移表
* CoreCollectionCount : int 核心项集个数
*/
void PrintLRMigrate(struct LRElement **LRMigrateTable, int CoreCollectionCount)
{
// 为了方便压缩打印,将行链表转换为列链表
struct LRElement **LRCompression[];
int index, ItemPtr;
for (index = ; index < ; index++)
{
LRCompression[index] = NULL;
} for (index = ; index < CoreCollectionCount; index++) // 行
{
for (ItemPtr = ; ItemPtr < ; ItemPtr++) // 列
{
if (LRMigrateTable[index][ItemPtr].Action != None || LRMigrateTable[index][ItemPtr].ActionValue != )
{
if (LRCompression[ItemPtr] == NULL) // 如果该列自始自终没有任何表项,那么不创建该列的指针表
{
LRCompression[ItemPtr] = (struct LRElement**)malloc(sizeof(int) * CoreCollectionCount);
memset(LRCompression[ItemPtr], '\0', sizeof(int) * CoreCollectionCount);
}
LRCompression[ItemPtr][index] = &LRMigrateTable[index][ItemPtr];
}
}
} // 此时列表头若为 NULL 则该列无数据
printf("State");
for (index = ; index < ; index++)
{
if (LRCompression[index] != NULL)
{
if (index != )
{
printf("\t%c", index);
}
else
{
printf("\t<eof>");
}
}
}
printf("\n");
for (index = ; index < CoreCollectionCount; index++)
{
printf("%d", index);
for (ItemPtr = ; ItemPtr < ; ItemPtr++)
{
if (LRCompression[ItemPtr] != NULL)
{
if (LRCompression[ItemPtr][index] != NULL)
{
printf("\t");
switch (LRCompression[ItemPtr][index]->Action)
{
case None:
// printf("");
break;
case Shift:
printf("s");
break;
case Reduce:
printf("r");
break;
case Accept:
printf("acc");
break;
}
if (LRCompression[ItemPtr][index]->Action != Accept)
{
printf("%d", LRCompression[ItemPtr][index]->ActionValue);
}
}
else
{
printf("\t");
}
}
}
printf("\n");
}
}
全部代码:http://files.cnblogs.com/rexfield/LR.7z
LR(1)表生成算法演示程序的更多相关文章
- <编程>比较两种素数表生成算法+计算程序运行时间+通过CMD重定向测试程序
最近学习加密算法,需要生成素数表,一开始使用简单的循环,从2开始判断.代码如下: #include<iostream> #include<cstdio> #include< ...
- LR(1)表驱动语法分析程序
/* * LR(1) 语法分析 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #inc ...
- 分布式全局不重复ID生成算法
分布式全局不重复ID生成算法 算法全局id唯一id 在分布式系统中经常会使用到生成全局唯一不重复ID的情况.本篇博客介绍生成的一些方法. 常见的一些方式: 1.通过DB做全局自增操作 优点:简单.高 ...
- 分布式系统的唯一id生成算法你了解吗?
在分库分表之后你必然要面对的一个问题,就是id咋生成? 因为要是一个表分成多个表之后,每个表的id都是从1开始累加自增长,那肯定不对啊. 举个例子,你的订单表拆分为了1024张订单表,每个表的id都从 ...
- PHP 短连接生成算法
短连接生成类: <?php #短连接生成算法 class Short_Url { #字符表 public static $charset = "0123456789ABCDEFGHIJ ...
- 微博短链接的生成算法(Java版本)
最近看到微博的短链接真是很火啊,新浪.腾讯.搜狐等微博网站都加入了短链接的功能.之所以要是使用短链接,主要是因为微博只允许发140 字,如果链接地址太长的话,那么发送的字数将大大减少.短链接的主要职责 ...
- php短网址生成算法
<?php //短网址生成算法 class ShortUrl { //字符表 public static $charset = "0123456789ABCDEFGHIJKLMNOPQ ...
- 一个简单的QQ隐藏图生成算法 通过jQuery和C#分别实现对.NET Core Web Api的访问以及文件上传
一个简单的QQ隐藏图生成算法 隐藏图不是什么新鲜的东西,具体表现在大部分社交软件中,预览图看到的是一张图,而点开后看到的又是另一张图.虽然很早就看到过这类图片,但是一直没有仔细研究过它的原理,今天 ...
- 分布式唯一ID生成算法-雪花算法
在我们的工作中,数据库某些表的字段会用到唯一的,趋势递增的订单编号,我们将介绍两种方法,一种是传统的采用随机数生成的方式,另外一种是采用当前比较流行的“分布式唯一ID生成算法-雪花算法”来实现. 一. ...
随机推荐
- phpstorm使用技巧
确实很好用,不过还是要看一些方法 转自:http://blog.sina.com.cn/s/blog_488193d70102vk7e.html 2, 关联DOC文档: 右键External Libr ...
- Java---Hibernate>>Can't create table './xxx/#sql-b2c_1a.frm' (errno: xxx)解决方法
通用方案:删除相关表,重新生成. 1.关联表之间数据引擎不一致导致: 修改相关表的引擎设定,保持一致. 2.关联表索引字段的引用类型不一样(如A表关联字段是int,B表索引是char): 修改相关表的 ...
- 利用OllyDebug查看程序调用的dll模块
最近在做一个Qt项目,在产品发布的时候一直为找不到程序到底缺少了哪些dll组件而困扰.具体问题是,在我的项目中使用到了QMediaPlayer播放一段音频文件,我使用的开发环境的Win7 32位,而在 ...
- 初用jquery
---恢复内容开始--- 这两天在顶顶大人的指导下,利用jquery框架做了一个动态切换的小页面.最终效果图: 这么萌萌哒的图片让我觉得一直在测试也没那么累.实现功能如下: 1.打开页面时,自动切换, ...
- PL/SQL学习(三)游标
原文参考:http://plsql-tutorial.com/ 两种类型: 隐式: 执行INSERT.UPDATE.DELETE 或者只返回一条结果的SELECT语句时默认创建 ...
- DIV+CSS 网页布局之:一列布局
1.网页布局 布局(layout)即对事物的全面规划和安排,页面布局是对页面的文字.图像或表格进行格式化版式排列.网页布局对改善网站的外观非常重要,又称版式布局,大多数网站会把内容安排到多个列中,就像 ...
- ios8.1.2耗电情况严重的解决方法
打开cydia,搜索ifile(威锋源,版本2.1.0-1).打开ifile,进入路径/Applications.里面有许多程序文件,选择适当的进行禁用(ifile可以禁用程序的活动而不完全删除它,这 ...
- 粘滞位(sticky bit)
linux特殊权限:setUid, setGid, 粘着位(sticky) (1)目录的X权限(执行) 文件的可执行权限很简单,也就是可否执行它的意思,但目录的执行权限又代表什么意思呢? 当然不可能是 ...
- POJ 1459 Power Network 最大流(Edmonds_Karp算法)
题目链接: http://poj.org/problem?id=1459 因为发电站有多个,所以需要一个超级源点,消费者有多个,需要一个超级汇点,这样超级源点到发电站的权值就是发电站的容量,也就是题目 ...
- JNI/NDK开发指南(开山篇)
转载请注明出处:http://blog.csdn.net/xyang81/article/details/41759643 相信很多做过Java或Android开发的朋友经常会接触到JNI方面的技术, ...