PL/0 詞法分析器緩存
1 #include<stdio.h>
2 #include <ctype.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 typedef enum SymEnum 7 { 8 Identifier=0, //標識符
9 Const=1, //常數
10 Key=2, //關鍵字
11 Operator=3, //運算符
12 Delimiter=4 //界符
13 } SymEnum; 14
15 char KeyWord[13][15]; //關鍵字
16
17 void Init() 18 { 19 strcpy(&KeyWord[0][0],"begin"); 20 strcpy(&KeyWord[1][0],"call"); 21 strcpy(&KeyWord[2][0],"const"); 22 strcpy(&KeyWord[3][0],"do"); 23 strcpy(&KeyWord[4][0],"end"); 24 strcpy(&KeyWord[5][0],"if"); 25 strcpy(&KeyWord[6][0],"odd"); 26 strcpy(&KeyWord[7][0],"procedure"); 27 strcpy(&KeyWord[8][0],"read"); 28 strcpy(&KeyWord[9][0],"then"); 29 strcpy(&KeyWord[10][0],"var"); 30 strcpy(&KeyWord[11][0],"while"); 31 strcpy(&KeyWord[12][0],"write"); 32 } 33
34 //判斷一個單詞是否爲關鍵字
35 int IsKeyWord(char *word) 36 { 37 int i=0,j=12; 38 while(i<=j) 39 { 40 int k=(i+j)/2; 41 if(strcmp(word,KeyWord[k])<=0) 42 j=k-1; 43 if(strcmp(word,KeyWord[k])>=0) 44 i=k+1; 45 } 46 return i-1>j ? 1 : 0; 47 } 48
49 //判斷一個單詞是否爲界符
50 int IsDelimiter(char word) 51 { 52 if(word==','||word==';'||word=='.'||word=='('||word==')') 53 return 1; 54 return 0; 55 } 56
57 //判斷一個單詞是否爲操做符
58 int IsOperator(char *word) 59 { 60 if(word[0]=='+'||word[0]=='-'||word[0]=='*'||word[0]=='/'||word[0]=='<'||word[0]=='>'||strcmp(word,":=")==0||strcmp(word,">=")==0||strcmp(word,"<=")==0||word[0]=='#'||word[0]=='=') 61 return 1; 62 return 0; 63 } 64
65 //判斷一個單詞是不是常數
66 int IsConst(char *word) 67 { 68 if(word[0]>='0'&&word[0]<='9') 69 return 1; 70 return 0; 71 } 72
73 //判斷連個字符是否屬於相同類型
74 int IsSame(char f,char s) 75 { 76 int bf = (f>='0'&&f<='9'||f>='a'&&f<='z'||f>='A'&&f<='Z')? 1 : 0 ; 77 int bs = (s>='0'&&s<='9'||s>='a'&&s<='z'||s>='A'&&s<='Z')? 1 : 0 ; 78 return bf == bs; 79 } 80
81 //判斷 word 的類型
82 SymEnum TypeOfWord(char *word) 83 { 84 if(IsKeyWord(word)) 85 return Key; 86 if(IsConst(word)) 87 return Const; 88 if(IsOperator(word)) 89 return Operator; 90 return Identifier; 91 } 92
93 int GetSym() 94 { 95 FILE *fp,*fout; 96 if((fp=fopen("PL0.txt","r"))==NULL || (fout=fopen("source.txt","w+"))==NULL) 97 { 98 printf("Open Error!\n"); 99 exit(0); 100 } 101 SymEnum SYM; //存放每一個單詞的類別,用內部編碼形式表示;
102 char word[50]; //存儲單詞
103 word[0]='\0'; 104 int len=0; //單詞長度
105 char ch; 106 while(fscanf(fp,"%c",&ch)!=EOF) 107 { 108 // ch 爲空格,回車符,製表符
109 if(ch==' '||ch=='\n'||ch=='\t') 110 { 111 // word 不爲空
112 if(len) 113 { 114 //判斷單詞類型
115 SYM=TypeOfWord(word); 116 fprintf(fout,"%d %s\n",SYM,word); 117 //清空緩存區
118 len=0; 119 word[len]='\0'; 120 } 121 // word 爲空,忽略 ch
122 } 123 else if(IsDelimiter(ch)) 124 { 125 //word 不爲空
126 if(len) 127 { 128 //判斷單詞的類型
129 SYM=TypeOfWord(word); 130 fprintf(fout,"%d %s\n",SYM,word); 131 // ch == delimiter
132 SYM=Delimiter; 133 fprintf(fout,"%d %c\n",SYM,ch); 134 //清空緩存區
135 len=0; 136 word[len]='\0'; 137 } 138 else
139 { 140 //word 爲空, ch 爲界符
141 SYM=Delimiter; 142 fprintf(fout,"%d %c\n",SYM,ch); 143 //清空緩存區
144 len=0; 145 word[len]='\0'; 146 } 147 } 148 else
149 { 150 if(len>0) 151 { 152 if(IsSame(word[len-1],ch)) 153 { 154 //判斷 word 與 ch 是否同類型
155 word[len++]=ch; 156 word[len]='\0'; //字符串終結符
157 } 158 else
159 { 160 //判斷單詞類型
161 SYM=TypeOfWord(word); 162 fprintf(fout,"%d %s\n",SYM,word); 163 //清空緩存區,並把 ch 放入緩存區
164 len=0; 165 word[len++]=ch; 166 word[len]='\0'; //字符串終結符
167 } 168 } 169 else
170 { 171 word[len++]=ch; 172 word[len]='\0'; 173 } 174 } 175 } 176 fclose(fp); 177 fclose(fout); 178 return 0; 179 } 180
181 void PrintToScream() 182 { 183 FILE *fp; 184 if((fp=fopen("source.txt","r+"))==NULL) 185 { 186 printf("Open File Error!\n"); 187 exit(0); 188 } 189 int id; 190 char word[50]; 191 printf("0-標識符 1-常數 2-關鍵字 3-操做符 4-界符\n"); 192 while(fscanf(fp,"%d %s",&id,word)!=EOF) 193 { 194 printf("(%d,%s)\n",id,word); 195 } 196 fclose(fp); 197 } 198
199 int main() 200 { 201 Init(); 202 GetSym(); 203 PrintToScream(); 204 return 0; 205 }