天天看點

1231 實驗四 遞歸下降文法分析程式設計

#include<stdio.h>

#include<stdlib.h>

#include<malloc.h>

#define READ(ch) ch=getc(fp) /*宏:READ(ch)*/

char ch; /*聲明為全局變量*/

int right=0;

FILE *fp;

struct struCH{

char ch;

struct struCH *next;

}struCH,*temp,*head,*shift; /*head指向字元線性連結清單的頭結點*/ /*shift指向動态建成的結點(遊标)*/

void E();

void E1();

void T(void);

void T1(void);

void F(void);

void main(int argc,char *argv[])

{

void E (); /* P(E) */

void E1(); /* P(E')*/

void T (); /* P(T) */

void T1(); /* P(T')*/

void F (); /* P(F) */

int errnum=0,k=0,m=0,countchar=0,rownum;

int charerr=0; /*開關控制量*/

if((fp=fopen(argv[1],"r"))==NULL)

{

printf("\n\tCan not open file %s,or not exist it!\n",argv[1]);

exit(0);

} /*檔案不存在or打不開時,正常退出程式*/

else

printf("\n\tSuccess open file: %s\n",argv[1]); /*成功打開檔案*/

while(!feof(fp))

{

READ(ch); /*這裡讀取字元隻是讓檔案指針往前移*/

countchar++;

} /*統計檔案中的字元數(包括換行符及檔案結束符)*/

rewind(fp); /*将fp檔案指針重新指向檔案頭處,以備後面對檔案的操作*/

if(countchar==0)

{ /*空檔案*/

printf("\t%s is a blank file!\n",argv[1]);

exit(0); /*正常退出本程式*/

}

while(k<(countchar-1))

{ /*加換行符後countchar仍多了一個,不知為何*/

ch=getc(fp);

if(!(ch=='('||ch==')'||ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='#'||ch=='\n'))

{

charerr=1;errnum++; /*charerror出錯标記,errnum統計出錯個數*/

}

k++;

}

rewind(fp); /*将fp檔案指針重新指向檔案頭處,以備後面的建連結清單操作*/

if(charerr==1)

{ /*檔案中有非法字元*/

printf("\n\t%d Unindentify characters in file %s \n",errnum,argv[1]);

exit(0); /*正常退出本程式*/

for(rownum=1;m<(countchar-1);rownum++)

{ /*識别所有行,rownum記錄行号*/ /*初始變量及堆棧和*/

right=1; /*初始存放待識别的表達式的線性連結清單頭*/

shift= malloc(sizeof(struCH));/**/

shift->next=NULL;

head=shift; /*讀取一行形成線性連結清單*/

READ(ch);

putchar(ch);

m++;

while(ch!='\n'&&m<(countchar))

{ /*行末or到檔案尾。最後會讀取檔案結束符*/ /*讀取ch,讀取存入結點,這樣每行便形成一個線性連結清單*/

temp=malloc(sizeof(struCH));

temp->ch=ch;

temp->next=NULL;

shift->next=temp;

shift=shift->next;

READ(ch);

if(m!=(countchar-1))

putchar(ch); /*不輸出最後一次讀取的檔案結束符*/

m++;

}

head=head->next; /*消去第一個空頭結點,并使head指向非空線性連結清單*/

shift=head; /*shift指向頭結點,以便後面識别操作*/

putchar('\n');

E(); /*開始識别一行*/

if(shift->ch=='#'&&right) /*正确提示:[檔案名] Line [行号]:right expression!*/

printf("%s Line %d:\t right expression!\n",argv[1],rownum);

else /*錯誤提示:[檔案名] Line [行号]:error expression!*/

printf("%s Line %d:\t error expression!\n",argv[1],rownum);

putchar('\n');

}/*end for*/

printf("Completed!\n");

fclose(fp); /*關閉檔案*/

exit(0); /*正常結束程式*/

} /*以下函數分别對應于子子產品程式*/

void E()

T();

E1();

}

void E1()

{

if(shift->ch=='+'||shift->ch=='-')

shift=shift->next;

T();

E1();

}

else

if(shift->ch=='#'||shift->ch==')')

return;

else

right=0;

}

void T(void)

F();

T1();

void T1(void)

{

if(shift->ch=='*'||shift->ch=='/')

F();

T1();

}

if(shift->ch!='#'&&shift->ch!=')'&&shift->ch!='+'&&shift->ch!='-')

right=0; /*如果不是'#'or')'or'+'or'+'or'-'則出錯*/

void F(void)

if(shift->ch=='i')

shift=shift->next;

else{

if(shift->ch=='(')

E();

if(shift->ch==')')

shift=shift->next;

else

right=0;

}

}