關於簡單c的詞法分析器

來源:互聯網
上載者:User

這段源碼能在linux下運行!!! 能識別小數

 

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
/*#define  NULL          0*/

/*    自訂變數      */
#define  sy_if         0
#define  sy_then       1
#define  sy_else       2
#define  sy_while      3
#define  sy_begin      4
#define  sy_do         5
#define  sy_end        6
#define  a             7
#define  semicolon     8
#define  e             9
#define  jinghao       10
#define  S             11
#define  L             12

#define  tempsy        15
#define  EA            18    /*E end*/
#define  EO            19    /*E or*/

#define  plus          34
#define  times         36
#define  becomes       38
#define  op_and        39
#define  op_or         40
#define  op_not        41
#define  rop           42

#define  lparent       48     //左括弧
#define  rparent       49    //有括弧
#define  ident         56     //變數
#define  intconst      57 

char ch='/0';  /*儲存讀入當前字元*/
int count=0;        //詞法分析緩衝結果數
int count1=0;
static  char spelling[10]={""};    /*存放識別的字*/
static  char line[81]={""};        /*讀入一行字元到緩衝區*/
char *pline;    /*字元緩衝區指標*/

/*struct array{
        int sy11;
        int pos11;
         }A[100]      cunfangcifajieguo*/

static char ntab1[100][10];  /*存放變數表*/

struct rwords{
        char sp[10];
        int  sy;    };   /*存放保留字,sp為保留字,sy為保留字種別*/

struct rwords reswords[10]={    {"if",sy_if},
                                {"do",sy_do},
                                {"else",sy_else},
                                {"while",sy_while},
                                {"then",sy_then},
                                {"begin",sy_begin},
                                {"end",sy_end},
                                {"and",op_and},
                                {"or",op_or},
                                {"not",op_not}  };

struct aa{   int sy1;     //種別
             int pos;     /*內碼值*/
            }buf[1000];  /*詞法分析結果的緩衝區  來源程式*/

int nlength=0;  /*記錄變數表的長度*/

int lnum=0;  /*來源程式長度*/

int tt1=0;   /*變數表的起始位置*/
FILE *cfile;
FILE *mfile;

/*從檔案讀一行到緩衝區*/
void readline()
{
   char ch1;
   pline=line;
   ch1=getchar(cfile); //windows
  // ch1 = fgetc(cfile);          // Linux
   while(ch1!='/n')
   {   *pline=ch1;
       pline++;
       ch1=getchar(cfile);   // Windows
       //ch1 = fgetc(cfile);    // linux
   }
   *pline='/0';
   pline=line;
}                       /* read a line in the buffer */

/*從緩衝區讀一個字元*/
void readch()
{  if(ch=='/0')
   {   readline();
       lnum++;
    }
    ch=*pline;
    pline++;
}                     /* read a char from buffer */

/*識別(標識符)字串是否已收錄進變數表 :若不存在就返回-1 反之 */
int find(char spel[])
{
    int ss1=0;
    int ii=0;
    while((ss1==0)&&(ii<nlength))
    {  if(!strcmp(spel,ntab1[ii]))
          ss1=1;
       ii++;   //順序執行
    }
    if(ss1==1) return ii-1;
    else return-1;
}

// 識別標識符
void identifier()
{  int iii=0,j,k;
   int ss=0;
   k=0;
   do   //只識別了小寫字母 和 數字
   {  spelling[k]=ch;
      k++;
      readch();
   }while(((ch>='a')&&(ch<='z'))||((ch>='0')&&(ch<='9')));
   pline--;                 // 回退
   spelling[k]='/0';       // 由於do while 中 k已加了一個  1  所以這裡用'/0'做結束符
   while((ss==0)&&(iii<10))    //確認是否在保留字中(尋找)
     {  if(!strcmp(spelling,reswords[iii].sp)) //strcmp相等或小於 返回 0
  ss=1;   // 如果能找到保留字 則ss值變 1 ,跳出迴圈
      iii++;
   }
          /* guanjianzipipei*/
   if(ss==1)   //若為保留字         
   {    buf[count].sy1=reswords[iii-1].sy;   //把保留字放在分析結果緩衝區
   }
   else
   {  buf[count].sy1=ident;     //標識符的種別
      j=find(spelling);
      if(j==-1)            //若不存在
      {  buf[count].pos=tt1;   //這裡用變數在變數表的位置 來標記內碼值
         strcpy(ntab1[tt1],spelling); //複製
         tt1++;                  //位置加一
         nlength++;              // 變數表的長度加一
      }
      else buf[count].pos=j;  // 若已存在這樣的變數 ,內碼值為 第一個出現的變數的位置
   }
   count++;            //詞法分析緩衝結果數 加一
   for(k=0;k<10;k++)  spelling[k]=' ';  //清空
}               /*shuzideshibie*/
/*
void number()  // 識別常數
{   int ivalue=0;
    int digit;
    // 字元轉換為數字
 do
    {  digit=ch-'0';       // [0-9]的大小
       ivalue=ivalue*10+digit;   //常數的值
       readch();                  // 讀下一個字元
    }while((ch>='0')&&(ch<='9')); 
    buf[count].sy1=intconst;   //常數的種別
    buf[count].pos=ivalue;      // 常數值
    count++; 
    pline--; // 回退
}            
*/

void number()
{ float invalue = 0.0,index = 0.0,digit = 0.0;
  int flag = 0;
    do
    { 
      if((ch == '.')&&(flag = 0))
 {
   flag++;
   readch();
   continue;
 }
      if((ch >= '0')&&(ch <= '9'))
 {
   if(flag)
     {
       index = index*0.1;
       digit = ch - '0';
       invalue = invalue + digit*index;
     }
   else
     {
       digit = ch - '0';
       invalue = invalue*10 + digit;
     }
 }
      readch();
    }while(((ch >= '0')&&(ch <= '9'))||(ch == '.'));
  buf[count].sy1 = intconst;
  buf[count].pos = invalue;
  count++;
  pline--;
}

//掃描主函數
void scan()
{
   while(ch!='~')
   {  switch(ch)
      {  case' ':break;
         case'a':
         case'b':
         case'c':
         case'd':
         case'e':
         case'f':
         case'g':
         case'h':
         case'i':
         case'j':
         case'k':
         case'l':
         case'm':
         case'n':
         case'o':
         case'p':
         case'q':
         case'r':
         case's':
         case't':
         case'u':
         case'v':
         case'w':
         case'x':
         case'y':
         case'z':
         identifier();
         break;
         case'0':
         case'1':
         case'2':
         case'3':
         case'4':
         case'5':
         case'6':
         case'7':
         case'8':
         case'9':
         number();
         break;
         case'<':
         readch();
         if(ch=='=')
            buf[count].pos=0;
         else
         {  if(ch=='>')buf[count].pos=4;
            else
            {  buf[count].pos=1;
               pline--;
            }
         }
         buf[count].sy1=rop;
         count++;
         break;
         case'>':
         readch();
         if(ch=='=')
         {  buf[count].pos=2;
         }
         else
         {  buf[count].pos=3;
            pline--;
         }
         buf[count].sy1=rop;
         count++;
         break;
         case'(':
         buf[count].sy1=lparent;
         count++;
         break;
         case')':
         buf[count].sy1=rparent;
         count++;
         break;
         case'#':
         buf[count].sy1=jinghao;
         count++;
         break;
         case'+':
         buf[count].sy1=plus;
         count++;
         break;
         case'*':
         buf[count].sy1=times;
         count++;
         break;
         case':':
         readch();
         if(ch=='=')
         buf[count].sy1=becomes;
         count++;
         break;
         case'=':
         buf[count].sy1=rop;
         buf[count].pos=5;
         count++;
         break;
         case';':
         buf[count].sy1=semicolon;
         count++;
         break;
      }
   readch();
   }
   buf[count].sy1=-1;
   buf[count].pos=-1;
}

void disp1()
{  int temp1=0;
   printf("/n*********cifafenxijieguo**********/n");
   for(temp1=0;temp1<=count;temp1++)
   {
      printf("%d/t%d/n",buf[temp1].sy1,buf[temp1].pos);
      if(temp1==20)
      {  printf("Press any key to continue..../n");
         getchar();
      }
   }
   getchar();
}

void disp4()

{  int temp1=0;
   mfile=fopen("cf.txt","w");
   printf("/n******zidongshenchengwenjian*****/n");
   for(temp1=0;temp1<count;temp1++)
       fprintf(mfile,"%d/t%d/n",buf[temp1].sy1,buf[temp1].pos);
   fprintf(mfile,"~/n");
}

void disp3()
{
   int tttt;
   mfile=fopen("bl.txt","w");
   printf("/n/n%d,%d/n",lnum,count);
   getchar();
   printf("/n*********bianliaangbiao**********/n");
   for(tttt=0;tttt<tt1;tttt++)
   {   printf("%d/t%s/n",tttt,ntab1[tttt]);
       fprintf(mfile,"%d/t%s/n",tttt,ntab1[tttt]);
   }
   fprintf(mfile,"~/n");
   getchar();
}

int main()
{
   if((cfile=fopen("2.txt","r"))!=NULL)
      printf("open/n");
   else
      printf("close/n");
   readch();
      printf("%c/n",ch);
   scan();
   disp1();
   disp4();
   disp3();
   return 0;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.