?? 預測分析法實現(xiàn)的語法分析器.txt
字號:
#include<stdio.h>
#include<malloc.h>
struct struCH{
char ch;
struct struCH *next;
}struCH,*temp,*head,*shift,*top,*base;
/*head指向線性鏈表的頭結點,shift指向動態(tài)建成的結點
*top和base分別指向堆棧的頂和底
*/
FILE *fp;
char curchar; /*存放當前待比較的字符*/
char curtocmp; /*存放當前棧頂的字符*/
char ch;
int right, i,j;
int table[5][9]={ /*存儲預測分析表,1為有產生式,0為無*/
{1,0,0,0,0,1,0,0,0},
{0,1,1,0,0,0,1,1,1},
{1,0,0,0,0,1,0,0,0},
{0,1,1,1,1,0,1,1,1},
{1,0,0,0,0,1,0,0,0}};
void main(int argc,char *argv[]){
void puch(char ch);
void pop();
void doforpush(int t);
void identify();
int errnum=0, k=0, countchar=0, rownum;
int m=0;
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))語言,將會多出一個字符而難以控制,
*所以這里采用先計算字符數量再遍歷整個文件來檢測其否有非法字符*/
/*[1]計算文件中字符數量*/
while(!feof(fp)){
ch=getc(fp); /*這里只是讓指針往前移*/
countchar++; /*統(tǒng)計文件中的字符數(包括換行符及文件結束符)*/
}
rewind(fp); /*將fp文件指針重新指向文件頭處,以備后面對文件的操作*/
if(countchar==0){ /*空文件*/
printf("\t%s is a blank file!\n",argv[1]);
exit(0); /*正常退出本程序*/
}
/*[2]開始遍歷文件*/
while(k<(countchar-1)){/*加換行符后countchar仍多一個,故減1*/
ch=getc(fp);
if(!(ch=='('||ch==')'||ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='#'||ch=='\n')){
charerr=1;errnum++;/*charerror出錯標記,errnum統(tǒng)計出錯個數*/
}
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;
/* '#''E'進棧 */
base=malloc(sizeof(struCH)); /*初始化堆棧*/
base->next=NULL;
base->ch='#';
temp=malloc(sizeof(struCH));
temp->next=base;
temp->ch='E';
top=temp; /*棧頂指針top指向棧頂*/
/*初始存放待識別的表達式的線性鏈表頭*/
shift=malloc(sizeof(struCH));
shift->next=NULL;
head=shift;
/*讀取一行形成線性鏈表*/
ch=getc(fp);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;
ch=getc(fp);
if(m!=(countchar-1)) putchar(ch); /*不輸出最后一次讀取的文件結束符*/
m++;
}
head=head->next; /*消去第一個空頭結點,并使head指向非空線性鏈表頭*/
shift=head; /*shift指向頭結點,以便后面識別操作*/
putchar('\n');
identify(); /*開始識別一行*/
if(!right) /*錯誤提示:[文件名] Line [行號]:error expression!*/
printf("%s Line %d:\t error expression!\n",argv[1],rownum);
else /*正確提示:[文件名] Line [行號]:right expression!*/
printf("%s Line %d:\t right expression!\n",argv[1],rownum);
putchar('\n');
}/*end for*/
printf("Completed!\n");
fclose(fp); /*關閉文件*/
exit(0); /*正常退出程序*/
}
/*入棧函數*/
void push(char ch){
temp=malloc(sizeof(struCH));
temp->ch=ch;
temp->next=top;
top=temp;
}
/*出棧函數*/
void pop(void){
curtocmp=top->ch;
if(top->ch!='#')
top=top->next;
}
/*根據數組下標計算的值找對應的產生式,并入棧*/
void doforpush(int t){
switch(t){
case 0:push('A');push('T');break;
case 5:push('A');push('T');break;
case 11:push('A');push('T');push('+');break;
case 12:push('A');push('T');push('-');break;
case 20:push('B');push('F');break;
case 25:push('B');push('F');break;
case 33:push('B');push('F');push('*');break;
case 34:push('B');push('F');push('/');break;
case 40:push('i');break;
case 45:push(')');push('E');push('(');
}
}
/*根據curchar,curtocmp轉為數字以判斷是否有產生式*/
void changchartoint()
{
switch(curtocmp) /*非終結符:棧頂*/
{
case 'A':i=1;break;
case 'B':i=3;break;
case 'E':i=0;break;
case 'T':i=2;break;
case 'F':i=4;
}
switch(curchar) /*終結符:待識別的表達式中*/
{
case 'i':j=0;break;
case '+':j=1;break;
case '-':j=2;break;
case '*':j=3;break;
case '/':j=4;break;
case '(':j=5;break;
case ')':j=6;break;
case '#':j=7;
}
}
/*識別算法函數*/
void identify()
{
int t;
for(;;)
{
pop(); /*讀取棧頂的字符存curtocmp中*/
curchar=shift->ch; /*讀取鏈中的一個字符存curchar*/
printf("\t%c-->%c\n",curchar,curtocmp);
if(curtocmp=='#' && curchar=='#') break;
if(curtocmp=='A'||curtocmp=='B'||curtocmp=='E'||curtocmp=='T'||curtocmp=='F'){
if(curtocmp!='#'){ /*[1]未到棧底時,匹配字符*/
changchartoint();
if(table[i][j]){ /*[1.1]有產生式*/
t=10*i+j; /*計算產生式在數組中的位置*/
doforpush(t); /*找對應t的產生式,并入棧*/
continue;
}
else{ /*[1.2]沒有產生式*/
right=0; /*出錯*/
break;
}
}
else{ /*[2]到棧底,當前比較字符為'#'*/
if(curtocmp!=curchar){ /*輸入行中最后一字符非'#'*/
right=0; /*出錯*/
break;
}
else
break; /*正確*/
}
}
else{ /*若當前字符為終結符*/
if(curtocmp!=curchar){
right=0; /*出錯*/
break;
}
else{
shift=shift->next; /*讀取下一個字符*/
continue;
}
}
}/*end for*/
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -