#include<stdio.h>     //包含库所用的某些宏和变量

#include<stdlib.h>    //包含库

#include<string.h>    //包含字符串处理库

#define _KEY_WORD_END "waiting for your expanding"     //定义关键字结束标志

typedef struct  

{

         int typenum;  

         char * word;

}WORD;

char input[255];      //输入换缓冲区

char token[255]="";   //单词缓冲区

int p_input;          //输入换缓冲区指针

int p_token;          //单词缓冲区指针

char ch;              //当前所读的字符

char *rwtab[]={"begin","if","then","while","do","end",_KEY_WORD_END};        //C语言关键字

WORD * scaner();    //词法扫描函数,获得关键字

main()

{  

         int over=1;  

         WORD *oneword;  

         oneword=(WORD *)malloc(sizeof(WORD));  

         printf("Enter Your words(end with #):");   //读入源程序字符串到缓冲区,以#结束,允许多行输入    

         scanf("%[^#]s",input);                         

         p_input=0;  

         printf("Your words:%s\n\n",input);

         while(over<1000&&over!=-1)  

        {   

               oneword=scaner();   

               printf("单词符号:%s\t种别码:%d\n",oneword->word,oneword->typenum);   

               over=oneword->typenum;  

        }

}


char m_getch()

{  

            ch=input[p_input];

            p_input=p_input+1;

            return (ch);

}

//去掉空白字符

void getbc()

{  

        while(ch==' '||ch==10)

       {  

        ch=input[p_input];  

        p_input=p_input+1;  

        }

}

//拼接单词

void concat()

{  

        token[p_token]=ch;  

        p_token=p_token+1;

        token[p_token]='\0';

}

//判断是否字母

int letter()

{  

         if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')

                 return 1;  

         else

                 return 0;

}

//判断是否数字

int digit()

{  

         if(ch>='0'&&ch<='9')   

                 return 1;  

         else   

                 return 0;

}

//检索关键字表格

int reserve()

{

        int i=0;  

        while(strcmp(rwtab[i],_KEY_WORD_END))  

        {   

               if(!strcmp(rwtab[i],token))   

              {    

                        return i+1;  

              }  

               i=i+1;

        }  

        return 10;

}

//回退一个字符

void retract()

{  

       p_input=p_input-1;

}
WORD *scaner()

{  

         WORD *myword ; 

         myword=(WORD *)malloc(sizeof(WORD));

         myword->typenum=10;

         myword->word="";  

         p_token=0;  

         m_getch();  

         getbc();

         if(letter()){  
             while(letter()||digit()){     

                 concat();    

                 m_getch();

             }   

             retract();      

             myword->typenum=reserve();    

             myword->word=token;

             return(myword);  

         }
         else if(digit()){   

             while(digit())  

                   {   

                           concat();  

                           m_getch();  

                     }  

                      retract();  

                      myword->typenum=20;   

                      myword->word=token;  

                      return(myword);

             }  

              else  

             {  

                      switch(ch)   

                     {   
                      case '+':   

                          myword->typenum=13;       

                          myword->word="+";    

                          return(myword);     
                          
                          break;  

                      case '-':   

                          myword->typenum=14;  

                          myword->word="-";         

                          return(myword);    

                          break;   

                      case '*':   

                          myword->typenum=15;     

                          myword->word="*";   

                          return(myword);  

                          break;

                      case '/':    

                          myword->typenum=16;  

                          myword->word="/";   

                          return(myword);   

                          break;  

                      case ':':  m_getch();

                          if(ch=='='){

                              myword->typenum=18;     

                              myword->word=">=";     

                              return(myword);

                          }

                          retract();   

                          myword->typenum=17;    

                          myword->word=":";   

                          return(myword);  

                          break;

                      case '<':  m_getch();

                          if(ch=='='){

                              myword->typenum=21;     

                              myword->word="<=";     

                              return(myword);
                            
                          }
                          
                          else if(ch=='>'){

                              myword->typenum=22;     

                              myword->word="<>";     

                              return(myword);
                              
                          }

                          retract();  

                          myword->typenum=20;   

                          myword->word="<";   

                          return(myword);  

                          break; 
                              
                      case '>':  m_getch();

                          if(ch=='='){

                              myword->typenum=24;     

                              myword->word=">=";     

                              return(myword);

                          }

                          retract();
                              
                          myword->typenum=23;     

                          myword->word=">";     

                          return(myword);      

                          break;
                          
                      case '=':   

                          myword->typenum=25;     

                          myword->word="=";   

                          return(myword);  

                          break;

                      case ';':  

                          myword->typenum=26;   

                          myword->word=";";  

                          return(myword);    

                          break;
                              
                      case '(':   

                          myword->typenum=27;     

                          myword->word="(";   

                          return(myword);  

                          break;

                      case ')':   

                          myword->typenum=28;     

                          myword->word=")";   

                          return(myword);  

                          break;
                      
                      case '#':   

                          myword->typenum=0;  

                          myword->word="OVER";    

                          return(myword);   

                          break;

                      default:   

                                  myword->typenum=-1;      

                                  myword->word="ERROR";   

                                  return(myword);

                                 }

                  }  

}