1. 程式人生 > >編譯原理_遞迴下降語法分析(源程式)

編譯原理_遞迴下降語法分析(源程式)

一、實驗目的:

編制一個遞迴下降分析程式,實現對詞法分析程式所提供的單詞序列的語法檢查和結構分析。

利用C語言編制遞迴下降分析程式,並對簡單語言進行語法分析。

二、實驗原理

      1.待分析的簡單語言的語法

      2.用擴充的BNF表示如下:

                (1)<程式>::=begin<語句串>end

                (2)<語句串>::=<語句>{<語句>}

                (3)<語句>::=<賦值語句>

                (4)<賦值語句

>::=ID:=<表示式>

                (5)<表示式>::=<>{+<> | —項>

                (6)<>::=<因子>{*<因子> | /<因子>}

                (7)<因子>::=ID | NUM | (<表示式>)

     3待分析的簡單語言的詞法

              (1)關鍵字:

                                begin    if    then    while    do    end

                                所有關鍵字都是小寫。

              (2)運算子和界符:

                                   :  =   +   -   *    /   <    >   <=   <>    >=    ;    (  )   #

              (3)其他單詞是識別符號(ID)和整型常數(NUM),通過以下正規式定義:

                                                    ID=letter(letter | digit)*

                                                    NUM=digit digit*

              (4)空格由空白、製表符和換行符組成。空格一般用來分隔IDNUM、運算子、界符和關鍵字,詞法分析階段通常被忽略。

            (5)各種單詞符號對應的種別碼

單詞符號

種別碼

單詞符號

種別碼

Begin

1

:

17

If

2

:=

18

Then

3

<

20

While

4

<>

21

Do

5

<=

22

End

6

>

23

Letter(letter+digit)*

10

>=

24

Digit digit*

11

=

25

+

13

:

26

-

14

(

27

*

15

)

28

/

16

#

0

4.實驗要求說明

輸入單詞串,以“#”結束,如果是文法正確的句子,則輸出成功資訊,列印“success,否則輸出“error”。

例如:

輸入begin a:=9;x:=2*3;b:=a+x end #

輸出success

輸入x:=a+b*c  end #

輸出error

三、實驗步驟  

   1.語法分析的主程式  main.c

#include "wordscan.h"

void lrparser();
void yucu();
void statement();
void expression();
void term();
void factor();
int kk=0;

void lrparser() {
	if (syn==1) { //begin
		scaner();
		yucu();
		if (syn==6) { //end
			scaner();
			if (syn==0 && kk==0) printf("success \n");
		} else {
			if(kk!=1) printf("error,lose 'end' ! \n");
			kk=1;
		}
	} else {
		printf("error,lose 'begin' ! \n");
		kk=1;
	}
	return;
}

void yucu() {
	statement();
	while(syn==26) { 
		scaner();
		statement();
	}
	return;
}

void statement() {
	if (syn==10) { //為識別符號
		scaner();
		if (syn==18) { //為 :=
			scaner();
			expression();
		} else {
			printf("error!");
			kk=1;
		}
	} else {
		printf("error!");
		kk=1;
	}
	return;
}


void expression() {
	term();
	while(syn==13 || syn==14) {
		scaner();
		term();
	}
	return;
}


void term() {
	factor();
	while(syn==15 || syn==16) {
		scaner();
		factor();
	}
	return;
}


void factor() {
	if(syn==10 || syn==11)scaner(); //為識別符號或整常數時,讀下一個單詞符號
	else if(syn==27) {
		scaner();
		expression();
		if(syn==28)scaner();
		else {
			printf(" ')' 錯誤\n");
			kk=1;
		}
	} else {
		printf("表示式錯誤\n");
		kk=1;
	}
	return;
}


void main() {
	p=0;int i;
	printf("********************語法分析程式***************\n");
	printf("請輸入源程式:\n");
	do {
		scanf("%c",&ch);
		prog[p++]=ch;
	} while(ch!='#');
	p=0;
	scaner();
	lrparser();
	printf("語法分析結束!\n");
	getch();
}

2.編寫掃描子程式   wordscan.h

#include "string.h"

char prog[80],token[8];
int syn,p,m,n,sum=0;
char ch;
char *rwtab[6]= {"begin","if","then","while","do","end"};
void scaner() {
	m=0;
	for(n=0; n<8; n++) token[n]=NULL;
	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';
		syn=10;
		p=p-1;      //回退一個字元
		for(n=0; n<6; n++) {
			if(strcmp(token,rwtab[n])==0) {
				syn=n+1;
				break;
			}
		}
	} else if(ch>='0' && ch<='9') {
		sum=0;
		while(ch>='0' && ch<='9') {
			sum=sum*10+ch-'0';
			ch=prog[p++];
		}
		p=p-1;
		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;
					p=p-1;
				}
				p=p+1;
				token[m]='\0';
				break;
			case '>':
				m=0;
				token[m++]=ch;
				ch=prog[p++];
				if(ch=='=') {
					syn=24;
					token[m++]=ch;
				} else {
					syn=23;
					p=p-1;
				}
				break;
			case ':':
				m=0;
				token[m++]=ch;
				ch=prog[p++];
				if(ch=='=') {
					syn=18;
					token[m++]=ch;
				} else {
					syn=17;
					p=p-1;
				}
				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=26;
				token[0]=ch;
				break;
			case '(':
				syn=27;
				token[0]=ch;
				break;
			case ')':
				syn=28;
				token[0]=ch;
				break;
			case '=':
				syn=25;
				token[0]=ch;
				break;
			case '#':
				syn=0;
				token[0]=ch;
				break;
			default:
				syn=-1;
		}
	}
}

四、實驗過程原始記錄

輸入begin a:=9;x:=2*3;b:=a+x end #
輸出success

             

輸入x:=a+b*c  end #

輸出 error