`
chinamming
  • 浏览: 140662 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

lua词法语法分析

 
阅读更多
lua是我工作中的第一语言,因而工作的大部分时间,都在敲着lua代码。虽然它语法是否简单
好学,但它来做工程的人,都不免要抱怨作者的一些设定理念。 据说作者是一个学院派的人(从他的
sample代码中就能看出这点),很少也不会去考虑做工程的人的需求。 因而,留给我们这些使用lua
的人不少痛苦。
<wbr><wbr><wbr>大伙不爽的事情如下:<br><wbr><wbr><wbr>1. 默认的变量声明是全局的, 局部需要 local 关键字。<br><wbr><wbr><wbr>原因: 正常的一段代码, local的变量怎么也比全局的多, 如果反过来, 想python一样,<br><wbr><wbr><wbr>默认是local , global 来定义全局能省下不少要敲的代码量。并且避免不小心敲错一个<br><wbr><wbr><wbr>单词导致多一个global变量,而又无法察觉。<br><br><wbr><wbr><wbr>2. 没有continue....<br><wbr><wbr><wbr><wbr><wbr><wbr>- -,说不好其实也没啥,毕竟绕一下还是能实现,但作为一门成熟的编程语言,应该<br><wbr><wbr><wbr>不至于为了省点语法分析代码而不实现continue吧<br><wbr><wbr><wbr><br><wbr><wbr><wbr>3. hash 和 array不区分<br><wbr><wbr><wbr><wbr><wbr><wbr>这应该说是lua的特点, 只要把table用得正确也不会有太大问题。 但对于初学者<br><wbr><wbr><wbr>每次都必须花时间去了解table.getn之类的语义。 而且在我们项目里,因为很多table<br><wbr><wbr><wbr>不能区分到底是当array还是hash用,每次求table的大小时都必须一项一项去数。而且这<br><wbr><wbr><wbr>似乎还成为了编程的惯例。因而,我的设想是如果table里面能多一项来跟着table元素的<br><wbr><wbr><wbr>个数。将省不少麻烦。<br><br> 说是这样说,但是如果真正去改虚拟机,也是个不少的工作量。而最麻烦的是,如果项目真的使用<br> 自己改虚拟机,那么将会对以后使用第三方库带来很多麻烦。所以这一直只是个想法而没人去尝试。<br><wbr><wbr><wbr><br> 不过既然都想到这点,就不能不了解一下lua虚拟机的词法和语法分析过程。 前阵子花的点时间去<br> 阅读这部分源码。在此大家分享一些笔记。<br><br><wbr><wbr><wbr>lua源文件中与编译相关的主要有四个lopcodes(字节码),llex(词法分析),lparser(语法分析),lcode(目标代码生成).<br> lopcodes里定义了指令的格式,寄存器和常数的表示等.这里记录下一些用语的细节,方便下文.相信大家都比较熟悉. <wbr><br> --[[<br> 一个指令由32位的值,对于有三种模式。<br> iABC,iABx 和 iAsBx, i是6位的操作码,A为8位, BC为9位, Bx 和 sBx为18位。<br> A参数通常用作为需要赋值的寄存器, sBx一般用于做跳转量。<br><br> 然后是常量与寄存器的索引。lua通常使用255个寄存器,第n个寄存器一般表示为R(n),<br> 而常量从256开始编号。 常量与寄存器一起成为RK值,RK(x)如果x小于256则为R(x)<br> 否则,为K(x-256),即第x-256+1个常量。RK值经常作为指令的参数。<br><br> pc指下一个指令的位置<br> --]]<br><br> ----------------------------------------------------------------------------------------------------------------<br> 词法分析<br><br><wbr><wbr><wbr>词法分析过程比较简单,主要的处理函数是int llex(LexState *ls, SemInfo *seminfo)<br> 它接受一个LexState结构,通过其中的buff读取字节,返回一个token和将语义信息填充到SemInfo中(字符串和数值)。<br> 要注意的地方有两个。<br><br><wbr><wbr><wbr>一是保留字的处理。lua在初始化时调用luaX_init,建立起所有保留字的字符串对象(同时让它永远不回收,调用luaS_fix)。<br> 并且设定其reserved值为该保留字的枚举值。因为lua中相同的字符串只有一份,所以在llex中遇到reserved字段非空的<br> 字符串即为保留字,否则为TK_NAME。<br><br><wbr><wbr><wbr>二是多行注释和字符串。即当读取到'--[' 或 '['的时候,要处理长字符串的情况。通过skip_sep 和 read_long_string处理两段‘=’<br> 数量的匹配。<br> ----------------------------------------------------------------------------------------------------------------<br><br> 语法分析<br><wbr><wbr><wbr><br><wbr><wbr><wbr>语法分析是编译过程的重点,其外部接口是Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name)<br> 它从字节流z读取符合, 建议LexState做词法分析, 同时按照语法生成规则展开, 最后调用到lcode里的接口生成各条指令记录到函数体Proto.<br><br><wbr><wbr><wbr>最上层的语法规则都比较容易理解, 如 chunk , statment, block等. 执行根据生成规则一层层打开即可.<br> 需要注意的是以下的内容:<br><br> ----------------------------------------------------------------------------------------------------------------<br> 1.table的构造过程<br><br> 表构造的处理函数是void constructor (LexState *ls, expdesc *t)<br> 它先生存一条OP_NEWTABLE指令, 然后根据语法, 按','(或';')切分每项, 根据格式调用listfield 或者 recfield<br> recfield 生成的是 记录项, 也就是 x = y 或者 [x] = y 的形式, 它用分别用expr求出key 和 value 表单式值,<br> 然后生成一条OP_SETTABLE指令.<br><br> 这里想说的是数组项的处理方式, 它并没有对每一项产生一个OP_SETTABLE指令, 而是缓存起来再一次性处理的.<br> 其实listfield的只是对之listfield里面仅仅是对value 进行expr调用. 然后记录待处理的项数量+1 (cc-&gt;tostore++)<br> 在每次遇到项处理前, 都调用closelistfield, closelistfield 发现当待处理的项达到FPF时(默认50个)<br> 生成一个OP_SETLIST指令, 批量对他们赋值.<br> OP_SETLIST指令的格式为 OP_SETLIST<br> 意外把 寄存器A中的table批量赋值, 数量为B个, 目标值所指寄存器范围是 [C-1]*FPF+1 ~ [C-1]*FPF+B<br><br> 因而, 以下语句<br> local a = { 1; 2; 3; [5] = 'a', 4, 5, [7] = 'b', 6, 7, 8}<br><br> 的编译结果将是<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [01] newtable<wbr><wbr> 0<wbr><wbr> 8<wbr><wbr> 2<wbr><wbr><wbr> ; array=8, hash=2<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [02] loadk<wbr><wbr><wbr><wbr><wbr> 1<wbr><wbr> 0<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 1<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [03] loadk<wbr><wbr><wbr><wbr><wbr> 2<wbr><wbr> 1<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 2<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [04] loadk<wbr><wbr><wbr><wbr><wbr> 3<wbr><wbr> 2<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 3<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [05] settable<wbr><wbr> 0<wbr><wbr> 259 260<wbr> ; 5 "a"<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [06] loadk<wbr><wbr><wbr><wbr><wbr> 4<wbr><wbr> 5<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 4<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [07] loadk<wbr><wbr><wbr><wbr><wbr> 5<wbr><wbr> 3<wbr><wbr><wbr><wbr><wbr><wbr><wbr> ; 5<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> [08] settable<wbr><wbr> 0<wbr><wbr> 262 263<wbr> ; 7 "b"<br><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
分享到:
评论

相关推荐

    lua语法:Lua的ANTLRv4语法分析器和语法

    分解词法分析器和语法分析器 添加了更多的语句类型(varstat等) 添加了一个COMMENTS频道 空格进入隐藏频道,而不是简单地跳过 用法 至于其他ANTLRv4语法: antlr4 LuaLexer.g4 LuaParser.g4 铁路图 请在以铁路图...

    《自己动手实现Lua:虚拟机、编译器和标准库》_张秀宏_2018-9-27.rar

    本书是一本面向Lua程序员和脚本语言...第二部分主要讨论Lua语法和编译器实现,包括词法分析、语法分析、代码优化、代码生成等。第三部分主要讨论Lua辅助API和标准库实现,包括基础库、实用工具库、包和模块、协程等。

    Lua源码剖析21

    Lua源码剖析(二):词法分析、语法分析、代码生成词法分析lua对与每一个文件(chunk)建立一个 LexState 来做词法分析的词法分析根据语法分析的需求

    LuaMacro:一个扩展的 Lua 宏预处理器

    LuaMacro - Lua 的宏预处理器这是一个用于预处理和评估 Lua 代码的库和驱动程序脚本。... 这个实现使用最初由的词法分析器来标记 Lua 源代码,并显式地构建一个预处理过的字符串,然后可以以通常的方

    Lua中文教程(pdf版)

    1.3 词法约定...7 1.4 命令行方式.................7 第2章类型和值9 2.1 Nil..............9 2.2 Booleans....9 2.3 Numbers...10 2.4 Strings......10 2.5 Functions.12 2.6 Userdata and Threads.12 第3...

    lpeg-grammars:LPEG 词法分析器的一组语法

    Lua 5.1.x 或 LuaJIT 2.0.x+ LPEG 库 用法 解析 HTML 文档 local htmlParser = require ' lexers/html ' local content = htmlParser. parse ( [[ &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;...

    lpil53:用Lua编写的Lua 5.3的Lua解析器。 (仍在进行中)

    LPIL的两个重要部分是词法分析器和解析器。Lexer 位于lexer.lua中,lexer的工作是接受一个字符串并将其转换为令牌表。 Lua中的令牌可以是: 字符串文字,例如“ hi”,“ hey”或-[[hello]] 数值文字,例如25或0xFF...

    GameFramework:简易游戏框架,整合D2D和Lua

    脚本操作系统简介:语言为简化C语言,自制编译器(词法+语法+ LR分析),IR(基于寄存器),虚拟机,GUI,VFS原理:执行程序时,即时编译代码并执行所生成的二进制指令,按需加载。介绍架构是C / C ++ ,渲染用...

    lua 程序设计学习.doc 版

    1.3 词法约定 1.4 命令行方式 第2章 类型和值 2.1 Nil 2.2 Booleans 2.3 Numbers 2.4 Strings 2.5 Functions 2.6 Userdata and Threads 第3章 表达式 3.1 算术运算符 3.2 关系运算符 3.3 逻辑运算符 3.4 连接运算符 ...

    hua:Hua(㕦)是lua编译器的一种类似hy的lisp语言

    华 Hua(㕦)是lua编译器的一种类似于的lisp语言。 它利用hy的解析器和宏扩展机制,并... Hua(和lua)具有适当的词法作用域实现。 例如,嵌套的let在hy中被打破,而hua完全支持嵌套的let 。 Lua被广泛地嵌入到主机应用

    [易语言]火花代码编辑器3.4最新版源码,封装scintilla控件

    最新版支持Basic C PHP Lua Python ASM等120种语言的词法解析 代码折叠 添加标签 文本搜索功能一如既往强大 新增2000种宏 现在封装为易语言模块 将模块源码及实例奉出 "&gt;最新的scintilla版本全新封装易语言模块...

    libmarpa-bindings:基于libffi和Kollos的libmarpa绑定

    正在编写一个接口(语法,识别器/词法分析器,评估器)。 Python 可以通过cffi从Python调用libmarpa C函数(并进行错误检查)。 Sample ,也是json.c的端口,带有基于Python正则表达式的手写词法分析器。 C# ...

    nginx_config_parser:Nginx上游解析器

    介绍通过 HTTP接口用来 查看/添加/删除 Nginx 反向代理的节点原理通过类似于 lex/yacc 的词法和语法分析,解析nginx upstream文本配置,并生成对象通过接口操作对象内的数据,并生成新的upstream文本配置。...

    pllua-deprecated:[已弃用]该存储库不再维护。 请按照https

    PL / Lua为Lua带来了Lua的强大功能和简便性,包括:内存占用少,语法简单,词法作用域,作为一等值的功能以及用于非抢先线程的协程。 作为一个简单的示例,请考虑以下hello函数: # CREATE FUNCTION hello

    notepad2-mod:寻找开发人员-Notepad2-mod,Notepad2分支,快速且轻便的类似Notepad的文本编辑器,具有语法突出显示功能

    记事本2-mod 基于刘凯和其他人的补丁程序的Notepad2的修改版本(分支)... 如果您发现任何错误,或对所实施的词法分析器任何建议(而不是只)随时提供补丁/拉请求。 如果没有补丁或请求请求,则很可能无法修复/实施任

    papageno:帕雷尔·帕瑟(Parrallel PArser)总经理

    生成的解析器是独立的,可以与常见的GNU Flex生成的词法分析器一起使用,而无需付出更多努力。 生成的解析器已在x86_64和ARM体系结构上成功测试。 PAPAGENO在Python 2.x中实现。 作者和贡献者 亚历山德罗·巴伦吉...

Global site tag (gtag.js) - Google Analytics