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

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

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

#define _KEY_WOED_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_WOED_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("(%d,%s)\n",oneword->typenum,oneword->word);   

               over=oneword->typenum;  

        }

}

//需要用到的自编函数参考实现

//从输入缓冲区读取一个字符到ch中

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;  

        for(i=0;i<7;i++)  

       {   

               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 '=':m_getch();    

                            if(ch=='=')    

                            {     

                                     myword->typenum=39;    

                                     myword->word="==";    

                                     return(myword);  

                             }   

                              retract();   

                              myword->typenum=21;     

                              myword->word="=";      

                              return(myword);   

                              break;   

                    case '+':   

                              myword->typenum=22;       

                              myword->word="+";    

                              return(myword);     

                              break;  

                     case '-':   

                              myword->typenum=23;  

                              myword->word="-";         

                              return(myword);    

                              break;   

                      case '*':   

                              myword->typenum=24;     

                              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=29;         

                              myword->word="]";  

                              return(myword);   

                              break;

                       case '{':  

                               myword->typenum=30;      

                               myword->word="{";

                               return(myword);  

                               break;  

                       case '}':   

                               myword->typenum=31;    

                               myword->word="}";   

                               return(myword);    

                               break;  

                        case ',':   

                                myword->typenum=32;    

                                myword->word=",";    

                                return(myword);     

                                break;

                         case ':':    

                                myword->typenum=33;    

                                myword->word=":";   

                                return(myword);  

                                break;

                          case ';':  

                                 myword->typenum=34;   

                                 myword->word=";";  

                                 return(myword);    

                                 break;  

                          case '>':   

                                  myword->typenum=35;     

                                  myword->word=">";     

                                  return(myword);      

                                  break;  

                          case '<':   

                                  myword->typenum=36;   

                                  myword->word="<";   

                                  return(myword);  

                                  break;  

                          case '!':  

                                  m_getch();  

                                  if(ch=='=')   

                                  {    

                                            myword->typenum=40;  

                                            myword->word="!=";   

                                            return(myword);    

                                  }    

                                  retract();  

                                  myword->typenum=-1;    

                                  myword->word="ERROR";   

                                  return(myword);      

                                  break;  

                          case '\0':   

                                  myword->typenum=1000;  

                                  myword->word="OVER";    

                                  return(myword);   

                                  break;

                          default:   

                                  myword->typenum=-1;      

                                  myword->word="ERROR";   

                                  return(myword);

                                 }

                  }  

}