#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <conio.h>
typedef struct{
char* formula;//产生式
char right[100][100]; //产生式右部
int rightNum; //产生式右部个数
char left; //产生式左部
int hasNull; //是否有ε产生式
}grammarElement;
grammarElement gramOldSet[200];//原始文法的产生式集
typedef struct {
char* formula;
int mark;//记录'.'目前在该表示里的位置
}Element;
typedef struct {
int status;
Element elements[100];
int itemNum;
}Closure;
Closure closureSet[100]; //文法的closure集
typedef struct {
char *base;
char *top;
int size;
}Stack;
Stack analyzeStack;
typedef struct {
int *base;
int *top;
int size;
}Stack2;
Stack2 statusStack;
/*变量定义*/
char terSymbol[200]; //终结符号
char non_ter[200]; //非终结符号
char AllSymbol[200]; //非终结符号
int Go[100][100]; //函数转换之间的Go函数
int Action[100][100]; //ACTION表
int Goto[100][100]; //GOTO表
char* input;
int terSymbolLength;
int non_terLength;
int gramOldSetNum;
int statusNum=0;
void toxy(int x, int y){ //将光标移动到X,Y坐标处
COORD pos = { x , y };
HANDLE Out = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(Out, pos);
}
/*初始化栈*/
void initCharStack(){
analyzeStack.base=(char*)malloc(50*sizeof(char));
analyzeStack.size=0;
analyzeStack.top=analyzeStack.base;
}
/*入栈操作*/
int push(char a){
if(analyzeStack.top-analyzeStack.base>analyzeStack.size){
return 0;
}
*analyzeStack.top=a;
analyzeStack.top++;
analyzeStack.size++;
return 1;
}
/*出栈操作*/
char pop(){
if(analyzeStack.top==analyzeStack.base){
return 0;
}
analyzeStack.top--;
char ch=*analyzeStack.top;
analyzeStack.size--;
return ch;
}
char getTop(){
return *(analyzeStack.top-1);
}
//遍历栈
void stackTraverse(){
char *temp=analyzeStack.base;
while(temp!=analyzeStack.top){
printf("%c",*temp);
temp++;
}
}
void destroyStack(){
analyzeStack.base=NULL;
analyzeStack.top=NULL;
analyzeStack.size=0;
}
/*初始化栈*/
void initStatusStack(){
statusStack.base=(int *)malloc(50*sizeof(int ));
statusStack.size=0;
statusStack.top=statusStack.base;
}
/*入栈操作*/
int push2(int a){
if(statusStack.top-statusStack.base>statusStack.size){
return 0;
}
*statusStack.top=a;
statusStack.top++;
statusStack.size++;
return 1;
}
/*出栈操作*/
int pop2(){
if(statusStack.top==statusStack.base){
return 0;
}
statusStack.top--;
int ch=*statusStack.top;
statusStack.size--;
return ch;
}
int getTop2(){
return *(statusStack.top-1);
}
//遍历栈
void stackTraverse2(){
int *temp=statusStack.base;
while(temp!=statusStack.top){
printf("%d",*temp);
temp++;
}
}
void destroyStack2(){
statusStack.base=NULL;
statusStack.top=NULL;
statusStack.size=0;
}
int isTerSymbol(char ch){
for (int i = 0; i < strlen(terSymbol); ++i) {
if(ch==terSymbol[i]){
return 1;
}
}
return 0;
}
int isNonTerSymbol(char ch){
for(int i=0;i<strlen(non_ter);i++){
if(ch==non_ter[i]){
return 1;
}
}
return 0;
}
int getNonTerPoint(char ch){
for(int h=0;h<strlen(non_ter);h++){
if(non_ter[h]==ch){
return h;
}
}
return -1;
}
int getTerPoint(char ch){
for(int h=0;h<strlen(terSymbol);h++){
if(ch==terSymbol[h]){
return h;
}
}
return -1;
}
int getSymbolPoint(char ch){
for(int h=0;h<strlen(AllSymbol);h++){
if(AllSymbol[h]==ch){
return h;
}
}
return -1;
}
void init(){
gramOldSet[0].formula="G->E";
gramOldSet[1].formula="E->aA";
gramOldSet[2].formula="E->bB";
gramOldSet[3].formula="A->cA";
gramOldSet[4].formula="A->d";
gramOldSet[5].formula="B->cB";
gramOldSet[6].formula="B->d";
/* gramOldSet[1].formula="E->E+T";
gramOldSet[2].formula="E->T";
gramOldSet[3].formula="T->T*F";
gramOldSet[4].formula="T->F";
gramOldSet[5].formula="F->(E)";
gramOldSet[6].formula="F->i";*/
gramOldSetNum=7;
input="bcccccd#";
//input="i*i+i#";
for(int i=0;i<gramOldSetNum;i++){
char c=gramOldSet[i].formula[0];
int f=0;
for(int k=0;k<strlen(non_ter);k++){
if(c==non_ter[k]){
f=1;
}
}
if(f==0){
non_ter[strlen(non_ter)]=c;
}
for (int j = 3; j < strlen(gramOldSet[i].formula); j++) {
char ch=gramOldSet[i].formula[j];
if(ch!='|'){
if(ch>='A'&&ch<='Z'){
int flag=0;
for(int k=0;k<strlen(non_ter);k++){
if(ch==non_ter[k]){
flag=1;
}
}
if(flag==0){
non_ter[strlen(non_ter)]=ch;
}
} else{
int flag=0;
for(int k=0;k<strlen(terSymbol);k++){
if(ch==terSymbol[k]){
flag=1;
}
}
if(flag==0){
terSymbol[strlen(terSymbol)]=ch;
}
}
}
}
}
terSymbol[strlen(terSymbol)]='#';
for (int i=0;i<strlen(terSymbol);i++){
AllSymbol[i]=terSymbol[i];
}
int length=strlen(AllSymbol);
for (int i=0;i<strlen(non_ter);i++){
AllSymbol[length+i]=non_ter[i];
}
//AllSymbol=strcat(terSymbol,non_ter);
for (int i = 0; i < 100;i++) {
for (int j=0;j<100;j++){
Go[i][j]=-1;
}
}
}
/*对每个产生式进行初始化准备*/
void prepare(){
for (int i = 0; i <gramOldSetNum; i++) {
gramOldSet[i].left=gramOldSet[i].formula[0];
int rightNum=0,mark=3;
for(int j=3;j<strlen(gramOldSet[i].formula);j++){
if(gramOldSet[i].formula[j]=='|'){
for(int k=mark;k<j;k++){
gramOldSet[i].right[rightNum][k-mark]=gramOldSet[i].formula[k];
}
mark=j+1;
rightNum++;
}
}
for(int k=mark;k<strlen(gramOldSet[i].formula);k++){
gramOldSet[i].right[rightNum][k-mark]=gramOldSet[i].formula[k];
}
rightNum++;
gramOldSet[i].rightNum=(rightNum);
}
}
/*//通过CLOSURE(I)的第一个元素对该闭包进行完善
void analyzeStatus(int status){
int mark=closureSet[status].elements[0].mark;
int forLength=strlen(closureSet[status].elements[0].formula);
int num=closureSet[status].itemNum;
if(forLength!=mark){
char ch=closureSet[status].elements[0].formula[mark];
//若A->α.Bβ属于CLOSURE(I),那么对于任何关于B的产生式B->γ,项目B->.γ也属于CLOSURE(I)
if(isNonTerSymbol(ch)){
for(int i=0;i<gramOldSetNum;i++){
if(ch==gramOldSet[i].left){
closureSet[status].elements[num].formula=gramOldSet[i].formula;
closureSet[status].elements[num].mark=3;
num++;
}
}
closureSet[status].itemNum=num;
int flag=1;
while(flag==1) {
for(int i=1;i<num;i++){
int markk=closureSet[status].elements[i].mark;
char chh=closureSet[status].elements[i].formula[markk];
if(isNonTerSymbol(chh)){
int index=0;
for(int j=0;j<num;j++){
if(chh==closureSet[status].elements[j].formula[0]){
index=1;
}
}
if(index==0){
flag=1;//还可以进行扩展
for(int j=0;j<gramOldSetNum;j++){
if(chh==gramOldSet[j].left){
closureSet[status].elements[num].formula=gramOldSet[i].formula;
closureSet[status].elements[num].mark=3;
num++;
}
}
}
}
}
if(closureSet[status].itemNum==num){
flag=0;//没有再进行扩展
} else{
closureSet[status].itemNum=num;
}
}
for(int j=0;j<closureSet[status].itemNum;j++){
//printf("扩展子元素%s--%d\n",closureSet[status].elements[j].formula,closureSet[status].elements[j].mark);
}
}
} else{
//printf("该状态%s不能再扩展子集\n",closureSet[status].elements[0].formula);
return;
}
}
void expandStatus(int status){
if(closureSet[status].itemNum>1){
for(int i=0;i<closureSet[status].itemNum;i++){
int flag=0;
char* string1=closureSet[status].elements[i].formula;
int mark1=closureSet[status].elements[i].mark;
char ch=closureSet[status].elements[i].formula[mark1];
for(int j=0;j<statusNum;j++){ //这一部分是为了判断状态集里是否已经有该状态了
char* string2=closureSet[j].elements[0].formula;
int mark2=closureSet[j].elements[0].mark;
if(!strcmp(string1,string2)){
if((mark1+1)==mark2){
Go[status][getSymbolPoint(ch)]=j;
flag=1;
}
}
}
*//*flag仍为0说明状态集里还没有该状态,可以往其中进行扩展*//*
if(flag==0){
closureSet[statusNum].status=statusNum;
closureSet[statusNum].itemNum=1;
closureSet[statusNum].elements[0].formula=string1;
closureSet[statusNum].elements[0].mark=(mark1+1);
Go[status][getSymbolPoint(ch)]=statusNum;
analyzeStatus(statusNum);
statusNum++;
expandStatus(statusNum-1);
}
}
} else{
//printf("该状态集%s不能再扩展\n",closureSet[status].elements[0].formula);
return;
}
}*/
/*通过CLOSURE(I)的第一个元素对该闭包进行完善*/
void analyzeStatus(int status){
int flag=1;
while (flag>0){
int num=closureSet[status].itemNum;
for (int i=0;i<num;i++){
int mark=closureSet[status].elements[i].mark;
int forLength=strlen(closureSet[status].elements[i].formula);
if(mark<forLength){
char ch=closureSet[status].elements[i].formula[mark];
if(isNonTerSymbol(ch)){
for(int j=0;j<gramOldSetNum;j++){
if(ch==gramOldSet[j].left){
char* string=gramOldSet[j].formula;
int temp=0;
for(int k=0;k<num;k++){
if(!strcmp(string,closureSet[status].elements[k].formula)){
if(closureSet[status].elements[k].mark==3){
temp=1;
flag=0;
break;
}
}
}
if(temp==0){
closureSet[status].elements[num].formula=gramOldSet[j].formula;
closureSet[status].elements[num].mark=3;
num++;
flag=1;
}
}
}
} else{
flag=0;
}
} else{
flag=0;
}
}
closureSet[status].itemNum=num;
}
}
/*通过遍历该状态的子元素对整个状态集进行扩充,这是一个广度递归的过程*/
void expandStatus(int status){
if(closureSet[status].itemNum==1){
return;
} else{
for(int i=0;i<closureSet[status].itemNum;i++){
char* string1=closureSet[status].elements[i].formula;
int length=strlen(string1);
int mark1=closureSet[status].elements[i].mark;
char ch=closureSet[status].elements[i].formula[mark1];
if(length==mark1){
continue;
} else{
initStatusStack();
for(int t=0;t<closureSet[status].itemNum;t++){
int mark2=closureSet[status].elements[t].mark;
char ch_mark=closureSet[status].elements[t].formula[mark2];
if(ch_mark==ch){
push2(t);
}
}
int index=0;
for(int j=0;j<statusNum;j++){ //这一部分是为了判断状态集里是否已经有该状态了
if(statusStack.size>closureSet[j].itemNum){
continue;
} else{
int flag=0;
for (int k=0;k<statusStack.size;k++){
char* string2=closureSet[j].elements[k].formula;
int mark2=closureSet[j].elements[k].mark;
for(int h=0;h<statusStack.size;h++){
int status_temp=*(statusStack.base+h);
char* string_temp=closureSet[status].elements[status_temp].formula;
int mark_temp=closureSet[status].elements[status_temp].mark;
if(!strcmp(string_temp,string2)){
if((mark_temp+1)==mark2){
flag++;
}
}
}
}
if(flag==statusStack.size){
Go[status][getSymbolPoint(ch)]=j;
index=1;
break;
}
}
}
if(index==0){
closureSet[statusNum].status=statusNum;
closureSet[statusNum].itemNum=0;
for(int h=0;h<statusStack.size;h++){
int status_temp=*(statusStack.base+h);
char* string_temp=closureSet[status].elements[status_temp].formula;
int mark_temp=closureSet[status].elements[status_temp].mark;
closureSet[statusNum].itemNum++;
closureSet[statusNum].elements[h].formula=string_temp;
closureSet[statusNum].elements[h].mark=(mark_temp+1);
Go[status][getSymbolPoint(ch)]=statusNum;
}
destroyStack2();
Go[status][getSymbolPoint(ch)]=statusNum;
analyzeStatus(statusNum);
statusNum++;
}
}
}
}
for(int i=status+1;i<statusNum;i++){
expandStatus(i);
}
}
void getCLOSURE(){
closureSet[0].status=statusNum;
statusNum++;
Element element;
element.formula=gramOldSet[0].formula;
element.mark=3;
closureSet[0].elements[0]=element;
closureSet[0].itemNum=1;
analyzeStatus(0);
expandStatus(0);
}
void getAction(){
for(int i=0;i<100;i++){
for (int j=0;j<100;j++){
Action[i][j]=0;
}
}
for (int i=0;i<statusNum;i++){
char* string=closureSet[i].elements[0].formula;
int mark=closureSet[i].elements[0].mark;
if(!strcmp(gramOldSet[0].formula,string)&&(strlen(string)==mark)){
Action[i][getTerPoint('#')]=100;
} else if(strlen(string)==mark){
for (int j=0;j<gramOldSetNum;j++){
if(!strcmp(string,gramOldSet[j].formula)){
for (int k=0;k<strlen(terSymbol);k++){
Action[i][k]=(0-j);
}
}
}
} else{
for (int j=0;j<strlen(terSymbol);j++){
if(Go[i][j]!=-1){
Action[i][j]=Go[i][j];
}
}
}
}
}
void getGoto(){
for(int i=0;i<100;i++){
for (int j=0;j<100;j++){
Goto[i][j]=0;
}
}
for(int i=0;i<statusNum;i++){
for (int j=0;j<strlen(non_ter);j++){
int temp=Go[i][getSymbolPoint(non_ter[j])];
if(temp!=-1){
Goto[i][j]=temp;
}
}
}
}
void showInfo(){
printf("%s\n",non_ter);
printf("%s\n",terSymbol);
for(int i=0;i<gramOldSetNum;i++){
printf("%s\t%c\t%d\t",gramOldSet[i].formula,gramOldSet[i].left,gramOldSet[i].rightNum);
for(int j=0;j<gramOldSet[i].rightNum;j++){
printf("%s\t",gramOldSet[i].right[j]);
}
printf("\n");
}
for(int i=0;i<statusNum;i++){
printf("CLOSURE(%d)的元素为:\t",i);
for(int j=0;j<closureSet[i].itemNum;j++){
printf("%s--%d\t",closureSet[i].elements[j].formula,closureSet[i].elements[j].mark);
}
printf("\n");
}
printf("Go函数:\n\t");
for (int i=0;i<strlen(AllSymbol);i++){
printf("%c\t",AllSymbol[i]);
}
printf("\n");
for (int i=0;i<statusNum;i++){
printf("%d\t",i);
for (int j=0;j<strlen(AllSymbol);j++){
if(Go[i][j]==-1){
printf("error\t");
} else{
printf("%d\t",Go[i][j]);
}
}
printf("\n");
}
printf("\t\t\tACTION表\t\t\tGOTO表\n\t");
for (int i=0;i<strlen(terSymbol);i++){
printf("%c\t",terSymbol[i]);
}
for (int i=0;i<strlen(non_ter);i++){
printf("%c\t",non_ter[i]);
}
printf("\n");
for (int i=0;i<statusNum;i++){
printf("%d\t",i);
for (int j=0;j<strlen(terSymbol);j++){
if(Action[i][j]==0){
printf("error\t");
} else if(Action[i][j]==100){
printf("acc\t");
} else{
printf("%d\t",Action[i][j]);
}
}
for (int j=0;j<strlen(non_ter);j++){
if(Goto[i][j]==0){
printf("error\t");
} else{
printf("%d\t",Goto[i][j]);
}
}
printf("\n");
}
}
/*对输入串进行分析*/
void analyzeInput(){
int line=55;
toxy(0,line);
printf("步骤");
toxy(15,line);
printf("状态");
toxy(30,line);
printf("符号");
toxy(45,line);
printf("输入串");
toxy(60,line);
printf("操作");
initCharStack();
initStatusStack();
push2(0);
push('#');
int index=0;
int flag=1;
int step=1;
char* operation="初始化";
while (flag>0){
line++;
toxy(0,line);
printf("%d",step);
step++;
toxy(15,line);
stackTraverse2();
toxy(29,line);
stackTraverse();
toxy(44,line);
for(int i=index;i<strlen(input);i++){
printf("%c",input[i]);
}
toxy(58,line);
printf("%s",operation);
int status=getTop2();
char ch=input[index];
int action=Action[status][getTerPoint(ch)];
if(action==0){
flag=0;
break;
}else if(action==100) {
flag=-1;
break;
}else if(action>0){
push2(action);
push(ch);
index++;
flag=1;
operation="移进";
} else if(action<0){
int temp=-action;
flag=1;
operation="规约";
char* right=gramOldSet[temp].right[0];
char left=gramOldSet[temp].left;
int rightLength=strlen(right);
for(int i=0;i<rightLength;i++){
pop();
pop2();
}
push(left);
int status_below=getTop2();
int new_statu=Goto[status_below][getNonTerPoint(left)];
if(new_statu==0){
flag=0;
break;
} else{
push2(new_statu);
}
}
}
if(flag==0){
printf("\n出现错误");
} else if(flag==-1){
printf("\n输入正确");
}
}
int main() {
init();
prepare();
getCLOSURE();
getAction();
getGoto();
showInfo();
analyzeInput();
return 0;
}
该算法对于不带左递归的非常简单的文法还是可以轻松处理的,但对于带有左递归的就不行了(这也就是LR(0)算法的缺点),不过还是可以将项目集规范族正确产生的。代码测试的不多,bug很多望大神指教。