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

在词法分析阶段,我们要做的就是将词分出来,而且确定单词的类型,一般的程序设计语言的单词符号能够份为下面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.\n");
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, "\n");
va_end(ap);
} void Warning(const char *format, ...)
{
va_list ap;
fprintf(stderr, "warning:");
va_start(ap, format);
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
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(); }

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

编译器DIY——读文件的更多相关文章

  1. 编译器DIY——词法分析

    在上一篇文章中已经介绍了读文件的操作,那么这一篇文章中将会细致解释词法分析. 在源文件里解析出的单词流必须识别为保留字,标识符,常量,操作符和界符五大类 1.显然我们须要列举出全部的保留字,而这里与保 ...

  2. GoLang几种读文件方式的比较

    GoLang提供了很多读文件的方式,一般来说常用的有三种.使用Read加上buffer,使用bufio库和ioutil 库. 那他们的效率如何呢?用一个简单的程序来评测一下: package main ...

  3. Python之路 day2 按行读文件

    #1. 最基本的读文件方法: # File: readline-example-1.py file = open("sample.txt") while 1: line = fil ...

  4. java的读文件操作

    java读取文件内容,可以作如下理解: 首先获得一个文件句柄,File file = new File():file即为文件句柄.两人之间联通电话网络了,就可以开始打电话了. 通过这条线路读取甲方的信 ...

  5. PHP使用feof()函数读文件的方法

    这篇文章主要介绍了PHP使用feof()函数读文件的方法,以实例形式对比了正确与错误的用法,阐明了feof()函数的使用技巧,需要的朋友可以参考下 本文实例讲述了PHP使用feof()函数读文件的方法 ...

  6. Java基础之读文件——使用输入流读取二进制文件(StreamInputFromFile)

    控制台程序,读取Java基础之读文件部分(StreamOutputToFile)写入的50个fibonacci数字. import java.nio.file.*; import java.nio.* ...

  7. c++中ifstream读文件的问题(关于eof())

    今天帮别人找BUG,是一段关于c++读写文件的问题,使用的是ifstream与outstream类,关于ofstream与ifstream的用法,此处不再獒述,见代码: #include<ios ...

  8. python (11)文件的读写 按行读文件

    读文件: 读取文件 f = open('\info.txt') fil = f.read() f.close() 按行读文件: f = open("info.txt") while ...

  9. Python学习入门基础教程(learning Python)--5.2 Python读文件基础

    上节简单的说明了一下Pyhon下的文件读写基本流程,从本节开始,我们做几个小例子来具体展示一下Python下的文件操作,本节主要是详细讲述Python的文件读操作. 下面举一个例子,例子的功能是读取当 ...

随机推荐

  1. 使用tortoisegit访问git@oschina

    转自:http://www.3lian.com/edu/2014/01-03/121350.html 首先,如果你想使用git@oschina ,你的电脑上必须先有git工具:你可以从这里获取谷歌提供 ...

  2. myeclipse8.6首次运行maven项目的问题解决

    myeclipse8.6导入maven项目后识别为普通java项目,即项目图标上没有小M的标识.这时是无法直接运行的. 解决方法:1,打开Window --> perferences,找到mye ...

  3. vnstat 查看服务器带宽统计命令

    vnStat是一个Linux下的网络流量监控软件,它记录指定网卡每日的传输流量日志. 它并非基于网络包的过滤,而是分析文件系统- /proc, 所以vnStat无需root的权限就可使用. ,它还自带 ...

  4. spring+mybatis 多数据源切换

    摘自: http://www.oschina.net/code/snippet_347813_12525 1. 代码: DbContextHolder public class DbContextHo ...

  5. BI项目简单备份策略

    在项目的开发中,备份是一个很重要的操作和良好的开发习惯,下面我们就针对BI相关项目的备份说一下备份策略 前端:Cognos 后端:SSIS+View+Procedure 服务器A装了Cognos内容库 ...

  6. ASP服务器I I S出现authentication mode=Windows错误解决办法

    网上下载的asp.net源码出现 <authentication mode="Windows"/>错误信息 属性 说明 mode 必选的属性. 指定应用程序的默认身份验 ...

  7. poj 3237(树链剖分+线段树)

    题意:给一棵树,三种操作.将第i条边的权值改为v,将a到b的路径上的边的权值全部取反,求a到b路径上边的权值的最大值. 思路:明显的树链剖分,加上线段树的操作.因为有取反的操作所以每个区间要记录最大值 ...

  8. Poj-1274-The Perfect Stall-匈牙利算法

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19174   Accepted: 869 ...

  9. angular.copy() 取消angular的数据双向绑定

    网址:https://www.tslang.cn/docs/tutorial.html

  10. MVC中cshtml文件中怎样使用ViewBag进行筛选?

    @foreach (PermissionForRoleModel item in ((List<PermissionForRoleModel>)ViewBag.PermissionsFor ...