递归下降LL(1)语法分析程序

文法是E->TA、A->+TA|-TA|ε、T->FB、B->*FB|/FB|ε、F->(E)|i ,可以判断输入的表达式是否正确,且能指出错误的原因,并能生成简单的语法分析树。

源程序为

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char out='o';
char str[50]={0};
char arr[50][100]={0};
int inter=0;
int len;
char n=0;
char m;
int number=1;
int row=0;
int col=0;
int timeA=0;
int timeB=0;
int timeT=0;
int timeE=1;//由E开始 
void E();
void A();
void T();
void B();
void F();

void num(){
	printf("%d\t",number);
	number++;
}
 
void residue(){
	for(int i=inter;i<=len;i++){
		printf("%c",str[i]);
	}
	printf("\n");
}
 
void E(){//E->TA
    num();
    printf("E->TA\t\t");
    residue();
    if(timeE>=2){
    	row=row+2;
        arr[row][col-1]='/';
    	arr[row][col+1]='\\';
    	arr[row+1][col-4]='T';
    	arr[row+1][col+3]='A';
    	row++;col=col-4;
	}
    timeT++;
	T();
	timeA++;
	if(timeT>1){
		row=row-3;//要根据图调整 
		col=col+5;
	}
	else{
		row=2;	 
		col=36;
	}	
	A();
}

void A(){//A->+TA|-TA|ε
	if(str[inter]=='+'){
		num();
		printf("A->+TA\t\t");
		residue();
		inter++;
		row++;
		arr[row][col-2]='/'; 
		arr[row][col]='|';
		arr[row][col+2]='\\';
		arr[row+1][col-3]='+';
		arr[row+1][col]='T';
		arr[row+1][col+5]='A';
		row++;
		timeT++;
		T();
		timeA++;
		row=row-3;//根据图调整 
		col=col+3;
		A();
	}else if(str[inter]=='-'){
		num();
		printf("A->-TA\t\t");
		residue();
		inter++;
        row++;
        col++;
        n=str[inter];
        m=str[inter+1];
		arr[row][col-1]='/'; 
		arr[row][col]='|';
		arr[row][col+2]='\\';
		arr[row+1][col-2]='-';
		arr[row+1][col]='T';
		arr[row+1][col+5]='A';
		str[inter]=n;
		str[inter+1]=m;
		row++;
		timeT++;  
		T();
		timeA++;
		row=row-3;//根据图调整 
		col=col+5;
		A();
	}
	else {
		num();
		printf("A->ε\t\t");
		residue();
		row++; 
	}
}

void T(){//T->FB
    num();
	printf("T->FB\t\t");
	residue();
	if(timeT>1){
		row++;
	    arr[row][col-2]='/'; 
	    arr[row][col+1]='\\';
	    arr[row+1][col-3]='F';
	    arr[row+1][col+2]='B';
	    row++;col=col-3;
	}
	F();
	timeB++;
    col=col+4;row--;//根据图调整 
	B();
}

void B(){//B->*FB|/FB|ε
	if(str[inter]=='*'){
		num();
		printf("B->*FB\t\t");
		residue();
		inter++;
		row++;
		arr[row][col-2]='/'; 
		arr[row][col]='|';
		arr[row][col+2]='\\';
		arr[row+1][col-3]='*';
		arr[row+1][col]='F';
		arr[row+1][col+3]='B';
		row++; 
		F();
		timeB++;
		row=row-1;//根据图调整 
		col=col+4;
		B();
	}else if(str[inter]=='/'){
		num();
		printf("B->/FB\t\t");
		residue();
		inter++;
        row++;
		arr[row][col-2]='/'; 
		arr[row][col]='|';
		arr[row][col+2]='\\';
		arr[row+1][col-3]='/';
		arr[row+1][col]='F';
		arr[row+1][col+3]='B';
		row++;
		F();
		timeB++;
		row=row-0;//根据图调整 
		col=col+4;
		B();
	}
	else{
		num();
		printf("B->ε\t\t");
		residue(); 
		row++;
	}
}

void F(){//F->(E)|i 
     if(str[inter]=='('){
     	num();
		printf("F->(E)\t\t");
		residue();
     	inter++;
     	row++;
     	arr[row][col-1]='/'; 
		arr[row][col]='|';
		arr[row][col+1]='\\';
		arr[row+1][col-2]='(';
		arr[row+1][col]='E';
		arr[row+1][col+2]=')';
		timeE++;
		E();		
     	if(str[inter]==')'){
     		num();
			printf("F->(E)\t\t");
			residue();
     		inter++;
		 }
		 else{
		 	printf("表达式分析结果:该表达式语法错误\n"); 
		 	printf("表达式错误原因:表达式中缺少')'");
		 	exit(0);//错误则退出 
		 }
	 }else if(str[inter]=='i'||str[inter]<='9'&&str[inter]>='0'||str[inter]<='z'&&str[inter]>='a'){
	 	num();
		printf("F->i\t\t");
		residue();
	 	inter++;
	 	row++;
	 	arr[row][col]='|';
		arr[row+1][col]='i';
	 }else if(str[inter]==')'){
	 	printf("表达式分析结果:该表达式语法错误\n"); 
	 	printf("表达式错误原因:表达式中缺少'('");
	 	exit(0); 
	 }else{
	 	printf("表达式分析结果:该表达式语法错误\n"); 
	 	printf("表达式错误原因:表达式中缺少或者不是数字或标识符");
	 	exit(0);
	 }
}

int main(){
	while(1){
		for(int i=0;i<50;i++){
			str[i]=0;
		}
		for(int i=0;i<50;i++){
			for(int j=0;j<100;j++){
				arr[i][j]=0;
			}
		}
		number=1;n=0;inter=0;row=0,col=0;
		timeA=0;timeB=0;timeT=0;timeE=1;//由E开始
		arr[0][30]='E';
    	arr[1][25]='/';//表示父节点和子节点的从属关系
    	arr[1][35]='\\';//注意'\'是转义字符
    	arr[2][24]='T';
    	arr[2][36]='A';
    	arr[3][23]='/';
    	arr[3][25]='\\';
    	arr[4][22]='F';
    	row=4;col=22;
    	arr[4][26]='B';
		printf("请输入表达式:");
    	scanf("%s", str);
   		len = strlen(str);
    	str[len] = '#';
    	if(str[0]=='#'){
    		printf("'#'为结束标志,不能作为输入\n");
    		printf("请重新输入!"); 
    		exit(0);
		}
    	printf("步骤\t 文法\t\t 剩余串\n");
    	E();
    	if (str[inter] == '#'){
    		printf("表达式分析结果:该表达式语法正确\n");
    		printf("该表达式的语法分析树为:\n");
		}   
    	else if(str[inter]==')'){
    		printf("表达式分析结果:该表达式语法错误\n"); 
	 		printf("表达式错误原因:表达式中缺少'('\n");
	 		exit(0);
		}else{
			printf("表达式分析结果:该表达式语法错误\n"); 
	 		printf("表达式错误原因:不是合法的句子\n");
	 		exit(0);
		}
    	for(int i=0;i<30;i++){//打印语法分析树
        	for(int j=0;j<50;j++)
           	{
                printf("%c",arr[i][j]);
           	}
            printf("\n");
    	}
		printf("输入'q'退出,输入'c'继续:");
		scanf("%s",&out); 
		printf("\n");
		if(out=='q'){
   			exit(0);
	   	}
	}
   return 0;
}

运行结果为

1.表达式正确的为:

2.表达式错误:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值