/*
* 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)表生成算法演示程序的更多相关文章

  1. <编程>比较两种素数表生成算法+计算程序运行时间+通过CMD重定向测试程序

    最近学习加密算法,需要生成素数表,一开始使用简单的循环,从2开始判断.代码如下: #include<iostream> #include<cstdio> #include< ...

  2. LR(1)表驱动语法分析程序

    /* * LR(1) 语法分析 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #inc ...

  3. 分布式全局不重复ID生成算法

    分布式全局不重复ID生成算法 算法全局id唯一id  在分布式系统中经常会使用到生成全局唯一不重复ID的情况.本篇博客介绍生成的一些方法. 常见的一些方式: 1.通过DB做全局自增操作 优点:简单.高 ...

  4. 分布式系统的唯一id生成算法你了解吗?

    在分库分表之后你必然要面对的一个问题,就是id咋生成? 因为要是一个表分成多个表之后,每个表的id都是从1开始累加自增长,那肯定不对啊. 举个例子,你的订单表拆分为了1024张订单表,每个表的id都从 ...

  5. PHP 短连接生成算法

    短连接生成类: <?php #短连接生成算法 class Short_Url { #字符表 public static $charset = "0123456789ABCDEFGHIJ ...

  6. 微博短链接的生成算法(Java版本)

    最近看到微博的短链接真是很火啊,新浪.腾讯.搜狐等微博网站都加入了短链接的功能.之所以要是使用短链接,主要是因为微博只允许发140 字,如果链接地址太长的话,那么发送的字数将大大减少.短链接的主要职责 ...

  7. php短网址生成算法

    <?php //短网址生成算法 class ShortUrl { //字符表 public static $charset = "0123456789ABCDEFGHIJKLMNOPQ ...

  8. 一个简单的QQ隐藏图生成算法 通过jQuery和C#分别实现对.NET Core Web Api的访问以及文件上传

    一个简单的QQ隐藏图生成算法   隐藏图不是什么新鲜的东西,具体表现在大部分社交软件中,预览图看到的是一张图,而点开后看到的又是另一张图.虽然很早就看到过这类图片,但是一直没有仔细研究过它的原理,今天 ...

  9. 分布式唯一ID生成算法-雪花算法

    在我们的工作中,数据库某些表的字段会用到唯一的,趋势递增的订单编号,我们将介绍两种方法,一种是传统的采用随机数生成的方式,另外一种是采用当前比较流行的“分布式唯一ID生成算法-雪花算法”来实现. 一. ...

随机推荐

  1. 在hyper安装openwrt

    写了长长长一篇文章,结果把标签关了,这篇文章就不见了,草稿箱也没有!!! 只好直接copy原来作者的文章了 下载地址 openwrt image tulip driver 引用 Want to add ...

  2. CSS3 skew倾斜、rotate旋转动画

    css3出现之前,我们实现一个对象的一组连续动画需要通过JavaScript或Jquery编写,脚本代码较为复杂: 若需要实现倾斜.旋转之类的动画难度将更高(我还没试过用JavaScript或Jque ...

  3. 在Laravel5.* 中使用 AdminLTE

    在Laravel5.* 中使用 AdminLTE AdminLTE是一个很棒的单纯的由 HTML 和 CSS 构建的后台模板,在这片文章中,我将讲述如何将 AdminLTE 和 Laravel 优雅的 ...

  4. Oracle课堂实验一“表的使用”代码。

    --创建本地管理表空间CustomerTBSCREATE TABLESPACE CustomerTBS         DATAFILE 'd:\Oracle11\product\11.2.0\ora ...

  5. delphi发送html带附件邮件

    var html: TIdText; begin if not SMTP.Connected then SMTP.Disconnect(); try SMTP.Connect; try if SMTP ...

  6. Newtonsoft post Json 日期格式处理

     Newtonsoft.Json.Converters.IsoDateTimeConverter DateTimeConverter = new Newtonsoft.Json.Converters. ...

  7. makefile debug

    1. 使用warning指令 warning 是个不错的命令,可以打印出消息,来判断makefile执行的流程 2.使用ifeq ifneq 当makefile被多次调用到的时候,如果都输出warni ...

  8. 阿里云centOS6 下python安装及配置、pip安装及配置、ipython安装及配置

    我是在阿里云服务器上进行的python环境搭建,阿里云服务器会自带python但是版本低,所以打算自己安装一个,期间遇到各种问题,而且百度根本不够用无奈上的外网很快解决了.在此分享一下. 一.pyth ...

  9. 数据库之--- SQLite 语句

    一. 基础创表操作: 1. 创建表 CREATE TABLE IF NOT EXISTS t_dog(name text, age bolb, weight real); 2. 插入记录 INSERT ...

  10. Mozilla公布WebVR API标准草案

    随着信息技术的迅速发展,虚拟现实(Virtual Reality,VR)技术在近些年不断完善,其应用范围也变得十分广泛.为了搭建逼真的虚拟场景,VR技术一般都需要用到大量精美的图像和复杂的动作.因此, ...