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

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述


作者:野孩子1991
来源:CSDN
原文:https://blog.csdn.net/u010668907/article/details/39141925
版权声明:本文为博主原创文章,转载请附上博文链接!

如下是我对野孩子代码的修正:
预处理代码:

#include<stdio.h>
#include<String.h>
int main()
{
 FILE *p;
 int  i=0,j=0;//
 char str[1000],str1[1000],c;
 if((p=fopen("e:\\test.txt","rt"))==NULL){
  printf("无法打开");
  return  0;
 }
 else{
  
  while((c=getc(p))!=EOF){
   str[i] = c; 
   i++;
  }
  fclose(p);
  str[i] = '\0';
  for(i=0;i<strlen(str);i++){
   if(str[i]=='/'&&str[i+1]=='/'){
    while(str[i++]!='\n'){}
    i--;
   }//单行注释
   else if(str[i]=='/'&&str[i+1]=='*'){
    while(!(str[i]=='*'&&str[i+1]=='/'))
	{
	i++;
	}
    i+=1;
   }//多行注释
   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';
  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; int k; 
 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')){
   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( 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'){
   num = 0;
   while(str[i]>='0'&&str[i]<='9'){//当读到第一个为0~9的数字时接着读之后的数字 
    num = num*10+str[i]-'0';
    token[j++] = str[i++];
   }
   if((str[i]>='a'&&str[i]<='z')||
   (str[i]>='A'&&str[i]<='Z'))
  {
  	 num=-1;syn=-3;
  	 while((str[i]>='a'&&str[i]<='z')||
   (str[i]>='A'&&str[i]<='Z')||(str[i]>='0'&&str[i]<='9')){
    token[j++] = str[i++];
   }
  
  }
   else syn = 26;
  }//数字在此处处理
  
  else {
   if(str[i]==':'&&str[i+1]=='='){
    syn = 32;
    token[j++] = str[i];
    token[j++] = str[++i];
    i++;
   }
   else if(str[i]=='<'&&str[i+1]=='>'){
    syn = 34;
    token[j++] = str[i];
    token[j++] = str[++i];
    i++;
   }
   else if(str[i]=='<'&&str[i+1]=='='){
    syn = 35;
    token[j++] = str[i];
    token[j++] = str[++i]; 
    i++;
   }
   else if(str[i]=='>'&&str[i+1]=='='){
    syn = 36;
    token[j++] = str[i];
    token[j++] = str[++i];
    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;
    }
    
    token[j++] = str[i++];
   }
  }
  token[j] = '\0';
  if(num!=-1){
   printf("%d %d\n",num,syn);
   
   
   
  }
  else if(syn!=-1&&syn !=-2 &&syn!=-3){
   printf("%s %d\n",token,syn);
   
  }
  else if(syn==-1){
   printf("%s error\n",token);
   
  }
  else if(syn == -3){
   printf("%s error ID\n",token);
   
  }
 }
 fclose(p);
 return 0;
}


  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
实验一  手工构造简单词法分析程序(必修) 一、实验目的 了解词法分析程序的基本构造原理,掌握简单词法分析程序的手工构造方法。 二、实验内容 对从键盘输入或从文件读入的形如: “const count=10,sum=81.5,char1=’f’,string1=”hj”, max=169;”的常量说明串进行处理,分析常量说明串中各常量名、常量类型及常量值,并统计各种类型常量个数。 三、实验要求 1、输入的常量说明串,要求最后以分号作结束标志; 2、根据输入串或读入的文本文件中第一个单词是否为“const”判断输入串或文本文件是否为常量说明内容; 3、识别输入串或打开的文本文件中的常量名。常量名必须是标识符,定义为字母开头,后跟若干个字母,数字或下划线; 4、根据各常量名紧跟等号“=”后面的内容判断常量的类型。其中:字符型常量定义为放在单引号内的一个字符;字符串常量定义为放在双引号内所有内容;整型常量定义为带或不带+、- 号,不以0开头的若干数字的组合;实型常量定义为带或不带+、- 号,不以0开头的若干数字加上小数点再后跟若干数字的组合; 5、统计并输出串或文件中包含的各种类型的常量个数; 6、以二元组(类型,值)的形式输出各常量的类型和值; 7、根据常量说明串置于高级语言源程序中时可能出现的错误情况,模仿高级语言编译器对不同错误情况做出相应处理。
源程序预处理是指在编译过程中对源代码进行处理,以便于后续的编译工作。预处理的主要任务包括宏定义、文件包含、条件编译等。预处理程序设计实现需要考虑以下几个方面: 1. 宏定义:预处理程序需要支持宏定义功能,即将一段代码片段定义为一个宏,并在后续的代码中使用该宏。宏定义需要支持参数传递和嵌套定义。 2. 文件包含:预处理程序需要支持文件包含功能,即在源代码中引用其他文件中的代码。文件包含需要支持相对路径和绝对路径。 3. 条件编译:预处理程序需要支持条件编译功能,即根据条件判断是否编译某段代码。条件编译需要支持#if、#else、#elif、#endif等指令。 词法分析程序设计实现需要考虑以下几个方面: 1. 词法分析器的设计词法分析器需要根据语法规则将源代码分解成一个个单词,即词法单元。词法分析器需要支持关键字、标识符、常量、运算符、分隔符等词法单元。 2. 词法单元的定义:词法单元需要定义其类型、值、行号等属性。词法单元的类型包括关键字、标识符、常量、运算符、分隔符等。 3. 错误处理:词法分析程序需要支持错误处理功能,即在遇到不符合语法规则的代码时,能够及时报错并停止分析。错误处理需要支持错误类型、错误行号等信息的输出。 以上是源程序预处理词法分析程序设计实现的一些方面,具体实现需要根据编译器的需求进行设计
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值