Lua 5.1.3源代码分析之词法分析[1]
词法分析器在llex.h, llex.c两个文件中实现。
1
|
/* maximum length of a reserved word */
|
2
|
#define TOKEN_LEN (sizeof("function")/sizeof(char))
|
这一句说的意思是,function是Lua的保留字中最长的保留字,其它所有的保留字单词长度不应该超过它。
01
|
enum RESERVED {
|
02
|
/* terminal symbols denoted by reserved words */
|
03
|
TK_AND = FIRST_RESERVED, TK_BREAK,
|
04
|
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
|
05
|
TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
06
|
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
|
07
|
/* other terminal symbols */
|
08
|
TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
|
09
|
TK_NAME, TK_STRING, TK_EOS
|
10
|
};
|
这一句定义了保留字的内部符号,叫做“终止符”,意思就是词法分析器一找到这些单词,就自动记录并断开。
前21个是基础的保留字的程序中对应的宏名称,后10个是一些运算符对应的宏名称。定义这样的符号集,是为了后面写解析器时方便返回值。
01
|
/* ORDER RESERVED */
|
02
|
const char * const luaX_tokens [] = {
|
03
|
"and" , "break" , "do" , "else" , "elseif" ,
|
04
|
"end" , "false" , "for" , "function" , "if" ,
|
05
|
"in" , "local" , "nil" , "not" , "or" , "repeat" ,
|
06
|
"return" , "then" , "true" , "until" , "while" ,
|
07
|
".." , "..." , "==" , ">=" , "<=" , "~=" ,
|
08
|
"<number>" , "<name>" , "<string>" , "<eof>" ,
|
09
|
NULL
|
10
|
};
|
这些是真实的保留字,与上面那个与前一个完全是一一对应的,所以要变位置的话,要两个同时变。这里写明了真正的保留字符号,存在数组luaX_tokens 里面。
1
|
/* number of reserved words */
|
2
|
#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
|
这一句是计算所有的保留字的个数。FIRST_RESERVED在前面被定义为257,不知道为什么要这么定义。设计这样一个单数值的方式很巧妙。使得后面编程时,只需返回一个单变量索引值就可以知道扫描到一个什么记号了。给后面编程带来很大简化工作。注意:TK_WHILE是保留字中的最后一个保留字。
01
|
typedef struct LexState {
|
02
|
int current; /* current character (charint) */
|
03
|
int linenumber; /* input line counter */
|
04
|
int lastline; /* line of last token `consumed' */
|
05
|
Token t; /* current token */
|
06
|
Token lookahead; /* look ahead token */
|
07
|
struct FuncState *fs; /* `FuncState' is private to the parser */
|
08
|
struct lua_State *L;
|
09
|
ZIO *z; /* input stream */
|
10
|
Mbuffer *buff; /* buffer for tokens */
|
11
|
TString *source; /* current source name */
|
12
|
char decpoint; /* locale decimal point */
|
13
|
} LexState;
|
LexState是词法解析器在解析过程中的一个状态结构。这里面这些结构都非常重要。
成员变量 | 意义 |
current | 指示当前的字符 (相对于文件开头的偏移位置),可以看做一个指针,实际是一个索引; |
linenumber | 指示当前解析器的current指针的行位置; |
lastline | 指示当前文件里面的最后一个有作用的记号所在的行; |
t | 当前的记号; |
lookahead | 下一个 (待分析的) 记号; |
fs | 函数状态指针,暂时不明何用; |
L | Lua的状态机指针; |
z | 输入流; |
buff | 用于存储所有记号的一个缓存; |
source | 当前源码的的名字,是不是文件名还不太清楚; |
decpoint | 当前十进制小数点?不太清楚。后面给其赋值为’.'。看后面的代码,估计是认为在有些地区或行业里面,十进制小数点不一定是’.'。所以当一个变量先存起来了。 |
下面继续往下看:
01
|
/*
|
02
|
** String headers for string table
|
03
|
*/
|
04
|
typedef union TString {
|
05
|
L_Umaxalign dummy; /* ensures maximum alignment for strings */
|
06
|
struct {
|
07
|
CommonHeader;
|
08
|
lu_byte reserved;
|
09
|
unsigned int hash;
|
10
|
size_t len;
|
11
|
} tsv;
|
12
|
} TString;
|
Lua中字符串表的一个头结构,在整个解析过程字符串的存储中起到很重要的作用。
1
|
void luaX_init (lua_State *L) {
|
2
|
int i;
|
3
|
for (i=0; i<NUM_RESERVED; i++) {
|
4
|
TString *ts = luaS_new(L, luaX_tokens[i]);
|
5
|
luaS_fix(ts); /* reserved words are never collected */
|
6
|
lua_assert( strlen (luaX_tokens[i])+1 <= TOKEN_LEN);
|
7
|
ts->tsv.reserved = cast_byte(i+1); /* reserved word */
|
8
|
}
|
9
|
}
|
luaX_init 函数的功能是将所所的保留字设置标志量,以便在搜集的时候,会自动略过这些保留字。luaS_fix功能是给保留字变量设置防搜集标志。ts->tsv.reserved = cast_byte(i+1) 给各个保留字编序号,以1起始开始编号。
1
|
const char *luaX_token2str (LexState *ls, int token) {
|
2
|
if (token < FIRST_RESERVED) {
|
3
|
lua_assert(token == cast(unsigned char , token));
|
4
|
return ( iscntrl (token)) ? luaO_pushfstring(ls->L, "char(%d)" , token) :
|
5
|
luaO_pushfstring(ls->L, "%c" , token);
|
6
|
}
|
7
|
else
|
8
|
return luaX_tokens[token-FIRST_RESERVED];
|
9
|
}
|
luaX_token2str将以数值形式表示的记号序号转换成相应的字符,如果是大于256的值,会直接转换为保留字(多个字符),而不是一个字符。只有小于等于256的,才转换为一个字符,并且这其中还要区分普通字符还是控制字符。 这里就体现出它设计FIRST_RESERVED等于257的用意了,统一化,一次性处理。
Lua 5.1.3源代码分析之词法分析[1]相关推荐
- php输出源代码,PHP源代码分析-echo实现详解
PHP源代码分析-echo实现详解 echo,这个是PHP运用得最多的标记之一,算不上是函数,PHP手册里这么写的,因为它没有返回值.今天好奇就去看看PHP的源代码,因为echo不是一般的函数,所以找 ...
- Android系统默认Home应用程序(Launcher)的启动过程源代码分析
在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应 ...
- 《LINUX3.0内核源代码分析》第一章:内存寻址
https://blog.csdn.net/ekenlinbing/article/details/7613334 摘要:本章主要介绍了LINUX3.0内存寻址方面的内容,重点对follow_page ...
- Scrapy源代码分析-经常使用的爬虫类-CrawlSpider(三)
CrawlSpider classscrapy.contrib.spiders.CrawlSpider 爬取一般站点经常使用的spider.其定义了一些规则(rule)来提供跟进link的方便的机制. ...
- Android 中View的绘制机制源代码分析 三
到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编 ...
- Android应用程序进程启动过程的源代码分析(1)
Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制:这两个特点都是在进程的初始化过程中实 ...
- AFNetworking 源代码分析
关于其他 AFNetworking 源代码分析的其他文章: AFNetworking 概述(一) AFNetworking 的核心 AFURLSessionManager(二) 处理请求和响应 AFU ...
- Hadoop源代码分析 - MapReduce(转载)
1. Hadoop源代码分析(MapReduce概论) http://caibinbupt.javaeye.com/blog/336467
- RTMPdump(libRTMP) 源代码分析 3: AMF编码
2019独角兽企业重金招聘Python工程师标准>>> 注:此前写了一些列的分析RTMPdump(libRTMP)源代码的文章,在此列一个列表: RTMPdump 源代码分析 1: ...
最新文章
- 目标检测--Object Detection via Aspect Ratio and Context Aware
- Android fill_parent、wrap_content和match_parent的区别
- js deep clone 深克隆
- python下载手机-QPython下载
- 【干货】H3C如何配置VLAN-trunk 二层隔离技术?
- 【收藏】CentOS 7 安装NFS
- bzoj 1221: [HNOI2001] 软件开发
- MFC学习之路之多媒体 --(1) DirectShow
- C++STL与泛型编程 侯捷 (1)
- 如何执行字符串的PHP代码
- CentOS查看分区的方式
- eclipse cdt无法调试_eclipse导入Web项目并且部署到tomcat(超详细)
- c#.net利用RNGCryptoServiceProvider产生任意范围强随机数的办法
- 交易系统开发(七)——交易延迟分析
- app录制回放 jmeter_Jmeter使用之脚本录制回放
- CentOS安装Nacos后,输入默认用户名和密码nacos/nacos,提示“用户名或密码错误”
- 基于BP神经网络的车牌识别问题研究附Matlab代码
- Centos 7分区合并
- 04 【CSS选择器 】
- 算法分析:时间和空间复杂度