题目要求:
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; }
代码已粘上,如有什么漏洞都可再与鄙人联系。欢迎评论。