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

📄 cifa.c

📁 编制一个词法分析程序
💻 C
字号:
/********************************************/
/*  词法分析程序                            */
/*  作者:李广军                            */
/*  学号:1402093120                        */
/*  计算机科学与信息工程系 0201班           */
/*  Copyright (C) 2005 by loverlife workroom*/
/*  ALL Rights Reserved.                    */
/********************************************/  


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int key_count;
int id_count;

/**********************************************/
/*  初始化函数                                */
/*1 保留字、2 标识符、3 常数、4 运算符、5 界符*/
/**********************************************/
void initialize()
{
    char *keywords[] = {" ",                    /*0号单元不用*/
	                    "auto","break","case","char","const",
					    "continue","default","do","double","else",
				   	    "enum","extern","float","for","goto",
					    "if","int","long","register","return",
					    "short","signed","sizeof","static","struct",
					    "switch","typedef","union","unsigned","void",
					    "volatile","while"};     
	                     /*C语言所有关键字,共32个*/


	char *operators[] = {" ",
		                 "(", ")", "[", "]", ".", "->", "!", 
						 "~", "++", "--", "-", "&", "*", "(type)",
						 "sizeof()", "/", "%", "+", "<<", ">>", "<",
						 "<=", ">", ">=", "==", "!=", "^", "|",
						 "&&", "||", "?:", "=", "+=", "-=", "*=", 
						 "/=", ","};
	                     /*运算符,共37个*/

	char *seperators[] = {" ",
	                   	  ";", "{", "}", "#", ".", "'"};
	                     /*限界符,共7个*/

    FILE *fp;
    int i;
    char c;

    fp = fopen("E:\\cifa\\keyword.txt", "w");
    for(i = 1; i <= 32; i ++)
       fprintf(fp, "%s\n", keywords[i]);
    fclose(fp);               /*初始化关键字表*/


    fp = fopen("E:\\cifa\\operator.txt", "w");
    for(i = 1; i <= 37; i ++)
       fprintf(fp, "%s\n", operators[i]);
	fclose(fp);                /*初始化运算符表*/

    fp = fopen("E:\\cifa\\seperator.txt", "w");
    for(i = 1; i <= 6; i ++)
       fprintf(fp, "%s\n", seperators[i]);
    c = '"';
    fprintf(fp, "%c\n", c);
    fclose(fp);               /*初始化限界符表*/


    fp = fopen("E:\\cifa\\identity.txt", "w");
    fclose(fp);               /*初始化标识符表*/


    fp = fopen("E:\\cifa\\constant.txt", "w");
    fclose(fp);               /*初始化常数表*/


    fp = fopen("E:\\cifa\\output.txt", "w");
    fclose(fp);               /*初始化输出文件*/
}

/********************************************/
/*  查表或造表函数                          */
/********************************************/
int find(char *buf, int type, int command)
{
    int number = 0;
    FILE *fp;
    char c;
    char temp[30];
    int i = 0;
    switch(type)
    {
	case 1: fp = fopen("E:\\cifa\\keyword.txt", "r");break;
	case 2: fp = fopen("E:\\cifa\\identity.txt", "r");break;
	case 3: fp = fopen("E:\\cifa\\constant.txt", "r");break;
    case 4: fp = fopen("E:\\cifa\\operator.txt", "r");break;
	case 5: fp = fopen("E:\\cifa\\seperator.txt", "r"); 
    }

    c = fgetc(fp);
    while(c != EOF)
    {
		while(c != '\n')
        {
            temp[i++] = c;
            c = fgetc(fp);
        }
        temp[i] = '\0';
        i = 0;
        number ++;
        if(strcmp(temp,buf) == 0)
        {
		    fclose(fp);
			return(number);        /*若找到,返回在相应表中的序号*/
        }
        else
           c = fgetc(fp);
    }

    if(command == 1)
     {
	     fclose(fp);
		 return(0);                /*找不到,当只需查表,返回0,否则还需造表*/
     }
	
    fclose(fp);
	switch(type)
	{
	 case 1: fp = fopen("E:\\cifa\\keyword.txt", "a");break;
	 case 2: fp = fopen("E:\\cifa\\identity.txt", "a");id_count++;break;
	 case 3: fp = fopen("E:\\cifa\\constant.txt", "a");break;
     case 4: fp = fopen("E:\\cifa\\operator.txt", "a");break;
     case 5: fp = fopen("E:\\cifa\\seperator.txt", "a"); 
	}

	fprintf(fp, "%s\n", buf);
    fclose(fp);
    return(number+1);             /*造表时,将字符串添加到表尾并返回序号值*/
}

/*******************************************/
/*  数字串处理函数                         */
/*******************************************/
void constant_manage(char *buffer)
{
    FILE *fp;
	int result;
    result = find(buffer, 3, 2);       /*先查常数表,若找不到则造入常数表并返回序号值*/

    fp = fopen("E:\\cifa\\output.txt", "a");
	fprintf(fp, "3\t\t\t%s\t\t\t%d\n", buffer, result);
	fclose(fp);                                 /*写入输出文件*/
}


/*******************************************/
/*    字符串处理函数                       */
/*******************************************/
void char_manage(char *buffer)
{
    FILE *fp;
    int result;
    result = find(buffer, 1, 1);                    /*先查关键字表*/
    fp = fopen("E:\\cifa\\output.txt", "a");

    if(result != 0)
	{
		fprintf(fp, "1\t\t\t%s\t\t\t%d\n", buffer, result);    /*若找到,写入输出文件*/
		key_count++;
	}
    else
    {
        result = find(buffer, 2, 2);
		               /*若找不到,则非关键字,查标识符表,还找不到则造入标识符表*/
        fprintf(fp, "2\t\t\t%s\t\t\t%d\n", buffer, result); /*写入输出文件*/
    }                                            
    
    fclose(fp);
}


/******************************************/
/*  出错处理函数                          */
/******************************************/
void error_manage(char error, int lineno)
{
	FILE *fp;
	fp = fopen("E:\\cifa\\output.txt", "a");
    fprintf(fp, "error: %c ,line %d\n", error, lineno); /*报告出错符号和所在行数*/
	fclose(fp);
}

/*******************************************/
/*  扫描输入源程序                         */
/*******************************************/
void scanner()
{
    FILE *fp, *fp1, *fp2;
    char filename[30];
    char ch;
    int  i = 0, line = 1;
    int count, result, errorno = 0;
	char array[30];
    char *word;

	printf("\nPlease input the file name:");
    scanf("%s", filename);
    if((fp1 = fopen(filename, "r")) == NULL)
    {
        printf("Cannot open file!");
        exit(0);
    }
  
    ch = fgetc(fp1);

    while(ch != EOF)            /*按字符依次扫描源程序,直至结束*/
    {
        i = 0;

        if( ((ch>='A') && (ch<='Z')) || ((ch>='a') && (ch<='z')) || (ch=='_') )
        {                                      /*以字母或下划线开头*/
            while( ((ch >= 'A')&&( ch <= 'Z' )) || ((ch>='a')&&(ch<='z')) ||
				   (ch == '_') || ((ch >= '0')&&(ch <= '9')) )
            {
                array[i++] = ch;
                ch = fgetc(fp1);
            }                                 /*字母数字下划线的组合*/

            word = (char *)malloc( (i+1)*sizeof(char) );
			memcpy(word, array, i);           /*将array中的前i个字符拷贝到指针word中*/
			word[i] = '\0';

            char_manage(word);                  /*字符串处理*/

			word=NULL;
            free(word);
            if(ch != EOF)
			   fseek(fp1, -1L, SEEK_CUR);       /*文件指针定位在前的一个位置*/
        }/*判断关键字、标识符结束*/

        else if(ch >= '0' && ch <= '9')            /*以数字开头*/
        {           
            while( ((ch>='0')&&(ch<='9')) || ch == '.' 
				   || ch == 'e' || ch == 'E' || ch == '-')
            {
                array[i++] = ch;
                ch = fgetc(fp1);
            }                                   /*数字的组合*/

            word = (char *)malloc( (i+1)*sizeof(char) );
			memcpy(word, array, i);
			word[i] = '\0';
            constant_manage(word);
     
            word=NULL;
            free(word);
			if(ch != EOF)
			   fseek(fp1, -1L, SEEK_CUR);
        }/*判断数字组合结束*/

        else if( (ch == ' ') || (ch == '\t') )
			;                                /*滤除空格符和水平制表符*/

		else if(ch == '\n')
			line++;                          /*滤除回车符,行数加1*/

	
		else if(ch == '/')                   /*过滤注释*/
        {                                    
			ch = fgetc(fp1);

			if(ch == '=')                     /* 若为'/='符号*/
			{                                
				fp2 = fopen("E:\\cifa\\output.txt", "a");
				fprintf(fp2, "4\t\t\t/=\t\t\t32\n");
                fclose(fp2);
			}
			else if(ch != '*')
            {                               /*若为除号,写入输出文件*/
                fp2 = fopen("E:\\cifa\\output.txt", "a");
				fprintf(fp2, "4\t\t\t/\t\t\t13\n");
                fclose(fp2);
				fseek(fp1, -1L, SEEK_CUR);
			}
			else if(ch == '*')
			{                            /*若为注释的开始,消除包含在里面的所有字符*/
				count = 0;
				ch = fgetc(fp1);
				while(count != 2)
                {            /*当扫描到'*'且紧接着下一个字符为'/'才是注释的结束*/
					count = 0;
					while(ch != '*')
						ch = fgetc(fp1);

					count++;
					ch = fgetc(fp1);
					if(ch == '/')
						count++;
					else
						ch = fgetc(fp1);
				}
			}
		}/*过滤注释结束*/


		else if(ch == '"')
		{                                         /*消除包含在双引号中的字符串常量*/
			fp2 = fopen("E:\\cifa\\output.txt", "a");

			fprintf(fp2, "5\t\t\t%c\t\t\t7\n", ch);
			ch = fgetc(fp1);

			while(ch != '"')
				ch = fgetc(fp1);
			
			fprintf(fp2, "5\t\t\t%c\t\t\t7\n", ch);
			fclose(fp2);
		}

		else
        {                           /*首字符为其它字符,即运算限界符或非法字符*/
            array[0] = ch;
            ch = fgetc(fp1);        /*再读入下一个字符,判断是否为双目运算符、限界符*/
            if(ch != EOF)
            {                       /*若该字符非文件结束符*/
                array[1] = ch;
				word = (char *)malloc( 3 * sizeof(char) );
				memcpy(word, array, 2);
				word[2] = '\0';
                result = find(word, 4, 1);      /*先检索是否为双目运算符*/

				if(result == 0)
				{                           /*若不是双目运算符*/
                    /*word = (char *)malloc( 2 * sizeof(char) );*/
					memcpy(word, array, 1);
					word[1] = '\0';
					result = find(word, 4, 1);      /*检索是否为单目运算符*/

					if(result == 0)                  /*若不是单目运算符*/
                    {                                /*检索是否为限界符 */
						result = find(word, 5, 1);

						if(result == 0)              /*若不是限界符,则为非法字符*/
						{
							error_manage(array[0], line);
						    errorno++;
						    fseek(fp1, -1L, SEEK_CUR);
						}
						else
						{                           /*若为限界符,写输出文件*/    
							fp2 = fopen("E:\\cifa\\output.txt", "a");
							fprintf(fp2, "5\t\t\t%s\t\t\t%d\t\n", word, result);
							fclose(fp2);
							fseek(fp1, -1L, SEEK_CUR);
						}
					}
                    else
					{     /*若为单目运算符,写入输出文件并将扫描文件指针回退一个字符*/
						fp2 = fopen("E:\\cifa\\output.txt", "a");
						fprintf(fp2, "4\t\t\t%s\t\t\t%d\t\n", word, result);
						fclose(fp2);
						fseek(fp1, -1L, SEEK_CUR);
					}
				}
                else
				{             /*若为双目运算符,写输出文件*/
					fp2 = fopen("E:\\cifa\\output.txt", "a");
					fprintf(fp2, "4\t\t\t%s\t\t\t%d\n", word, result);
					fclose(fp2);
				}
				word=NULL;
                free(word);

            }

            else
			{      /*若读入的下一个字符为文件结束符,当前字符是否为 '}'*/
				if(array[0] != '}')         /*若不是,转出错处理*/
					error_manage(array[0], line);
				else
				{                          /*若是'}',写输出文件*/
					fp2 = fopen("E:\\cifa\\output.txt", "a");
					fprintf(fp2, "5\t\t\t%s\t\t\t%d\n", '}', 2);
					fclose(fp2);
				}
			}
		}/*运算限界非法字符判断结束*/

        ch = fgetc(fp1); 
    }
	fclose(fp1);
	fp2 = fopen("E:\\cifa\\output.txt", "a");
	fprintf(fp2, "Number of error(s): %d .\n", errorno); /*报告错误字符个数*/
	fprintf(fp2, "NUmber of identities: %d.\n", id_count);
	fprintf(fp2, "Number of keywords: %d.\n", key_count);
	fclose(fp2);
}

/*******************************************/
/*    主函数                               */
/*******************************************/
main()
{           
    initialize();            /*初始化*/
    scanner();               /*扫描源程序*/
    printf("Succeed!\n");
    getch();
}
 

⌨️ 快捷键说明

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