1. 程式人生 > >遞迴下降的語法分析

遞迴下降的語法分析

#include <stdio.h>
#include <string.h>
#include <conio.h>

char prog[80],token[6];
char ch;
int syn,p,m,n,sum,kk = 0;
char *rwtab[6] = {"begin","if","then","while","do","end"};

void scaner();
void lrparser();
void factor();
void expression();
void term();
void statement();
void yucu();


int main()
{
    FILE *fp= fopen("file1.txt","r");
    fread(prog,sizeof(char),80,fp);
    fclose(fp);
	printf("file1:");
	p = 0;
	scaner();
	lrparser();
	
	fp= fopen("file2.txt","r");
    fread(prog,sizeof(char),80,fp);
    fclose(fp);
	printf("file2:");
	p = 0;
	scaner();
	lrparser();
	return 0;
}


/*掃描器,進行詞法分析*/
void scaner()
{
	for(int i = 0; i < 8; i++)
		token[i] = NULL;
	m = 0;
	ch= prog[p++];
	while(ch == ' '){ch = prog[p++];}
	if((ch >= 'a' && ch <= 'z')||(ch >= 'A' && ch <= 'Z'))
	{
		while((ch >= 'a' && ch <= 'z')||(ch >= 'A' && ch <= 'Z')||(ch >= '0' && ch <='9' ))
		{
			token[m++] = ch;
			ch = prog[p++];
		}
		token[m++] = '\0';
		ch = prog[--p];
		syn = 10;           //syn=10表示識別符號
		for(n = 0; n < 6; n++)
			if(strcmp(token,rwtab[n]) == 0)//判斷token陣列與rwtab[n]關鍵字陣列是否相等
			{
				syn = n + 1;   //若相等,則置syn為對應的關鍵字的種別碼值
				break;
			}
	}
	else if(ch <= '9' && ch >= '0')
	{
		sum = 0;
		while(ch <= '9' && ch >= '0')
		{
			sum = sum * 10 + ch - '0';
			ch = prog[p++];
		}
		ch = prog[--p];
		syn = 11;      //syn=11表示數字
	}
	else{
		switch(ch)
		{
		case '<':m = 0;token[m++] = ch;
			ch = prog[p++];
			if(ch == '>')
			{
				syn = 21;
				token[m++] = ch;
			}
			else if(ch == '=')
			{
				syn = 22;
				token[m++] = ch;
			}
			else
			{
				syn = 20;
				ch = prog[--p];
			}
			break;
		case '>':m = 0;token[m++] = ch;
			ch = prog[p++];
			if(ch == '=')
			{
				syn = 24;
				token[m++] = ch;
			}
			else
			{
				syn = 23;
				ch = prog[--p];
			}
			break;
		case ':':m = 0;token[m++] = ch;
			ch = prog[p++];
			if(ch == '=')
			{
				syn = 18;
				token[m++] = ch;
			}
			else
			{
				syn = 17;
				ch = prog[--p];
			}
			break;
		case '+':syn = 13;token[0] = ch;break;
		case '-':syn = 14;token[0] = ch;break;
		case '*':syn = 15;token[0] = ch;break;
		case '/':syn = 16;token[0] = ch;break;
		case ':=':syn = 18;token[0] = ch;break;
		case '<>':syn = 21;token[0] = ch;break;
		case '<=':syn = 22;token[0] = ch;break;
		case '>=':syn = 24;token[0] = ch;break;
		case '=':syn = 25;token[0] = ch;break;
		case ';':syn = 26;token[0] = ch;break;
		case '(':syn = 27;token[0] = ch;break;
		case ')':syn = 28;token[0] = ch;break;
		case '#':syn = 0;token[0] = ch;break;
		default:syn = -1;
		}
	}
}


/*遞迴下降分析*/
void lrparser()    //<程式>::=begin<語句串>end
{
	if(syn == 1) //syn=1表示的單詞符號是begin
	{              //如果是begin
		scaner();  //掃描下一個單詞
		yucu();    //進行語句串分析
		if(syn == 6)//如果是end
		{
			scaner();//掃描下一個單詞
			if(syn == 0 && kk == 0)//如果是'#',則成功
				printf("success\n\n");
		}
		else{
			if(kk != 1)
				printf("error:lack end\n\n");
			kk = 1;
		}
	}  
	else{//第一個單詞不是begin
		printf("error:lack begin\n\n");
		kk = 1;
	}
}


/*語句串分析*/
void yucu()   //<語句串>::=<語句>{;<語句>}
{
	statement();     //分析語句
    while(syn == 26)  //如果單詞是';',則掃描下一個單詞
	{
		scaner(); 
		statement();
	}
}


/*語句分析*/
void statement()//<語句>::=<賦值語句>  <賦值語句>::=ID:=<表示式>
{
	if(syn == 10)  //如果是識別符號,則掃描下一個單詞
	{
		scaner();
		if(syn == 18)  //如果識別符號後面是賦值號,則掃描下一個單詞
		{
			scaner();
			expression(); //表示式分析
		}
		else    //如果識別符號後面不是賦值號
		{
			printf("賦值號錯誤!");
			kk = 1;
		}
	}
	else     //如果不是識別符號
	{
		printf("語句錯誤!");
		kk = 1;
	}
}


/*表示式分析函式*/
void expression()//<表示式>::=<項>{+<項> | -<項>}
{
	term();//項分析
	while(syn == 13 || syn == 14)//如果是'+'或'-',則掃描下一個單詞
	{
		scaner();
		term();//項分析
	}
}


/*項分析函式*/
void term()//<項>::=<因子>{*<因子> | /<因子>
{
	factor();//因子分析
	while(syn == 15 || syn == 16)//如果是'*'或'/',則掃描下一個單詞
	{
		scaner();
		factor();//因子分析
	}
}


/*因子分析函式*/
void factor()//<因子>::=ID | NUM | (<表示式>)
{
	if(syn == 10 || syn == 11)//如果是識別符號或數字,則掃描下一個單詞
		scaner();
	else if(syn == 27)//如果是左括號
	{
		scaner();//掃描下一個單詞
        expression();//表示式分析
		if(syn == 28)//如果是右括號
			scaner();//掃描下一個單詞
		else{
			printf("')'錯誤!");
			kk = 1;
		}
	}
	else{ 
		printf("表示式錯誤!");
		kk = 1;
	}
}