前言:

编译实践系列将以lua的词法,语法和语意为标准,用C++实现lua的解释器,这其中也会参考lua解释器官方实现,但重点在于理清编译系统的基本框架和每个环节最基本的实现。
一般的编译系统结构:


1 从源码文件读入字符,词法分析阶段即按给定的标准(标识符,分隔符,数字)组装成token,进而形成token流;
2 语法分析阶段,会将token按照编程语言给定的语法模式,组合成节点,最后形成抽象语法树AST;
3 语义分析,说的抽象点就是语言背后的含义,那么谁赋予语言以含义?是解释它的“人”,从来不是语法它自己。俗话说,一千个读者就有一千个哈姆雷特,但在程序语言的世界里,这肯定是行不通的。所以,人们规定一个语法模式只能有一种解释,所有的这些设定都在语言规范(language specification)里。
说了这么多,那么语义到底是什么呢?是变量查找顺序(C++里是先找最近的block,依次向外延伸),是结构体内存对齐的规则,是类型转换规则(C++容许int转double,但不容许int转string,然而lua是可以的)等等,所有这些规则就形成了语义分析。语义分析阶段便是靠这些规则来解释语法的含义的。其实,CPU和内存才是最终的解释器。
4.代码优化可以分为与机器无关的优化和机器相关的优化,说的简单点就是整合,删除不必要的代码。这部分可以单独拿出来,不影响后续流程,所以lua解释器暂时不考虑做优化。
5.代码生成可以是虚拟机的字节码,也可以是x86汇编码,甚至可以是c语言。当然,我会先生成字节码,然后配套做一个虚拟机,解释执行。

本系列相应的源码在:https://github.com/pzhp/lua_interpretor
****************************************************************************

词法分析:

基本篇

1 先看一道常见的面试题:把字符串转换为整数(即实现atoi),如果考虑到实现基本功能(不含溢出处理),这并不难:依次读入字符取得对应的数字再乘以权重累加即可,正负数也只是加个前置判断而已。

2 再给道题,判断一段字符串是否满足一下要求:只能以字母或下划线开始,其余部分数字、字母、下划线均可。我相信这个也不难,从头开始扫描字符串,if判断即可。

3 如果再告诉你一条规则,以 ‘“’ 开头直到遇到 ‘”’结尾,或者以 单引号开头和结尾可判定为字符串常量。

4 最后,增加判定是运算符(+ - * 、 % <= ...)和分隔符(; , ...)的规则,也就可以识别程序语言中的运算符和分割符了。只不过这里会用到一个小技巧,lua里存在 ".", "..", "..." 当字符判定为"."时,会继续预读入下一个字符再判定, 如果第二个字符是"." 则拿到该字符,结果为"..",继续这么处理第三个字符。可以将这个判断转化为查表。

当完成这几个函数,那么需要考虑什么时候选择解析成数字,什么时候解析成字符串...,其核心在于预先看一两个字符做预判,决定走那条路,这里的预测可以采用标准流的peek, get, putback等函数完成,其基本框架如下:

while (true)
{       // init a single token recognise statechar ch = GetNextChar();if (isdigit(ch)){tk = ProcessNumberState(ch);}else if (std::isalpha(ch) || ch == '_'){tk = ProcessIndentifyState(ch);}else if (ch == '\'' || ch == '"'){tk = ProcessStringState(ch);}else if (ch == '-' && PeekNextChar() == '-'){HandleComemnt(ch);continue;}else if (m_dict.haveToken(std::string(1,ch))){tk = ProcessOperatorAndDelim(ch);}else{m_currState = S_Fatal;m_strErrReason = "cannot find dispatch method";}
}

为了存放词法分析的结果,定义Token类,主要含有一下属性:token所在位置(文件,行,列),token类型(数字常量,字符串常量,标识符等),token的值(可以用解析出来字符串代表)。
具体源码请参考scanner.cpp

高级篇

如果你要写针对特定语言的词法分析模块,上面描述就够了,那么为什么编译原理类的书会讲正则文法,有限状态自动机(DFA,NFA),搞的那么复杂呢?一方面为了形式化表述,另外方面也是为了自动化生成,满足可配置性。以lex generator:flex为例:

/* 规定DIGIT为0-9的数,如果规定[0-8],那么9将无法被判定到数字里面 */
DIGIT             ([0-9])
HEX_DIGIT         ([0-9a-fA-F])
HEX_INTEGER       (0[Xx]{HEX_DIGIT}+)
INTEGER           ({DIGIT}+)
EXPONENT          ([Ee][-+]?{INTEGER})
DOUBLE            ({INTEGER}"."{DIGIT}*{EXPONENT}?)
BEG_STRING        (\"[^"\n]*)
STRING            ({BEG_STRING}\")
IDENTIFIER        ([a-zA-Z][a-zA-Z_0-9]*)
OPERATOR          ([-+/*%=.,;!<>()[\]{}])
BEG_COMMENT       ("/*")
END_COMMENT       ("*/")
SINGLE_COMMENT    ("//"[^\n]*)/* -------------------- Constants ------------------------------ */
"true"|"false"      { yylval.boolConstant = (yytext[0] == 't');return T_BoolConstant; }
{INTEGER}           { yylval.integerConstant = strtol(yytext, NULL, 10);return T_IntConstant; }
{HEX_INTEGER}       { yylval.integerConstant = strtol(yytext, NULL, 16);return T_IntConstant; }
{DOUBLE}            { yylval.doubleConstant = atof(yytext);return T_DoubleConstant; }
{STRING}            { yylval.stringConstant = _strdup(yytext); return T_StringConstant; }
{BEG_STRING}        { ReportError::UntermString(&yylloc, yytext); }/* -------------------- Identifiers --------------------------- */
{IDENTIFIER}        { if (strlen(yytext) > MaxIdentLen)ReportError::LongIdentifier(&yylloc, yytext);strncpy(yylval.identifier, yytext, MaxIdentLen);yylval.identifier[MaxIdentLen] = '\0';return T_Identifier; }

具体源码请参考scanner.l

我们提供正则表达式,generator其内部完成以下转换,从正则式转换到NFA再到DFA阶段,DFA还可以做优化精简,生成一个词法分析模块。每一步的转化都有相应的算法完成。比如NFA到DFA算法:采用子集构造算法,类似于广度优先搜索,将下一阶段有可能的状态集中到一个集合,遍历操作增加下一步,只有最终集合中存在可接受的状态,则视为成功。可以参考engineering a compiler:chapter2 和装配脑袋博客

****************************************************************************
小问题:
如果数字超过其类型而溢出,gcc会怎么处理?
关于"1++2",“x+++1”,gcc会怎么分割成token?1+(+2) or error?
数字在词法分析阶段需要判断正负?

转载于:https://www.cnblogs.com/espzest/p/4095914.html

Lua编译实践1-词法分析:相关推荐

  1. 编译原理中词法分析的递归下降分析法实例--能被5整除的二进制数---c语言实现

    一.前言 又到了一周一度的编译原理实验课,一次实验课上完了,又是大学生必备技能-写实验报告.行了,废话不多说,我直接展现,如何实现编译原理中词法分析的递归下降分析法实例–能被5整除的二进制数的思路.作 ...

  2. 编译原理 C-Minus词法分析(FLEX)

    C–源代码词法分析 文章目录 C--源代码词法分析 一.实现目标 二.C-Minus语法 三.Flex Flex简介 Flex正则表达式 Flex安装与使用 Flex文件编写 定义 规则 用户代码 四 ...

  3. 编译原理画出c语言中注释的转化图,编译原理节词法分析DFANFA及其转换.ppt

    编译原理节词法分析DFANFA及其转换 Step4 寻找可合并状态 ε ε 0 1 2 0 5 0 1 6 1 3 4 7 ε ε 0 8 9 1 1 0 10 11 0 0 1 1 1 0 12 1 ...

  4. Cocos2d-x lua 编译到Android设备

    需要完成Android下ant,ndk,sdk(adt)的环境配置.Java环境配置. 也可以搭建VS下的Lua开发环境. 首先新建项目 cocos new -l lua -d (...address ...

  5. 【编译原理】词法分析和语法分析两万字全总结(这知识它不进脑子啊~!)

    文章目录 1 引论-一些名词解释 1.1 解释器 1.2 翻译器和编译器 1.3 编译型的程序设计语言和解释型的程序设计语言各有哪些优缺点? 1.4 编译过程六个阶段的任务 1.5 遍的概念 2 词法 ...

  6. 编译实验(一)词法分析

    编译原理课程即将结束,开始了在校中最麻烦的实验,编译实验......同在一个系,其他班的编译实验分成好几块,简短的文法, 完成一些小功能,就我们班的老师,撂下一句话:参考书本,把编译器实现了,可以一组 ...

  7. 编译原理之词法分析、语法分析、语义分析,【精炼总结】

    词法分析和词法分析程序 词法分析阶段是编译过程的第一个阶段.这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号).词法分析 ...

  8. 【编译原理】词法分析程序设计

    概述 词法分析即对程序源码进行分词处理,分词处理就是把文本流分割成一个又一个符号.分词处理的输入输出是什么呢? 输入是源码字符串流 输出是: 整型的类型枚举值,表示符号类型,如字符串: 符号内容信息, ...

  9. Android 6.0 源代码编译实践

    前阵子去上海参加 Android 开发面试,被问及了 Android 的基本原理.常用组件背后的实现机制.设计模式等问题,我都回答地不好.面试时,老司机们常常问我对知识点"背后的实现代码有没 ...

最新文章

  1. 清华人工智能研究院成立,张钹姚期智分别任院长和主任
  2. java request get json数据_Java中,获取request中json数据
  3. 【DIY】自己动手更换热水器镁棒,保养电加热热水器注意事项,电热水器镁棒多久更换一次实际数据参考...
  4. cmake使用教程(一)-起步
  5. Semaphore同步
  6. 【Linux系统编程】Linux 可执行文件结构与进程结构
  7. php cap,PHP ImagickDraw setStrokeLineCap()用法及代码示例
  8. C语言怎么合并两个有序链表
  9. 为Mac安装homebrew
  10. 阿里云物联网边缘计算加载MQTT驱动
  11. 英语总结系列(十五):别样的三月
  12. php常用的日期时间操作
  13. FPGA 实现 RGB 图像转 Gray
  14. Google基本语法二,指令
  15. 安装了java环境后,双击.jar包无法运行的解决方案
  16. 2018年终总结--修身篇
  17. Backdoor.Zegost木马病毒分析(一)
  18. k8s——通过暴漏端口实现外部访问服务
  19. mysql数据库导出数据乱码问题_Mysql数据库导出来的是乱码如何解决
  20. 开源问答社区软件Answer

热门文章

  1. PHP服务器时间差8小时解决方案
  2. LSA 安装及管理应用程序
  3. hadoop 023.0与hadoop 1.0 io.serializable分析
  4. 主瓣,旁瓣,栅瓣概念解析
  5. php mysql什么意思_php MySQLi是什么意思?
  6. mac邮件过滤器SpamSieve,支持任意类型的任意数量的电子邮件帐户
  7. JavaScript夯实基础系列(一):词法作用域
  8. blast | diamond 输出结果选择和解析 | 比对
  9. CentOS 7.2 搭建内网ntp时间服务器
  10. 【计算几何】【分类讨论】Gym - 101173C - Convex Contour