遞迴下降的語法分析
阿新 • • 發佈:2019-01-26
#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; } }