编译原理之LR(0)算法

#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很多望大神指教。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值