词法分析器 (SNL语言) 自己写的,拿出来大家一起分享,指正

自己实验课写的一个词法分析程序,针对SNL语言的,有兴趣的看一下,单文件,可能不是很清晰,先对付看吧,有时间我再把他改一下

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

      /**********************类型定义*************************/
      /*标识符(BSF) 1 -------常量(CL) 2---------- 分符隔(FJF)3------ 保留字(BLZ) 10 ------------*/
      /*错误  (CW)  100-----双分界符:=(SFJF)4------程序结束标志(CXJS)6------数组下表(SZXB)7------*/
      /**************************************************************/
struct TOKEN                                                    //token序列结构
{
 int line;                                                   //行号
 char str[20];                                               //用来存字符串本身
 int type;                                                   //存储类型
};
const int maxnum_que=30;                                        //定义队列最多容纳字符
struct queue
{
 void insert(char ch);      //向队列尾插入一个字符
 void ini();                //队列初始化函数
 void delet();            //删除队列头元素
 char view_head();          //查看队列头元素
 bool empty();              //判断队列是否为空
 void clear();              //清空队列
 int count;                 //对里元素计数
 int rear;                  //队尾
 int head;                  //对头
 char a[maxnum_que];
};
bool lookup(char* str);                               //查找是否是保留字
void insert_token(int line,int stat,queue store,TOKEN token[],int count,int p_token);
void send_error(int line,char ch);                               //发送错误消息
void getTokenlist();  
//****************************************************************************************************
const int baol_n=21;
char * baoliuzi[baol_n]={"char","int","var","program","integer","procedure","array","begin","while","if",
"then","else","endwh","end","read","of","record","fi","return","write","type"};                      //个数未必是二十,查找时注意????????????????????????没完
bool lookup(char* str)                                          //查找是否是保留字
{
 int i;
 bool m=false;
 for(i=0;i<baol_n;i++)
 {
  if(strcmp(str,baoliuzi[i])==0)
  {
   m=true;
   break;
  }
 }
 return m;
}
//queue 结构里的函数声明///
void queue::clear()
{
 count=head=rear=0;
}
void queue::ini()
{
 count=head=rear=0; 
}
void queue::delet()
{
 if(count<=0)
  printf("队列里已经没有字符可以删除!!!!!!!!!!!!!!/n");
 else
 {
  head++;
  if(head>=maxnum_que)
   head=head%maxnum_que;
  count--;
 }
}
char queue::view_head()
{
 if(count>0)
  return a[head];
 else
  printf("没有字符可以查看!!!!!!!!!!!/n");
}
bool queue::empty()
{
 if(count<=0)
  return true;
 else
  return false;
}
void queue::insert(char ch)
{
 if(count>=maxnum_que)
  printf("队列已满 缓冲区溢出!!!!!!!!!!!!!!!!!!!/n");
 else
 { 
  a[rear]=ch;
  rear++;
  if(rear>=maxnum_que)
   rear=rear%maxnum_que;
  
  count++;
 }
}
///*******************************************************************************************//
void insert_token(int line,int stat,queue store,TOKEN token[],int count,int p_token,int type)
{
 token[p_token].line=line;                                  
 switch(stat)
 {
 case 1:
  token[p_token].type=1;
  break;
 case 2:
  token[p_token].type=2;
  break;
 case 3:
  token[p_token].type=3;
  break; 
 case 5:
  token[p_token].type=4;
  break;
 case 6:
  token[p_token].type=5;
  break;
 case 7:
  token[p_token].type=6;
  break;
 case 8:
  token[p_token].type=7;
  break;
 }
 int q,m;
 for(int i=0;i<count;i++)
 {
  q=store.head;
  m=q+i;
  if(m>=maxnum_que)
   m%=maxnum_que;
  token[p_token].str[i]=store.a[m];
 }
 token[p_token].str[i]='/0';
 token[p_token].type=type;
 if(type==1)
 {
  if(lookup(token[p_token].str))
   token[p_token].type=10;
 }
}
//**************************************************************************************************
void getTokenlist()                                              //获取token 序列

 char ch;                                                     //用来读取字符 
 int line;                                                    //记录当前行数
 int stat;                                                    //标志状态
 line=1;                                                      //初始在第一行
 stat=0;                                                      //初始状态
 TOKEN token[3000];                                          //长度为10000的结构数组
 int p_token;                                              //标志着token存到第几个
 p_token=0;
 FILE * fp;
    if((fp=fopen("source.txt","r"))==NULL)
  printf("打开文件出错 !!!!!!!!!!!!/n");

 queue linshi,store;                                           //声明两个队列
 linshi.ini();
 store.ini();
    ch=fgetc(fp);
 //printf("%c",ch);


 linshi.insert(ch);
 int type;
 while(stat!=14)
 {
  if(stat!=0)           
  {
   char temp;
   temp=linshi.view_head();
   switch (stat)                                        // 队列操作,给出下一个状态  还是原来的状态则取新的,删除旧的,否则只改变状态
   {
    case 1:
     if(((temp>='A'&&temp<='Z')||(temp>='a'&&temp<='z'))||(temp>='0'&&temp<='9'))//还是标示符
     {
      store.insert(temp);
      //printf("count=%d/n",store.count);
      linshi.delet();
      ch=fgetc(fp);
      if(ch!=EOF)
      {
       //printf("%c",ch);
      
       linshi.insert(ch);
      }
      else
       stat=14;
     }
     else                                              //不是标示附
     {
      stat=13;                                      //转到结束状态
      type=1;
     }
     break;
    case 2:
     if(temp>='0'&&temp<='9')                           //还是数字
     {
      store.insert(temp);
      linshi.delet();
      ch=fgetc(fp);
      if(ch!=EOF)
      {
       //printf("%c",ch);
      
       linshi.insert(ch);
      }
      else
       stat=14;
     }
     else                                               //不是数字,转到结束状态
     {
      stat=13;
      type=2;
     }
     break;
    case 3:
     stat=13;
     type=3;
     break;
    case 4:
     if(temp=='=')
     {
      stat=5;
      store.insert(temp);
      linshi.delet();
      ch=fgetc(fp);
      if(ch!=EOF)
      {
       //printf("%c",ch);
      
       linshi.insert(ch);
      }
      else
       stat=14;
     }
     else
     {
      send_error(line,temp);
      stat=13;
      type=100;                                       //错误状态
     }
     break;
    case 5:
     stat=13;
     type=4;
     break;
    case 6:
     if(temp!='}')
     {
      linshi.delet();
      ch=fgetc(fp);
      if(ch!=EOF)
      {
       //printf("%c",ch);
       if(ch=='/n')
        line++;
       linshi.insert(ch);
      }
      else
       stat=14;     
     }
     else
     {
      linshi.delet();
      ch=fgetc(fp);
      if(ch!=EOF)
      {
       //printf("%c",ch);
      
       linshi.insert(ch);
      }
      else
       stat=14; 
      stat=13;
     }
      break;
    case 7:
     if(temp=='.')
     {
      stat=8;
      store.insert(temp);
      linshi.delet();
      ch=fgetc(fp);
      if(ch!=EOF)
      {
       //printf("%c",ch);
      
       linshi.insert(ch);
      }
      else
       stat=14;
     }
     else
     {
      stat=13;                             ///程序结束标志
      type=6;
     }  
     break;
    case 8:
     stat=13;
     type=7;
     break;   
   }
  }
  if(stat==0)                   //如果是s0的话则表明重新开始读                          要给出下一个状态
  {
   char c=linshi.view_head();
   if((c>='A'&&c<='Z')||(c>='a'&&c<='z'))// 说明是标示附
   {
    stat=1;
    store.insert(c);
    linshi.delet();
    ch=fgetc(fp);
    if(ch!=EOF)
    {
     //printf("%c",ch);
     
     linshi.insert(ch);
    }
    else
     stat=14;
   }
   else if(c>='0'&&c<='9')//说明是数字
   {
    stat=2;
    store.insert(c);
    linshi.delet();
    ch=fgetc(fp);
    if(ch!=EOF)
    {
     //printf("%c",ch);
     
     linshi.insert(ch);
    }
    else
     stat=14;
   }
   else if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c==';'||c=='['||c==']'||c=='='||c=='<')
   {
    stat=3;
    store.insert(c);
    linshi.delet();
    ch=fgetc(fp);
    if(ch!=EOF)
    {
     //printf("%c",ch);
     
     linshi.insert(ch);
    }
    else
     stat=14;
   }
   else if(c==' '||c=='/n'||c=='/t')
   {
    if(ch=='/n')
     line++;
    stat=13;
    linshi.delet();
    ch=fgetc(fp);
    if(ch!=EOF)
    {
     //printf("%c",ch);
     
     linshi.insert(ch);
    }
    else
     stat=14;
   }
   else if(c==':')
   {
    stat=4;
    store.insert(c);
    linshi.delet();
    ch=fgetc(fp);
    if(ch!=EOF)
    {
     //printf("%c",ch);
     
     linshi.insert(ch);
     
    }
    else
     stat=14;
   }
   else if(c=='{')
   {
    stat=6;
    //store.insert(c);
    linshi.delet();
    ch=fgetc(fp);
    if(ch!=EOF)
    {
     //printf("%c",ch);
     linshi.insert(ch);
    }
    else
     stat=14;
   }
   else if(c=='.')
   {
    stat=7;
    store.insert(c);
    linshi.delet();
    ch=fgetc(fp);
    if(ch!=EOF)
    {
     //printf("%c",ch);
     
     linshi.insert(ch);
    }
    else
    {
     stat=14;
     
    }
   }
   else                                             //其它的类似逗号之类的错误
   {
    send_error(line,c);
    linshi.delet();
    ch=fgetc(fp);
    stat=13;
    if(ch!=EOF)
    {
     //printf("%c",ch);
     
     linshi.insert(ch);
    }
    else
     stat=14;

   }
  }
  if(stat==13)
  {
   if(!store.empty())
   {
    insert_token(line,stat,store,token,store.count,p_token,type);
    
    p_token++;
    
   }   
   store.clear();    
   stat=0;
  }
  if(stat==14)
  {
   if(!store.empty())
   {
    insert_token(line,stat,store,token,store.count,p_token,type);
    store.clear();
    p_token++;
    //break;
   }
  }
 }
 if(fclose(fp)==EOF)
  printf("关闭文件出错  !!!!!!!!!!! /n");

 FILE *fpp=fopen("token.txt","w");

 
 /*printf("/******************************类型定义********************************/n"); //屏幕输出
    printf("/*标识符1-----常量2------分符隔3------保留字10-------错误 100------/n");
 printf("双分界符:=4-----注释头符号5-----程序结束标志6------数组下表7------*/n");
    printf("/********************************************************************/n");
 printf("行号 类型  字符串/n");
 for(int j=0;j<p_token;j++)
  printf("%d    %d    %s     /n",token[j].line,token[j].type,token[j].str);*/
 fprintf(fpp,"/******************************类型定义********************************//n");
    fprintf(fpp,"/*标识符1-----常量2------分符隔3------保留字10-------错误 100-------/n");
 fprintf(fpp,"双分界符:=4-----注释头符号5-----程序结束标志6------数组下表7------*//n");
    fprintf(fpp,"/********************************************************************//n");
 fprintf(fpp,"行号 类型  字符串/n");
 for(int p=0;p<p_token;p++)
  fprintf(fpp,"%d    %d    %s     /n",token[p].line,token[p].type,token[p].str);
}
void send_error(int line,char ch)
{
 printf("在        第 %d   行          字符  %c        有错误!!!!!!!!!!!!!!!!!!!!!!!!!!!/n",line,ch);
}


//****************************************************************************************************
void main()
{
 getTokenlist();
}

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值