据说有坑,,,但是并改不动了,,
原文:
闲着无聊,,,,写了一个简单的LALR(1)分析表的构造,就当是复习了
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
/*
1、输入文法,对非终结符和终结符进行映射
2、求出非终结符的FIRST集
3、求项目集的闭包函数(向前搜索符)
4、求GO函数
5、LR(1)分析表
6、合并LR(1)分析表内的同心项目集
7、LALR(1)分析表
8、输入串分析
注意:
1、输入产生式不超过100条
2、'@'代表空
3、'$'代表增加产生式$->S,拓广文法
4、终结符和非终结符的个数都不超过20
5、项目集不超过100
*/
struct grammar{
char vn, s[10];//产生式vn->s[10]
}g[100];
int g_num;//记录产生式的个数
map<char, int> vn_map;//对非终结符进行映射
map<char, int> vt_map;//对终结符进行映射
int vn_num, vt_num;//记录非终结符和终结符的个数
char vn[20], vt[20];//存储非终结符和终结符的值
int first[20][20];//fisrt[i][j]代表非终结符vn[i]的first集包含终结符vt[j]
struct project{
grammar g;//产生式
int k, pre[20];//空格点位置k,向前搜索符pre
};
vector<project> closure[100];//项目集
int closure_num;//项目集的个数
struct Edge{
int u, v;
int next;
char ch;
}edge[1000];//项目集closure[u]由条件ch转换为项目集closure[v]
int go[100];//GO函数头指针
int edge_num;//转换条件数目
int belong[100];//合并项目集后的归属
int merge_num;//合并后项目集的个数
int lalr1_action[100][20], lalr1_goto[100][20];//LALR(1)分析表的action和goto表
/*
读入文法G
控制输入格式
扩广文法
对非终结符和终结符进行映射
*/
void read() {
printf("请输入文法G,'@'代表空\n");
printf("直接输入'@'输入结束\n");
g_num = 0;
int i, j, len, flag;
char ch, str[20];
grammar temp;
while( gets(str) ) {
if( str[0] == '@' ) break;
len = strlen(str);
flag = 0;
if( len < 4 ) flag = 1;
else if( str[0] < 'A' || str[0] > 'Z' || str[1] != '-' || str[2] != '>' ) flag = 1;
else {
temp.vn = str[0];
for(i = 3; i < len; i++) {
if( str[i] == ' ' ) break;
temp.s[i-3] = str[i];
}
temp.s[i-3] = '\0';
if( i < len ) flag = 1;
}
if( flag ) {
printf("产生式%s不符合文法规则,已忽略。\n", str);
continue ;
}
else {
g[ ++g_num ] = temp;
}
}
if( g_num == 0 ) {
printf("未成功输入产生式\n");
return;
}
printf("输入完成,共输入%d条产生式\n", g_num);
g[0].vn = '$';
g[0].s[0] = g[1].vn;
g[0].s[1] = '\0';
printf("拓广文法:%c->%s\n", g[0].vn, g[0].s);
for(i = 1; i <= g_num; i++) {
printf("\t %c->%s\n", g[i].vn, g[i].s);
}
vn_num = vt_num = 0;
if( vt_map['@'] == 0 ) {
vt_map['@'] = ++vt_num;
vt[vt_num] = '@';
}
for(i = 0; i <= g_num; i++) {
ch = g[i].vn;
if( vn_map[ch] == 0 ) {
vn_map[ch] = ++vn_num;
vn[vn_num] = ch;
}
len = strlen( g[i].s );
for(j = 0; j < len; j++) {
ch = g[i].s[j];
if( ch >= 'A' && ch <= 'Z' ) continue;
if( vt_map[ch] == 0 ) {
vt_map[ch] = ++vt_num;
vt[vt_num] = ch;
}
}
}
if( vt_map['#'] == 0 ) {
vt_map['#'] = ++vt_num;
vt[vt_num] = '#';
}
for(i = 1, printf("非终结符:\n"); i <= vn_num; i++) {
printf("%c -> %d\n", vn[i], vn_map[ vn[i] ]);
}
for(i = 1, printf("终结符:\n"); i <= vt_num; i++) {
printf("%c -> %d\n", vt[i], vt_map[ vt[i] ]);
}
return;
}
/*
求first集
solve_fisrt()求出所有的非终结符的first集
dfs(char ch)求非终结符ch的first集
*/
void dfs(char ch,int acc[],int vis[],int val[]) {
int i, j, k, c = vn_map[ch];
if( acc[c] ) {
for(i = 1; i <= vt_num; i++)
val[i] = first[c][i];
return;
}
int value[20];
memset(value,0,sizeof(value));
for(i = 0; i <= g_num; i++) {
if( vis[i] ) continue;
vis[i] = 1;
if( g[i].vn != ch ) continue;
int len = strlen( g[i].s );
for(j = 0; j < len; j++) {
char sh = g[i].s[j];
if( vn_map[sh] ) {
dfs(sh,acc,vis,value);
for(k = 2; k <= vt_num; k++) {
if( value[k] ) val[k] = 1;
}
if( value[1] == 0 ) break;
}
else {
c = vt_map[sh];
val[c] = 1;
break;
}
}
if( j == len ) val[1] = 1;
}
return;
}
void solve_first() {
int acc[20], vis[20], value[20];
int i, j, k;
memset(first,0,sizeof(first));
memset(acc,0,sizeof(acc));
for(i = 1; i <= vn_num; i++) {
if( acc[i] ) continue;
memset(vis,0,sizeof(vis));
memset(value,0,sizeof(value));
dfs(vn[i],acc,vis,value);
for(j = 1; j <= vt_num; j++)
first[i][j] = value[j];
acc[i] = 1;
}
printf("输出first集\n");
printf("\t");
for(i = 1; i <= vt_num; i++)
printf("%c\t", vt[i]);
printf("\n");
for(i = 1; i <= vn_num; i++) {
printf("%c\t", vn[i]);
for(j = 1; j <= vt_num; j++)
printf("%d\t", first[i][j]);
printf("\n");
}
return;
}
/*
求解闭包函数/go函数
newproject()获得一个新的项目
solve_closure()求项目集的闭包
solve_projects()求所有的项目集
*/
int Equal(grammar u,grammar v) {
if( u.vn != v.vn ) return 0;
if( !strcmp(u.s,v.s) ) return 1;
return 0;
}
int Equal(project u,project v) {
if( !Equal(u.g,v.g) ) return 0;
if( u.k != v.k ) return 0;
for(int i = 1; i <= vt_num; i++)
if( u.pre[i] != v.pre[i] ) return 0;
return 1;
}
int Equal(int x,int y) {
int i, j;
if( closure[x].size() != closure[y].size() ) return 0;
for(i = 0; i < closure[x].size(); i++) {
project u = closure[x][i];
for(j = 0; j < closure[y].size(); j++) {
project v = closure[y][j];
if( Equal(u,v) ) break;
}
if( j == closure[y].size() ) break;
}
if( i == closure[x].size() ) return 1;
return 0;
}
project newproject() {
project temp;
memset(temp.pre,0,sizeof(temp.pre));
return temp;
}
int addproject(project temp,int c) {
for(int i = 0; i < closure[c].size(); i++) {
project old = closure[c][i];
if( Equal(old.g,temp.g) && old.k == temp.k ) return i;
}
return -1;
}
int solve_closure(int c){
int i, j, k, l;
for(i = 0; i < closure[c].size(); i++) {
project old = closure[c][i];
int len = strlen( old.g.s );
if( old.k == len ) continue;
char vn = old.g.s[ old.k ];
if( vt_map[vn] ) break;
for(j = 0; j <= g_num; j++) {
if( g[j].vn != vn ) continue;
//得到新添加项目temp
project temp = newproject();
temp.g = g[j];
temp.k = 0;
//排除S->.@的情况
for(k = 0; k < strlen( g[j].s ); k++) {
if( g[j].s[k] == '@' ) temp.k++;
else break;
}
char ch = old.g.s[old.k+1];
if( ch == '\0' ) {
for(k = 1; k <= vt_num; k++)
temp.pre[k] = old.pre[k];
}
else if( vn_map[ch] ) {
for(k = 1; k <= vt_num; k++)
temp.pre[k] = first[ vn_map[ch] ][k];
}
else
temp.pre[ vt_map[ch] ] = 1;
//判断temp是否已经存在在项目集中
int flag = addproject(temp,c);
if( flag == -1 ) closure[c].push_back(temp);
else {
for(k = 1; k <= vt_num; k++)
if( temp.pre[k] ) closure[c][flag].pre[k] = 1;
}
}
}
//完成新的项目集closure[c],判断是否出现过
for(i = 1; i < c; i++) {
if( Equal(i,c) ) return i;
}
return c;
}
void addedge(int u,int v,char ch) {//设置GO函数的边
edge[edge_num].u = u;
edge[edge_num].v = v;
edge[edge_num].ch = ch;
edge[edge_num].next = go[u];
go[u] = edge_num++;
}
void solve_projects() {
project temp = newproject();
//初始化项目集,仅包含g[0],向前搜索符包含'#'
closure_num = 0;
temp.g = g[0];
temp.k = 0;
temp.pre[ vt_map['#'] ] = 1;
closure[closure_num+1].clear();
closure[closure_num+1].push_back(temp);
int c = solve_closure(closure_num+1);
if( c == closure_num+1 ) {
closure_num++;
}
int i, j, k;
//求GO函数
memset(go,-1,sizeof(go));
edge_num = 0;
for(i = 1; i <= closure_num; i++) {
//测试项目集输出
printf("项目集%d包含:\n", i);
for(j = 0; j < closure[i].size(); j++) {
project old = closure[i][j];
printf("\t%c->", old.g.vn);
for(k = 0; k <= strlen( old.g.s ); k++) {
if( k == old.k ) printf(".");
printf("%c", old.g.s[k]);
}
printf("\t");
for(k = 1; k <= vt_num; k++)
if( old.pre[k] ) printf("%c ", vt[k]);
printf("\n");
}
//求GO函数
int vis[100];
memset(vis,0,sizeof(vis));
for(j = 0; j < closure[i].size(); j++) {
if( vis[j] ) continue;
project old = closure[i][j];
int len = strlen(old.g.s);
if( old.k == len ) continue;
closure[ closure_num+1 ].clear();
for(k = j; k < closure[i].size(); k++) {
project oldd = closure[i][k];
if( oldd.g.s[ oldd.k ] == old.g.s[ old.k ] ) {
vis[k] = 1;
project temp = oldd;
temp.k++;
closure[ closure_num+1 ].push_back(temp);
}
}
if( closure[ closure_num+1 ].size() == 0 ) continue;
c = solve_closure(closure_num+1);
if( c == closure_num+1 ) {
closure_num++;
}
addedge(i,c,old.g.s[ old.k ]);
}
}
return;
}
/*
输出LR(1)分析表
所有状态从1到closure_num
lr1_action中非负数i代表第i个产生式,负数-i代表状态i
lr1_goto中负数-i代表状态i
*/
int findgrammar(grammar temp) {
for(int i = 0; i <= g_num; i++) {
if( Equal(temp,g[i]) ) return i;
}
}
void printLR1() {
int flag = 0;
int lr1_action[100][20], lr1_goto[100][20];
memset(lr1_action,INF,sizeof(lr1_action));
memset(lr1_goto,INF,sizeof(lr1_goto));
int i, j, k;
for(i = 1; i <= closure_num; i++) {
for(j = 0; j < closure[i].size(); j++) {
project old = closure[i][j];
char ch = old.g.s[ old.k ];
int c = findgrammar(old.g);
if( ch == '\0' ) {
for(k = 1; k <= vt_num; k++) {
if( old.pre[k] ) {
if( lr1_action[i][k] == INF || lr1_action[i][k] == c )
lr1_action[i][k] = c;
else flag = 1;
}
}
}
}
for(j = go[i]; j != -1; j = edge[j].next) {
int u = edge[j].u, v = edge[j].v;
char ch = edge[j].ch;
if( vn_map[ch] ) {
if( lr1_goto[u][ vn_map[ch] ] == INF || lr1_goto[u][ vn_map[ch] ] == -v )
lr1_goto[u][ vn_map[ch] ] = -v;
else flag = 1;
}
else {
if( lr1_action[u][ vt_map[ch] ] == INF || lr1_action[u][ vt_map[ch] ] == -v )
lr1_action[u][ vt_map[ch] ] = -v;
else flag = 1;
}
}
}
if( flag ) {
printf("出现冲突,该文法不是LR(1)文法\n");
return;
}
printf("LR(1)分析表:\n");
printf("状态\t");
for(i = 1; i <= vt_num; i++)
printf("%c\t", vt[i]);
for(i = 1; i <= vn_num; i++)
printf("%c\t", vn[i]);
printf("\n");
for(i = 1; i <= closure_num; i++) {
printf("%d\t", i);
for(j = 1; j <= vt_num; j++) {
k = lr1_action[i][j];
if( k == INF ) printf("\t");
else if( k < 0 ) printf("S%d\t", -k);
else printf("r%d\t", k);
}
for(j = 1; j <= vn_num; j++) {
k = lr1_goto[i][j];
if( k == INF ) printf("\t");
else if( k < 0 ) printf("%d\t", -k);
else printf("r%d\t", k);
}
printf("\n");
}
return ;
}
/*
合并同心项目集
*/
int Equalproject(int x,int y) {
if( closure[x].size() != closure[y].size() ) return 0;
int i, j, k;
for(i = 0; i < closure[x].size(); i++) {
project u = closure[x][i];
for(j = 0; j < closure[y].size(); j++) {
project v = closure[y][j];
if( u.k == v.k && Equal(u.g,v.g) ) break;
}
if( j == closure[y].size() ) return 0;
}
return 1;
}
void project_merge() {
int i, j, k;
merge_num = 0;//num表示合并后的状态编号索引
int vis[100];
memset(vis,0,sizeof(vis));
for(i = 1; i <= closure_num; i++) {
if( vis[i] ) continue;
belong[i] = ++merge_num;
vis[i] = 1;
for(j = i+1; j <= closure_num; j++) {
if( Equalproject(i,j) ) {
belong[j] = merge_num;
vis[j] = 1;
}
}
}
printf("项目集合并:\n");
for(i = 1; i <= merge_num; i++) {
printf("新项目集%d包含项目集:", i);
for(j = 1; j <= closure_num; j++)
if( belong[j] == i ) printf("%d ", j);
printf("\n");
}
}
/*
构造LALR(1)分析表
*/
void solve_lalr1() {
int flag = 0;
memset(lalr1_action,INF,sizeof(lalr1_action));
memset(lalr1_goto,INF,sizeof(lalr1_goto));
int i, j, k;
for(i = 1; i <= closure_num; i++) {
for(j = 0; j < closure[i].size(); j++) {
project old = closure[i][j];
char ch = old.g.s[ old.k ];
int c = findgrammar(old.g);
if( ch == '\0' ) {
for(k = 1; k <= vt_num; k++) {
if( old.pre[k] ) {
if( lalr1_action[ belong[i] ][k] == INF || lalr1_action[ belong[i] ][k] == c )
lalr1_action[ belong[i] ][k] = c;
else flag = 1;
}
}
}
}
for(j = go[i]; j != -1; j = edge[j].next) {
int u = belong[edge[j].u], v = belong[edge[j].v];
char ch = edge[j].ch;
if( vn_map[ch] ) {
if( lalr1_goto[u][ vn_map[ch] ] == INF || lalr1_goto[u][ vn_map[ch] ] == -v )
lalr1_goto[u][ vn_map[ch] ] = -v;
else flag = 1;
}
else {
if( lalr1_action[u][ vt_map[ch] ] == INF || lalr1_action[u][ vt_map[ch] ] == -v )
lalr1_action[u][ vt_map[ch] ] = -v;
else flag = 1;
}
}
}
if( flag ) {
printf("出现冲突,该文法不是LALR(1)文法\n");
return;
}
printf("LALR(1)分析表:\n");
printf("状态\t");
for(i = 1; i <= vt_num; i++)
printf("%c\t", vt[i]);
for(i = 1; i <= vn_num; i++)
printf("%c\t", vn[i]);
printf("\n");
for(i = 1; i <= merge_num; i++) {
printf("%d\t", i);
for(j = 1; j <= vt_num; j++) {
k = lalr1_action[i][j];
if( k == INF ) printf("\t");
else if( k < 0 ) printf("S%d\t", -k);
else printf("r%d\t", k);
}
for(j = 1; j <= vn_num; j++) {
k = lalr1_goto[i][j];
if( k == INF ) printf("\t");
else if( k < 0 ) printf("%d\t", -k);
else printf("r%d\t", k);
}
printf("\n");
}
return ;
}
/*
对输入串进行匹配
当产生式S->@,不需要符号栈退出字符
*/
void solve_str() {
printf("请输入输入串:\n");
char str[100];
int step = 0, sta[100];
char sym[100];
int sta_num = 0, sym_num = 0;
sta[sta_num++] = 1;
sym[sym_num++] = '#';
int i, j, k, len;
scanf("%s", str);
len = strlen(str);
printf("步骤\t状态栈\t符号栈\t输入串\tACTION\tGOTO\t\n");
k = 0;
while(k < len) {
printf("%d\t", ++step);
for(i = 0; i < sta_num; i++)
printf("%d", sta[i]);
printf("\t");
for(i = 0; i < sym_num; i++)
printf("%c", sym[i]);
printf("\t");
for(i = k; i < len; i++)
printf("%c", str[i]);
printf("\t");
if( sta_num == 0 ) {
printf("状态栈为空,错误\n");
break;
}
int x = sta[ sta_num-1 ];
int y = vt_map[ str[k] ];
int c = lalr1_action[x][y];
if( c == INF ) {
printf("ACTION函数为空,错误\n");
break;
}
if( c < 0 ) {
sta[ sta_num++ ] = -c;
sym[ sym_num++ ] = str[k++];
printf("S%d\t\t", -c);
}
else {
if( c == 0 ) {
printf("acc\n");
break;
}
for(i = 0; i < strlen(g[c].s); i++) {
if( g[c].s[i] != '@' ) {
sym_num--;
sta_num--;
}
}
if( sym_num < 0 || sta_num < 0 ) {
printf("归约失败\n");
break;
}
sym[ sym_num++ ] = g[c].vn;
x = sta[ sta_num-1 ];
y = vn_map[ g[c].vn ];
if( lalr1_goto[x][y] == INF ) {
printf("GO函数为空,错误\n");
}
sta[ sta_num++ ] = -lalr1_goto[x][y];
printf("r%d\t%d\t", c, -lalr1_goto[x][y]);
}
printf("\n");
}
return;
}
int main() {
freopen("in2.txt","r",stdin);
read();//读入文法G(S)
solve_first();//求非终结符的first集
solve_projects();//求闭包函数,go函数
printLR1();//输出LR(1)分析表
project_merge();//合并同心项目集
solve_lalr1();//计算LALR(1)分析表
solve_str();//输入串处理
return 0;
}