1. 程式人生 > >編譯原理實驗之源程式的預處理及詞法分析程式設計

編譯原理實驗之源程式的預處理及詞法分析程式設計

題目要求:

1、實現預處理功能

源程式中可能包含有對程式執行無意義的符號,要求將其剔除。

首先編制一個源程式的輸入過程,從鍵盤、檔案或文字框輸入若干行語句,依次存入輸入緩衝區(字元型資料);然後編制一個預處理子程式,去掉輸入串中的回車符、換行符和跳格符等編輯性文字;把多個空白符合併為一個;去掉註釋。

2、實現詞法分析功能

輸入:所給文法的源程式字串。

輸出:二元組(syn,token或sum)構成的序列。其中,

 syn為單詞種別碼。

 Token為存放的單詞自身字串。

 Sum為整型常量。

具體實現時,可以將單詞的二元組用結構進行處理。

3、待分析的C語言子集的詞法

1)關鍵字

main  if  then  while  do  static  int  double  struct  break  else  long  switch  case  typedef  char  return  const  float  short  continue  for  void  default  sizeof  do     

所有的關鍵字都是小寫。

2)運算子和界符

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

3)其他標記ID和NUM

通過以下正規式定義其他標記:

ID→letter(letter|digit)*

NUM→digit digit*

letter→a|…|z|A|…|Z

digit→0|…|9

4)空格由空白、製表符和換行符組成

空格一般用來分隔ID、NUM、專用符號和關鍵字,詞法分析階段通常被忽略。

4、各種單詞符號對應的種別碼

表1   各種單詞符號的種別碼

單詞符號   種別碼       單詞符號   種別碼       

main       1             ;           41     

if         2             (           42      

then       3             )           43      

while      4             int         7 

do         5             double      8   

static     6             struct      9   

ID         25            break       10  

NUM        26            else        11  

+          27            long        12  

-          28            switch      13  

*          29            case        14     

/          30            typedef     15

:          31            char        16

:=         32            return      17

<          33            const       18

<>         34            float       19

<=         35            short       20

>          36            continue    21

>=         37            for         22

=          38            void        23

 default     39           sizeof      24

do          40           #            0  

題目要求如上,鄙人自己寫的如下(這是早幾個月前寫的,沒有再檢查對錯,由於當初老師給的實驗要求就有問題所以裡面的會有一些小問題不影響,且鄙人寫程式碼習慣寫註釋比較好理解):

第一步程式碼:

#include<stdio.h>
#include<String.h>
int main(){
 FILE *p;
 int  falg = 0,len,i=0,j=0;//
 char str[1000],str1[1000],c;
 if((p=fopen("e:\\test.txt","rt"))==NULL){
  printf("無法開啟");
  return  0;
 }
 else{
  //fgets(str,1000,p);
  while((c=getc(p))!=EOF){
   str[i++] = c; 
  }
  fclose(p);
  str[i] = '\0';
  for(i=0;i<strlen(str);i++){
   if(str[i]=='/'&&str[i+1]=='/'){
    while(str[i++]!='\n'){}
   }//單行註釋
   else if(str[i]=='/'&&str[i+1]=='*'){
    while(!(str[i]=='*'&&str[i+1]=='/')){i++;}
    i+=2;
   }//多行註釋
   else if(str[i]==' '&&str[i+1]==' '){
    while(str[i]==' '){i++;}
    i--;
    if(str1[j-1]!=' ')
       str1[j++]=' ';
   }//多個空格,去除空格
   else if(str[i]=='\n') {
    if(str1[j-1]!=' ')
       str1[j++]=' ';
   }//換行處理,
   else if(str[i]==9){
    while(str[i]==9){
     i++;
    }
    if(str1[j-1]!=' ')
     str1[j++]=' ';
    i--;
   }//tab鍵處理
   else str1[j++] = str[i];//其他字元處理
  }
  str1[j] = '\0';
 // printf("%s\n",str);
 // printf("%s\n",str1);
  /*
  for(int k=0;k<strlen(str1);k++){
   if(str1[k]!=' ')
     printf("%c",str1[k]);
   else  printf("_");
  }
  */
  if((p = fopen("e:\\test1.txt","w"))==NULL){
   printf("can not find it!");
   return 0;
  }
  else{
   if(fputs(str1,p)!=0){
    printf("儲存失敗!");
   }
   else printf("儲存成功!");
  }
  fclose(p);
 }
 return 0;
}


 第二部分程式碼:

#include<stdio.h>
#include<String.h>
int main(){
 FILE *p;
 int  falg = 0,len,i=0,j=0;//
 char *rwtab[27]={"","main","if","then","while","do",
  "static","int","double","struct","break","else","long",
  "switch","case","typedef","char","return","const","float",
  "short","continue","for","void","sizeof","default","do"};//26個
 char str[1000],str1[1000],c;
 int syn,num;
 char token[200];

 if((p=fopen("e:\\test1.txt","rt"))==NULL){
  printf("無法開啟");
  return  0;
 }
 
  //fgets(str,1000,p);
  while((c=getc(p))!=EOF){
   str[i++] = c; 
  }
  fclose(p);
  if((p=fopen("e:\\test2.txt","w"))==NULL){
  printf("無法開啟");
  return  0;
  }
  str[i] = '\0';
 //printf("%s\n",str);
 for(i=0;str[i]!='\0';){
  j = 0;
  num = -1;
  if((str[i]>='a'&&str[i]<='z')||(str[i]>='A'&&str[i]<='Z')||str[i]=='_'){
   while((str[i]>='a'&&str[i]<='z')||(str[i]>='A'&&str[i]<='Z')||(str[i]>='0'&&str[i]<='9')||str[i]=='_'){
    token[j++] = str[i++];
   } 
   token[j] = '\0';
   for(int k=1;k<27;k++){
    if(strcmp(rwtab[k],token)==0)
     break;
   }
   if(k<25)
    syn = k;
   else if(k==25)
    syn = 39;
   else if(k==26)
    syn = 40;
   else syn = 25;
  }//關鍵字和標示符處理
  else if((str[i]>='0'&&str[i]<='9')&&((str[i+1]>='a'&&str[i+1]<='z')||
   (str[i+1]>='A'&&str[i+1]<='Z')||str[i+1]=='_'||(str[i+1]>='0'&&str[i+1]<='9'))){
   syn = -3;
   while((str[i]>='a'&&str[i]<='z')||
   (str[i]>='A'&&str[i]<='Z')||str[i]=='_'||(str[i]>='0'&&str[i]<='9')){
    token[j++] = str[i++];
   }
   i--;
  }

  else if(str[i]>='0'&&str[i]<='9'){
   num = 0;
   while(str[i]>='0'&&str[i]<='9'){
    num = num*10+str[i++]-'0';
   }
   syn = 26;
  }//數字在此處處理
  else {//printf("%c********************************\n",str[i]);
   if(str[i]==':'&&str[i+1]=='='){
    syn = 32;
    token[j++] = str[i];
    token[j++] = str[i++];
   }
   else if(str[i]=='<'&&str[i+1]=='>'){
    syn = 34;
    token[j++] = str[i];
    token[j++] = str[i++];
   }
   else if(str[i]=='<'&&str[i+1]=='='){
    syn = 35;
    token[j++] = str[i];
    token[j++] = str[i++];
   }
   else if(str[i]=='>'&&str[i+1]=='='){
    syn = 36;
    token[j++] = str[i];
    token[j++] = str[i++];
   }
   else if(str[i]==' '){
    i++;
    syn = -2;
   }//空格處理
   /*
   else if(str[i]!=' '){
    syn = -1;
    while(str[i++]!=' '){
     token[j++] = str[i];
    }
   }//不明字元的處理
   */
   else{
    switch(str[i]){
     case '+': syn = 27;break;
     case '-': syn = 28;break;
     case '*': syn = 29;break;
     case '/': syn = 30;break;
     case ':': syn = 31;break;
     case '<': syn = 33;break;
     case '>': syn = 36;break;
     case ';': syn = 41;break;
     case ')': syn = 43;break;
     case '(': syn = 42;break;
     case '#': syn = 0;break;
     case '=':syn = 38;break;
     default: syn = -1;break;
    }
    //printf("%c********************************\n",str[i]);
    token[j++] = str[i++];
   }
  }
  token[j] = '\0';
  if(num!=-1){
   printf("%d %d\n",num,syn);
   fprintf(p,"%d %d\n",num,syn);
   char A[100];
   int i=0;
   while(num){
    A[i++] = num%2;
    num = num/2;
   }
   
   for(i--;i>=0;i--){
    printf("%c ",A[i]+'0');
    fprintf(p,"%c ",A[i]+'0');
   }
    printf(" %d\n",syn);
    fprintf(p,"%d\n",syn);
  }
  else if(syn!=-1&&syn !=-2 &&syn!=-3){
   printf("%s %d\n",token,syn);
   fprintf(p,"%s %d\n",token,syn);
  }
  else if(syn==-1){
   printf("%s error\n",token);
   fprintf(p,"%s error\n",token);
  }
  else if(syn == -3){
   printf("%s error ID\n",token);
   fprintf(p,"%s error ID\n",token);
  }
 }
 fclose(p);
 return 0;
}


程式碼已粘上,如有什麼漏洞都可再與鄙人聯絡。歡迎評論。