词法分析器

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct test   //关键字
{
 char name[10];
 int  num;
};
struct oper//运算符与关系运算符
{
 char name[4];
 int  num;
};
struct cut  //分隔符
{
 char name[2];
 int  num;
};
//定义全局变量
struct test test[10]={
 {"main",3},{"if",4},{"int",5},{"for",6},{"while",7},{"do",8},{"retuen",9},{"break",10},{"continue",11},
 };
struct oper oper[11]={
 {"+",41},{"-",42},{"*",43},{"/",44},{"=",45},{">",46},{"<",47},{">=",48},{">=",49},{"==",50},{"!=",51}
 };
struct cut cut[6]={
 {",",61},{";",62},{"{",63},{"}",64},{"(",65},{")",66}
 };
typedef struct sd
{int type;
int no;
char str[10];
}sdd;
sdd  value[10];

 

 

//包含的函数
void menu();//菜单
void scansource();//查看源文件
void rule();//查看输出规则
void analyse();//分析结果显示
void getch(char ch); //读取为字母
void getnum(char ch); //读取为数字
void getspace(char ch); //读取制表符类
void getelse(char ch);  //其他字符
int change(char str[10]);


char ch;
char str[10];
int  k=0,i=0;
char sourcefile[20];  //源文件名
char objectfile[20];   //目标文件名
FILE *fp;
FILE *hp;
int count=-1;
int flag=-1;

int main(int argc,char *argv[])
{
 int choice;
 //显示菜单
 menu();
 printf("输入进行词法分析的源文件名:");
 scanf("%s",sourcefile);
 printf("\n输入分析结果存入的文件名:");
 scanf("%s",objectfile);
 printf("\n输入选项:");
 scanf("%d",&choice);
 for(; ;)
 {  
  switch(choice)
  {
  case 1:
   scansource();
   break;
  case 2:
   rule();
   break;
  case 3:
   analyse();
   break;
  case 4:
   exit(1);
   break;
  }
  
  printf("\n\n");
  
  printf("请输入选项:");
  scanf("%d",&choice);}
  
 
 return 0;
}

void menu()
{
 printf("/-----------------------------------------------/\n");
 printf(" 词法分析器  \n");
 printf(" 1.查看源文件:  \n");
 printf(" 2.符号种别码:  \n");
 printf(" 3.分析结果:  \n");
 printf(" 4.退出程序:  \n");
 printf("/------------------------------------------------/\n");
}

void scansource()
{
 FILE *fp;
 char ch;
 if((fp=fopen(sourcefile,"r"))==NULL)
 {
 printf("文件打开错误或源文件不存在 !\n");
 exit(1);
 }
 ch=fgetc(fp);
 while(ch!=EOF)
 { 
  putchar(ch);
  ch=fgetc(fp);
 }
 fclose(fp);
 printf("\n");
}

void rule()
{
 int i;
 
    printf("标识符及其对应种别码:\n");
 printf("( 1,内部码 )\n");
    printf("数字及其对应的种别码:\n");
 printf("( 2,二进制码)\n");
 printf("关键字及其对应种别码:\n");
 for(i=0;i<9;i++)
 {
 printf("( %s,%d )\t",test[i].name,test[i].num);
 }
 printf("\n");
 printf("运算符及其对应种别码:\n");
 for(i=0;i<11;i++)
 {
 printf("( %s,%d )\t",oper[i].name,oper[i].num);
 }
 printf("\n");
 printf("分隔符及其对应种别码:\n");
 for(i=0;i<6;i++)
 {
 printf("( %s,%d )\t",cut[i].name,cut[i].num);
 }
 printf("\n");
}

void analyse()
{
 if((fp=fopen(sourcefile,"r"))==NULL)
 {
 printf("文件打开错误 !\n");
 exit(1);
 }
 if((hp=fopen(objectfile,"w"))==NULL)
 {
 printf("文件打开错误 !\n");
 exit(1);
 }

 

 while(ch!=EOF)
 {
 ch=fgetc(fp);
 if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))
 {
  getch(ch);
 }  
 else if((ch>='0')&&(ch<='9'))
 { //如果读取的是数字
  getnum(ch);
 }
     else if((ch==' ')||(ch=='\r')||(ch=='\n')||(ch=='\t'))
 {
  getspace(ch);
 }
 else //其他情况
 {
  getelse(ch);   
 }
  k=0;
  str[k]='\0';
 };
 fclose(fp); //关闭文件
 fclose(hp);
 printf("\n");
}

 

 

void getch(char ch)

while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9')))
{
 str[k]=ch;
 str[++k]='\0';
 ch=fgetc(fp);
}

 for(i=0;i<9;i++)
 {  if(strcmp(str,test[i].name)==0) //测试是否为保留字{    
        { printf("( -, )\n",test[i].num); fprintf(hp,"( -, )\n",test[i].num);
 k=0;
 flag=1;
 int f;
 f=count+1;
 value[f].type=test[i].num;
 break;
 }
 }

if(k!=0)  //否则为标识
{ int m;
    m=change(str);
    printf("(  1,%d ) \n",m);   fprintf(hp,"(  1,%d )\n",m);
k=0;
 
}
fseek(fp,-1L,1);   
}


void getnum(char ch)
{

  int s=0,i=0,a[20],j,m=0;
  char b[20];
 char *p;
 while((ch>='0')&&(ch<='9'))
    {
               str[k]=ch;
 
               str[++k]='\0';
            ch=fgetc(fp);
     } 
    for(p=str;(*p)!='\0';p++)
  s=(*p-48)+s*10;
 while(s>0)
 {
  a[i++]=s%2;
  s=s/2;
 }
 for(j=i-1;j>=0;j--)
 {
  b[m]=a[j]+48;
     m++;
 }
 b[m]='\0';
 k=0;
 fseek(fp,-1L,1);
 
 
  
  printf("(  2,%s ) \n",b);  fprintf(hp,"(  2,%s )\n",b);
  
 
   
 

}

void getspace(char ch)
{
for(; ;)
{
 ch=fgetc(fp);
 if(!((ch==' ')||(ch=='\n')||(ch=='\t')||(ch=='\r')))
 {
  fseek(fp,-1L,1);
  break;
 }
}
}

void getelse(char ch)
{
 switch(ch)
 {
 case ',':
  printf("( 61,  )\n");
  fprintf(hp,"( 61,  )\n");
  break;
 case ';':
  printf("( 62,  )\n");
  fprintf(hp,"( 62,  )\n");
  break;
 case '{':
  printf("( 63,  )\n");
  fprintf(hp,"( 63,  )\n");
  break;
 case '}':
  printf("( 64,  )\n");
  fprintf(hp,"( 64,  )\n");
  break;
 case '(':
  printf("( 65,  )\n");
  fprintf(hp,"( 65,  )\n");
  break;
 case ')':
  printf("( 66,  )\n");
  fprintf(hp,"( 66,  )\n");
  break;
 case '+':
  printf("( 41,  )\n");
  fprintf(hp,"( 41,  )\n");
  break;
 case '-':
  printf("( 42,  )\n");
  fprintf(hp,"( 42, )\n");
  break;
 case '*':
  printf("( 43,  )\n");
  fprintf(hp,"( 43,  )\n");
  break;
 case '/':
  printf("( 44,  )\n");
  fprintf(hp,"( 44,  )\n");
  break;
 case '=':
  str[k]=ch;
  str[++k]='\0';
  ch=fgetc(fp);
  if(ch!='=')
  {
   fseek(fp,-1L,1);
   printf("( 45,  )\n");
   fprintf(hp,"( 45,  )\n");
  }
  else if(ch=='=')
  {
   printf("( 50,  )\n");
   fprintf(hp,"( 50,  )\n");
  }
  break;
 case '>':
  str[k]=ch;
  str[++k]='\0';
  if(ch!='=')
  {
   fseek(fp,-1L,1);
   printf("( 46,  )\n");
   fprintf(hp,"( 46,  )\n");
  }
  else if(ch=='=')
  {
   printf("( 48,  )\n");
   fprintf(hp,"( 48,  )\n");
  }
  break;
 case '<':
  str[k]=ch;
  str[++k]='\0';
  if(ch!='=')
  {
   fseek(fp,-1L,1);
   printf("( 47,  )\n");
   fprintf(hp,"( 47,  )\n");
  }
  else if(ch=='=')
  {
  printf("( 49,  )\n");
  fprintf(hp,"( 49,  )\n");
  }
  break;
 case '!':
  str[k]=ch;
  str[++k]='\0';
  if(ch!='=')
  {
   fseek(fp,-1L,1);
  }
  else if(ch=='=')
  {
  printf("( 51,  )\n");
  fprintf(hp,"( 51,  )\n");
  }
  break;
 }
}
int change(char str[10])
{
 int j;
 for(j=0;j<count+1;j++)
  if(strcmp(str,value[j].str)==0) 
  break; 
  
 if(j<count+1)
 return (value[j].type*100+value[j].no);
 else
 { 
  count++;
  if(flag==-1)
  value[count].type=1;
  for(int i=0;i<9;i++)
   value[count].str[i]=str[i];
  value[count].no=count+1;
        flag=-1;  
  
  return ((value[count].type)*100+value[count].no);
 }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值