【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

学过编译器的同学都知道,词法分析是编译器里面最基础的一条。之前,在学校读书的时候,老师也会告诉我们这个时候,应该用状态机来实现。此外,必须要先要做一遍词法分析,然后才能做语法分析,其实不然。至少,我们今天的ucc里面,其实语法分析和词法分析是一起做的。

另外一点,和学校里面不一样的是,很多场合,大家也喜欢用flex工具自动生成词法分析的代码。毕竟,只要会写正则表达式,就可以完成很多的工作。这个比手写容易很多。

1、词法分析的文件

lex.c

https://github.com/nobled/ucc/blob/master/ucl/lex.c

2、给语法解析提供的接口

int GetNextToken(void)
{int tok;PrevCoord = TokenCoord;SkipWhiteSpace();TokenCoord.line = LINE;TokenCoord.col  = (int)(CURSOR - LINEHEAD + 1);tok = (*Scanners[*CURSOR])();return tok;
}

3、注册词法分析回调函数

void SetupLexer(void)

4、解析回调注册

{// other codeScanners[END_OF_FILE] = ScanEOF;Scanners['\''] = ScanCharLiteral;Scanners['"']  = ScanStringLiteral;Scanners['+']  = ScanPlus;Scanners['-']  = ScanMinus;Scanners['*']  = ScanStar;Scanners['/']  = ScanSlash;Scanners['%']  = ScanPercent;Scanners['<']  = ScanLess;Scanners['>']  = ScanGreat;Scanners['!']  = ScanExclamation;Scanners['=']  = ScanEqual;Scanners['|']  = ScanBar;Scanners['&']  = ScanAmpersand;Scanners['^']  = ScanCaret;Scanners['.']  = ScanDot;Scanners['{']  = ScanLBRACE;Scanners['}']  = ScanRBRACE;Scanners['[']  = ScanLBRACKET;Scanners[']']  = ScanRBRACKET;Scanners['(']  = ScanLPAREN;Scanners[')']  = ScanRPAREN;Scanners[',']  = ScanCOMMA;Scanners[';']  = ScanSEMICOLON;Scanners['~']  = ScanCOMP;Scanners['?']  = ScanQUESTION;Scanners[':']  = ScanCOLON;}

5、举例说明

5.1 一般的符号解析,比如加号解析

static int ScanPlus(void)
{CURSOR++;if (*CURSOR == '+'){CURSOR++;return TK_INC;}else if (*CURSOR == '='){CURSOR++;return TK_ADD_ASSIGN;}else{return TK_ADD;}
}

注意这里的加号解析,它有可能是+,有可能是++,也有可能是+=,其实有三种情况需要处理。不失一般性,我们可以找到减号的解析函数,

static int ScanMinus(void)
{CURSOR++;if (*CURSOR == '-'){CURSOR++;return TK_DEC;}else if (*CURSOR == '='){CURSOR++;return TK_SUB_ASSIGN;}else if (*CURSOR == '>'){CURSOR++;return TK_POINTER;}else{return TK_SUB;}
}

加号要比加号复杂一点,除了-,它还有可能是--,-=,->,所以总共有四种情况。

5.2 有些符号,因为实在不可能出现其他情况,根本不需要往后看,比如[、]、{、}等等,因此对它们的处理其实直接可以用macro宏来表示,

#define SINGLE_CHAR_SCANNER(t) \
static int Scan##t(void)       \
{                              \CURSOR++;                  \return TK_##t;             \
}

5.3 对变量的解析

static int ScanIdentifier(void)
{unsigned char *start = CURSOR;int tok;if (*CURSOR == 'L'){if (CURSOR[1] == '\''){return ScanCharLiteral();}if (CURSOR[1] == '"'){return ScanStringLiteral();}}CURSOR++;while (IsLetterOrDigit(*CURSOR)){CURSOR++;}tok = FindKeyword((char *)start, (int)(CURSOR - start));if (tok == TK_ID){TokenValue.p = InternName((char *)start, (int)(CURSOR - start));}return tok;
}

注意,对变量的解析这部分,还会进一步分成单字符、字符串、关键字、普通变量四种情况的解析。因此,它的结果可能有四种形式。

5.4 对数字的解析

static int ScanNumericLiteral(void)
{unsigned char *start = CURSOR;int base = 10;if (*CURSOR == '.'){return ScanFloatLiteral(start);}if (*CURSOR == '0' && (CURSOR[1] == 'x' || CURSOR[1] == 'X')){CURSOR += 2;start = CURSOR;base = 16;if (! IsHexDigit(*CURSOR)){Error(&TokenCoord, "Expect hex digit");TokenValue.i[0] = 0;return TK_INTCONST;}while (IsHexDigit(*CURSOR)){CURSOR++;}}else if (*CURSOR == '0'){CURSOR++;base = 8;while (IsOctDigit(*CURSOR)){CURSOR++;}}else{CURSOR++;while (IsDigit(*CURSOR)){CURSOR++;}}if (base == 16 || (*CURSOR != '.' && *CURSOR != 'e' && *CURSOR != 'E')){return ScanIntLiteral(start, (int)(CURSOR - start), base);}else{return ScanFloatLiteral(start);}
}

对数字的解析比较复杂,这个里面有可能是整数,也有可能是浮点数。整数里面还有10进制、16进制,浮点数里面有单精度和双精度。当然,不管结果是什么,都不外乎这两种情形。

5.5 其他支撑函数

这部分函数也有一些,比如检查是否是数字或字母,是否是关键字,是否跳过空格等等。这部分函数也非常关键,但是他们不是主要的接口函数。

记得读书的时候,这部分考虑的主要就是状态机的部分,也就是fsm。只要有一些fsm的基础知识,用起来还是比较容易地。

ucc编译器(词法分析)相关推荐

  1. ucc编译器(入门)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 要说开源编译器,一般大家想到的都是gcc.但是现在gcc的代码量太大了,不太适合学习.代码量比较 ...

  2. ucc编译器(优化)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 编译器优化几乎是现代编译器最重要的工作.一般编译器的优化有这么几层,a,中间代码生成前的优化,比 ...

  3. ucc编译器(语法解析)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 做完词法分析,后面紧接着就是语法分析.对于一个编程语言而言,语法解析才是语言和语言之间最大的区别 ...

  4. c语言编译器_学C语言写自己的K语言:编译器词法分析。

    词法分析(lexical analysis),是计算机科学中将字符序列转换为记录(Token)序列化的过程.词法分析一般分手动与自动,自动是基于lex,flex词法分析器使用正则式来配置,我们这里将学 ...

  5. ucc编译器(x86移植)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 之前写过一篇ucc的文章,也就是这一篇.这篇文章对ucc的流程说了挺多,但是怎么把ucc移植到新 ...

  6. TEST语言编译器--词法分析

    TEST语言编译器 目录 词法分析 词法分析时,依次读入源程序中的每个字符,依据语言的构词规则,识别出一个个具有独立意义的最小语法单位,即"单词",并用某个单词符号来表示每个单词的 ...

  7. 自己写编译器词法分析c语言,从零开始写个编译器吧 - 开始写词法分析器(3)...

    上周周末旅游去了,就没更新了,虽然回到海拔0m的地区,不过目前似乎还在缺氧,所以本次就少更点吧. 这章将结束词法分析的部分. 在之前的章节(第7章从零开始写个编译器吧 - 开始写词法分析器(1))中我 ...

  8. ucc编译器(中间代码生成)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 所谓中间代码生成,就是生成一种和具体汇编语言无关的中间代码.生成中间代码有很多的好处,一方面它可 ...

  9. ucc编译器(语义分析)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 符合语法的代码,不一定符合语义.这句话听上去很拗口,我们不妨举个例子,假设我们定义了一个变量in ...

最新文章

  1. Python3 websocket server与client
  2. i-usb-storer android,i usb storer
  3. java8 新特性之流式数据处理_Java8新特性 - 集合流式编程 - 最终操作
  4. opencv 利用图像轮廓函数填充圆环内部 图像轮廓函数应用小例子
  5. 网页服务器目录属性,IIS 6.0 F1:网站属性 - 目录安全性选项卡
  6. 拓端tecdat|R语言Poisson回归的拟合优度检验
  7. 智慧油气田可视化,打造油气田管控的“最强大脑”
  8. 省团团小程序被微信封禁
  9. 微信修改步数 Android,安卓微信怎么改步数
  10. 数据基础-索引和完整性(约束)
  11. channel estimation
  12. Ubuntu 16.04 LTS 初体验 (转载)
  13. STM32超低功耗入门之停止模式
  14. KRPANO资源分析工具下载720YUN全景图
  15. 读书笔记——阿加莎·克里斯蒂(英国)《控方证人》
  16. 软件测试软件测试工程师
  17. 超猛tuntap虚拟网卡实现超猛UDP隧道
  18. 提高C++程序运行效率,减少运行时间的方法
  19. 品三国、论国产RISC-V芯片天下大势
  20. 四路监控 php,4种常见道路监控系统,老司机带你认识,必须了解的3种摄像头

热门文章

  1. NOIP2015DAY2T2子串
  2. webrequest HttpWebRequest webclient/HttpClient
  3. 第十一章:WebSocket
  4. 动态链接库的隐式动态链接和显示动态链接
  5. 利用memcache来保存tomcat的session会话
  6. 关于Keil4 转到 Keil5以后的一些错误解决
  7. linux --- 部署前后端分离项目
  8. Ambari ambari 集群及组件
  9. 十一:贪心算法-寻找硬币
  10. cocos2d-js 网络请求之GET/POST