编译原理实验之源程序的预处理及词法分析程序设计

题目要求:

   

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;
}


代码已粘上,如有什么漏洞都可再与鄙人联系。欢迎评论。

  • 8
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值