zoukankan      html  css  js  c++  java
  • 编译器DIY——读文件

    编译器的前端词法分析:将源文件解析成一个个的单词流。为语法分析做准备。

    在词法分析阶段,我们要做的就是将词分出来,而且确定单词的类型,一般的程序设计语言的单词符号能够份为下面5种:

    1.keyword,如int,long等

    2.标识符,用来表示各种名字,如常量名,变量名等

    3.常数。各种类型的常数,如12。1.2等

    4.运算符:如+,-,*,/等

    5.界符,如“,”“;”等

    那么在实际的过程中应该怎样来区分这5中类型,在后面的文章中我将详细讲到。

    词法分析第一阶段。非常明显,须要从源文件里读取数据。考虑到如今的硬件内存都达到了2G及以上的标准,那么就将所有源文件读到内存中,并设置指针指向头位置。那么在随后的分词操作中,将直接操作指针就可以。在其它的编译器中,非常多类型都是从文件里按行读取然后对该行中的数据进行解析,这样做的优点就是空间的大大节省,特别是当内存紧凑的时候。而我之所以所有读取,不不过由于硬件的原因,另一个原因是在随后的分词中,我会相对简单一些。


    我们先构造一个结构用来存储对源文件有关的操作:

    struct File {
        void *file;// 指向文件的指针
    	char *fileName;//文件名称
    	unsigned char *cursor;//光标的位置
    	unsigned char *first;//内存区的首地址
    	unsigned long size;//文件的大小
    };
    


    接着用一个函数来实现读取源文件的操作:

    int readSourceFile(char *fileName) {
    	source.file = fopen(fileName, "r");
    	if (source.file == NULL) {
    		Error("Can not open file.
    ");
    		return 0;
    	}
    	source.fileName = fileName;
    	fseek(source.file, 0, SEEK_END);
    	source.size = ftell(source.file);
    	source.first = malloc(source.size + 1);
    	if (source.first == NULL) {
    		Error("The file is too big");
    		fclose(source.file);
    		return 0;
    	}
    	fseek(source.file, 0, SEEK_SET);
    	source.size = fread(source.first, 1, source.size, source.file);
    	fclose(source.file);
    	source.first[source.size] = END_OF_FILE;
    	source.cursor = source.first;
        return 1;
    }
    

    用fseek重定位文件的指针,ftell来取得指针对于文件首部的偏移量,从而得出文件的大小,接着开辟等量的空间,最后对文件结构体进行赋值


    在编译器中由于要对错误进行处理,所以就将全部的出错函数封装起来。以便随时调用。

    出错函数:

    void Error(const char *format, ...)
    {
    	va_list ap;
    	fprintf(stderr, "error:");
    	va_start(ap, format);
    	vfprintf(stderr, format, ap);
    	fprintf(stderr, "
    ");
    	va_end(ap);
    }
    
    void Warning(const char *format, ...)
    {
    	va_list ap;
    	fprintf(stderr, "warning:");
    	va_start(ap, format);
    	vfprintf(stderr, format, ap);
    	fprintf(stderr, "
    ");
    	va_end(ap);
    
    	return;
    }
    

    最后我们来进行測试:

    測试函数:

    /*
     * debug put all content from source file
     * */
    void putSrc(){
        unsigned char *ch=source.first;
        while(*ch != END_OF_FILE){
        	printf("%c", *ch++);
        }
    }


    主函数:

    int main() {
         readSourceFile("test.txt");
         putSrc();
    
    }

    到这里我们完毕了词法分析的第一步。在下篇文章中就是对源文件里的数据进行解析。




  • 相关阅读:
    纸上谈兵:最短路径与贪婪算法
    “不给力啊,老湿!”:RSA加密与破解
    纸上谈兵:拓扑排序
    Homebrew 安装使用
    Servlet详解
    搭建SpringMVC
    设置IDEA智能感知支持Jsp内置对象
    素材网站
    常用单词
    常见异常
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7295066.html
Copyright © 2011-2022 走看看