⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccc.c

📁 是个分析器
💻 C
字号:


#include "string.h"
#include "stdio.h"

#define  BMaxlen  10000     //定义缓冲区的最大长度
#define  WMaxlen  11        //用来定义取出的标识符的最大长度,如果长度大于这个值,则接下去的字忽略不计
#define  KEY_No    8        //定义要比较的关键字的个数
#define  Sign_No  12       //定义要比较的符号的个数
#define  Limit_No  6       //定义要比较的界符的个数
#define  Maxtype  '5'       //定义单词的总类型共有5种
#define  Longtype  '8'       //定义单词不合法且过长时的类型
#define  Errtype  '7'       //定义单词不合法但没超过长度的类型




//*********************************************
//函数说明
int scanner();//用来从缓冲区中取一个字符
void insource();//用来把文件中的内容放到缓冲区中
char getsym();//从缓冲区中取一个单词
//**********************************************


char Str[BMaxlen];//建立缓冲区
char Filename[100];//定义存放路径名的字符串
int  pStr=-1;     //用来表示从缓冲区取字母时的指针,定义为-1,为使以下的程序++pStr可以先指到缓冲区的第一个字母
char ch;        //用来表示从缓冲区中取出的一个字母
char *KEY[KEY_No]={{"if"},{"int"},{"for"},{"while"},{"do"},{"return"},{"break"},{"continue"}};
char *Sign[Sign_No]={{"+"},{"-"},{"*"},{"/"},{"%"},{"="},{"<"},{">="},{"<="},{"!="},{"=="},{">"}};
char *Limit[Limit_No]={{","},{";"},{"{"},{"}"},{"("},{")"}};
int  Fbuffer;//标志缓冲区中是否还有字母,如果没有的话,则Fbuffer的值为-1;如果还有的话,则其值为1
char Word[WMaxlen];//用来标识标识取出的单词,且其长度不超过
char CType;//用来标识得到的单词的类型
char Lasttype;//用来标识是其前面的单词的类型,如果是
char ty;//定义在调用取单词后取出的单词的类型


int main()
{
    FILE *fp;
    int n=100;
    printf("Please input the filename");//提示用户键入路径名

     gets(Filename);
    fp=fopen(Filename,"r");
    while (fp==NULL)//若打入的文件没有,则提示继续打入有效的路径名
    {
        printf("Sorry,the file isn't existent");
        printf("Please use another file");
        gets(Filename);
        fp=fopen(Filename,"r");
    }

    insource();//把文件中的内容放入缓冲区
    fclose(fp);
    printf("\n");

    scanner();//从文件中取出第一个字符中,并存在ch变量中
    Fbuffer=1;//初始化定义,认为缓冲区中还有字母

    while(Fbuffer!=-1)
    { 
        ty=getsym();//调用getsym()函数,得到一个单词,并返回此单词的类型

        if(ty==Errtype)/*单词不合法,长度没超过WMaxlen,显示其具体内容*/
            printf("iderror    ");
        else 
            if (ty==Longtype)//单词不合法,给出模糊描述
                printf("id is too long    ");
            else 
                if (ty<=Maxtype)//单词合法,输出其类型,以及内容
                {
                    printf("%s",ty);
                    printf("%s",Word);
                    printf(")");
                }
    }
        
    printf("\n");
    return  0;  
}


//用来从缓冲区中取一个字符,如果成功,则返回1,否则为-1
int scanner()
{ 
    ch=Str[++pStr];
    if (ch=='\0') return(-1);//当取出的字符是'\0',则表明缓冲区中已无字符,返回值为-1
    else return(1);
}


//用来把文件中的内容放到缓冲区中,以'\0'作为标识符
void insource()
{
    int i=0;//用来表示放入缓冲区数组的指针
    char ch; //表示从文件中读取的一个字符
    ch=fgetc(Filename);//根据输入的路径名来打开这个文件
    while (ch!=EOF)
        Str[i++]=ch;
    Str[i]='\0'; //以'\0'作为标识符
}



//从缓冲区中取一个单词
char getsym()
{
   int flag=0;//用来表示取出的单词是否为关键词,如果是则flag的值为true,否则为false
    int k=-1;       //表示取出的字符放在单词数组的指针
    CType='0';      //预先定义的取出的单词的类型
    Lasttype='0';   //初始化先前的类型,此变量为判断正负数用

    while (ch<=32 && ch>0)//去掉不能显示的字符
        Fbuffer=scanner();

    if (ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z')//取出标识符或者是关键词
    {
        k=-1;
        while(1)//取出的单词长度不超过WMaxlen,如果超过,则其后的字符无效
        {  
            if((++k)<WMaxlen)//(++k)为了使取出的单词最长为WMaxlen
            {
                Word[k]=ch;
            }
            Fbuffer=scanner();
              
            //如果取出的当前的字符不是字母或是数字,则此次取单词结束
            if  (!(ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z'||ch>='0' && ch<='9'))
                break; 
        }
        Word[++k]='\0';//以'\0'标识取出单词的结束,以方便后面的判断此单词是标识符还是关键词

        for (int i=0;i<KEY_No;i++) //用来判断取出的当前单词是不是关键词
            if (strcmp(KEY[i],Word)==0)
            { 
                flag=1;
                break;
            }
            
        if (flag)
            CType='1';//如果是关键词,则把此单词的类型定义为1型
        else 
            CType='2';      //否则是标识符,其类型为2
    
    }       
    else if (ch>='0' && ch<='9')//判断是不是为整数
    {  
        Word[++k]=ch;
        Fbuffer=scanner();
        while(flag)//如果是数字,则一直接受,且定义它的类型为3
            if(ch>='0' && ch<='9')
            {
                Word[++k]=ch;
                Fbuffer=scanner();
            }
            else  {CType='3';break;}//不是数字则跳出循环
            //如果以字母开头,且长度不超过WMaxlen,且下面跟有字母,则此整数非法,输出类型为8,在主程序中输出出错信息
            if (k<WMaxlen)
                if (ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z')
                {
                    Word[++k]=ch;
                    Fbuffer=scanner();
                    //取这个非法整数的单词,其中可包含英文字母和数字
                    while (ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z'|| ch>='0' && ch<='9'||Fbuffer==-1)
                        if (k<WMaxlen)
                        {
                            Word[++k]=ch;
                            Fbuffer=scanner();
                        }
                        else 
                        {
                            Fbuffer=scanner();
                            k++;
                        }
                        if (k>WMaxlen)//如果长度大于取出单词定义的最大长度,则返回类型为8,在主程序中打出出错信息
                            CType=Longtype;
                        else CType=Errtype;//否则返回类型7,在主程序出错,并明确写出此单词的具体内容
        }
            Word[++k]='\0'; 
    }
    else if (ch=='+'||ch=='-'||ch=='*'||ch=='/')//取出是运算符号的单词
    {   
        Word[++k]=ch;
        if (ch=='+' || ch=='-')//如果是+号或者是-号,则还要判断是不是正负数
            if (Lasttype=='6')//判断其取出的当前字母的前一个单词是6号类型的,即是<、>、<=、>=、==、=时则可判断现在取出的是整数
            {   
            
                Fbuffer=scanner();
                while(ch>='0' && ch<='9')//取出整数
                {
                    Word[++k]=ch;
                    Fbuffer=scanner();
                }
                CType='3';//如果正负整数,则直接返回类型为3,则表示此单词为整数
                return(CType);
         
            }
            else Fbuffer=scanner();//如果不是整数,则定义当前取出的单词是运算符,定义此类型为4
            Word[++k]='\0';
            CType='4';
    }
    else if (ch=='>'||ch=='<'||ch=='='||ch=='!')//取出运算符的另几类,即<、<=、>、>=、==、=、!=
    {    
        Word[++k]=ch;Fbuffer=scanner();
        if( ch=='=')//判断是不是<=、>=、==、!=
        { 
            Word[++k]=ch;
            Fbuffer=scanner();
        }
        Word[++k]='\0';
        for (int i=0;i<Sign_No;i++)//判断取出的单词是不是运算符
            if (strcmp(Sign[i],Word)==0) 
            { 
                flag=1;
                break;
            }
            if (flag)  CType='4';
            
            Lasttype='6';
        
    } 
    else if (ch==','||ch==';'||ch=='{'||ch=='}'||ch=='('||ch==')')//判断当前取出的单词是不是界符,如果是界符,则定义其类型为5
    {     
        CType='5';
        Word[++k]=ch;
        Word[++k]='\0';
        Fbuffer=scanner();
    }

    return(CType);
}

    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -