从零开始实现 Lua 解释器之介绍

警告??:这将是一个又臭又长的系列教程,教程结束的时候,你将拥有一个除了性能差劲、扩展性差、标准库不完善之外,其他方面都和官方相差无几的 Lua 语言解释器。说白了,这个系列的教程实现的是一个玩具语言,仅供学习,无实用性。请谨慎 Follow,请谨慎 Follow,请谨慎 Follow。

前言

编译原理是计算机科学的一个重要且复杂的知识体系。这个系列教程也只是你入门前的垫脚石。但即使如此,也并不代表这个教程就很简单,如果决定开始,请坚持到底。这是一个认真严肃的教程(咳咳),它不像网络上的其他类似教程,要么实现一个“高级计算器”就完事了,要么语法分析还没讲完,就太监了。也不像其他的 Lua 源码阅读类的指导教程,去教你怎么阅读并理解 Lua 的源码。但我相信完成本教程后再去读 Lua 的源代码,也会轻松很多。

本教程将从零开始,一砖一瓦的构建出一个完整的解释器。不使用任何自动化的工具,也不使用任何第三方库,从词法分析到虚拟机,全部亲力亲为。我们将要实现的语言起名为 SLua,意思是 Simple Lua。

前置要求

本教程并不是面向编程初学者的,你至少需要满足以下要求才可以继续阅读:

  • 本教程使用的编程语言为 Google 出品的 Go 语言。Go 语言上手非常容易,如果你有过其他任何语言的编程经验,请花几个小时阅读这篇教程:墙外多语言版墙内中文版
  • 本教程的定位不是教科书,因此不会过多的提及关于编译原理的理论性的内容,而更加注重实践。所以,这要求你至少要知道编译过程流水线的基本步骤以及每个步骤的作用,比如:词法分析、语法分析、虚拟机等。
  • 既然要实现 Lua 语言的解释器,自然要求你熟悉 Lua 语言,即使没有用它写过项目,至少要熟悉 Lua 语言的语法及语言特性。

面向人群

  • 如果你很想知道脚本语言的解释器的工作原理,请继续阅读。
  • 如果你不仅想知道工作原理,还想亲自实现一个,请继续阅读。
  • 如果你学完学校开设的编译原理课程,除了学会了 LEX 和 YACC,其余的还是一无所知,请继续阅读。

开发方式

我们不准备从一开始就着手实现一个完完整整的解释器,支持所有的 Feature,这样无疑会顾此失彼,也会极大的拉高教程的阅读门槛。所以我们会先抽取 Lua 中一些最最基本的特性,实现一个可以工作的原型。在原型之上,我们再不断添加特性,直到完成为止。

在第一个版本中,我们会将一些比较重要的 Feature 都砍掉,将目光集中在整个流程的实现上。

所以,第一个版本将:

  • 不支持 Table
  • 不支持函数和闭包
  • 不支持 for 循环语句
  • 不支持 repeat...until 循环语句
  • 不支持多行注释和多行字符串

阉割的差不多了,看看还剩下什么:

  • 变量的声明及赋值(全局变量和局部变量)
  • do...end 代码块
  • if...elseif...else...end 分支语句
  • while 循环语句
  • 单行注释
  • 单行形式的字符串
  • 各种单目和双目的运算符

编译流程

SLua 的编译共分为以下几个阶段:

  • 词法分析:将用户输入的文本形式的源代码分解为一个 Token 列表
  • 语法分析:将词法分析的输出作为输入,生成无语义信息的抽象语法树(AST)
  • 语义分析:完善 AST 中的语义相关的信息
  • 代码生成:根据 AST 生成字节码
  • 虚拟机:解释并执行字节码
  • 标准库:提供系统级的实用函数

教程的章节安排也和编译流程保持一致。

获取源代码

代码已托管到 Github 上:SLua,每一个阶段的代码我都会创建一个 release,你可以直接下载作为参照。虽然提供了源代码,但并不建议直接复制粘贴,因为这样学到的知识会很容易忘记。

刚开始玩 Github 和 博客园,所以没有任何粉丝和关注量(哭),如果你觉得这篇教程有帮助,请不要吝啬给文章点个喜欢,给 Github 上的项目点个 Star。如果能 Follow 一下博客园 和 Github 的账号就更好啦,我也会更加有动力将这个系列写下去。:)

时间: 2024-10-03 05:04:51

从零开始实现 Lua 解释器之介绍的相关文章

Lua语言的介绍和编程语言的归类

Lua 本条目介绍的是一种编程语言.关于关于Lua在维基百科中的使用,请见"维基百科:Lua".关于"Lua"一词的其他意思,请见"卢阿". Lua 编程范型 多重编程范式,脚本,命令式编程(过程式,基于原型的编程,面向对象程序),函数编程语言 设计者 Roberto Ierusalimschy Waldemar Celes Luiz Henrique de Figueiredo 发行时间 1993年 最新发行时间 5.3.4(2017年1月30

Lua 学习之基础篇七<Lua Module,Package介绍>

Lua 之Module介绍 包管理库提供了从 Lua 中加载模块的基础库. 只有一个导出函数直接放在全局环境中: [require]. 所有其它的部分都导出在表 package 中. require (modname) 加载一个模块. 这个函数首先查找 [package.loaded] 表, 检测 modname 是否被加载过. 如果被加载过,require 返回 package.loaded[modname] 中保存的值. 否则,它会为模块寻找加载器. require 遵循 [package.

Lua Rings库介绍

Rings需求 如果有一段lua脚本代码, 本来来源不可靠, 可能有安全性问题, 或者不像让这份代码污染了正在执行的lua环境, 则需要lua rings工具出厂了. 其在主lua环境中,即在宿主脚本中, 调用rings库创建一个子的lua环境, 将不可靠的lua代码在子lua环境中运行, 运行完毕环境销毁, 一点都不影响宿主环境. Rings is a library which provides a way to create new Lua states from within Lua.

lua解释执行脚本流程

1 #include "lua.hpp" 2 3 #include <iostream> 4 using namespace std; 5 6 #pragma comment(lib, "lua5.1.lib") 7 8 struct lua_guard{ 9 lua_State *pL; 10 lua_guard(lua_State *s) :pL(s){} 11 ~lua_guard(){ lua_close(pL); } 12 }; 13 14 i

从零开始部署bind9服务器之二:部署缓存服务器

所有操作均在192.168.1.104上进行   一.安装bind9: yum install -y bind     二.修改配置文件: cp /etc/named.conf{,.back}              //先做备份 vim /etc/named.conf     三.启动服务: chkconfig --level 35 named on          //设置开机启动 service named start     验证: dig -t A www.souhu.com @1

Lua1.1 Lua 的设计和实现 (一)

转载出处:http://my.oschina.net/xhan/blog/309613 说明: 这个文档是 Lua1.1 的 doc 目录里的 lua.ps 文件. 同时这个文档可以这里找到:http://www.lua.org/semish94.html 原文版权归原作者所有,这篇翻译只是作为学习之用.如果翻译有不当之处,请参考原文. --------------------以下是正文------------------ 应用程序扩展语言的设计和实现 摘要.我们描述 Lua 的设计和实现,一个

Lua标准库(转)

转载地址:http://www.yiibai.com/lua/lua_standard_libraries.html Lua的标准库提供了一组丰富的功能,与C的API直接实现,建立在Lua编程语言函数.Lua编程语言中这些库提供服务,还提供外部服务,如文件和数据库操作. 建于官方的C的API,这些标准库是作为单独的C模块.这包括: 基本库,其中包括协程分库 模块库 字符串操作 表操作 数学库 文件输入和输出 操作系统工具 调试设备 基本库 我们使用的基本库根据遍及不同主题的教程.下表提供了所有相

从零开始一起学习SLAM | 掌握g2o顶点编程套路

点"计算机视觉life"关注,置顶更快接收消息! ## 小白:师兄,上一次将的g2o框架<从零开始一起学习SLAM | 理解图优化,一步步带你看懂g2o代码>真的很清晰,我现在再去看g2o的那些优化的部分,基本都能看懂了呢! 师兄:那太好啦,以后多练习练习,加深理解 小白:嗯,我开始编程时,发现g2o的顶点和边的定义也非常复杂,光看十四讲里面,就有好几种不同的定义,完全懵圈状态...师兄,能否帮我捋捋思路啊 师兄:嗯,你说的没错,入门的时候确实感觉很乱,我最初也是花了些时间

LUA脚本调用C场景,使用C API访问脚本构造的表

LUA调用C lua解析中集成了一些系统服务, 故脚本中可以访问系统资源, 例如, lua脚本可以调用文件系统接口, 可以调用数学库, 但是总存在一些lua脚本中访问不到的系统服务或者扩展功能, 如果这些系统服务或者扩展功能是使用C语言实现, 那么可以, 使用lua库的对C库的封装方法, 将其中功能封装成lua 接口, 这样脚本就调用这些lua接口调用这些功能. ------- 这种情况,是以lua脚本作为宿主程序. C调用LUA 另外一种场景,是C程序作为宿主程序, 调用LUA脚本, 例如将l