先看一下在打开文件里用到的一个函数 lua_setinput
void lua_setinput (Input fn) { current = ‘ ‘; input = fn; if (yytext == NULL) { textsize = MINBUFF; yytext = newvector(textsize, char); } }
设置当前是的输入字符为空格。
设置函数指针,函数指针的定义为:
typedef int (*Input) (void);
即:函数指针指向一个无参的函数,返回一个整数类型。
如果 yytext 为空,则设置其大小,并给它分配内存。newvector 内存分配宏,在 mem.h 中定义。Lua2.4 中的内存分配相关方法都在 mem.h 中声明。
char *lua_lasttext (void) { *yytextLast = 0; return yytext; }
在语法错误时会调用到它,以获取出错处的输入文本。
static struct { char *name; int token; } reserved [] = { {"and", AND}, {"do", DO}, {"else", ELSE}, {"elseif", ELSEIF}, {"end", END}, {"function", FUNCTION}, {"if", IF}, {"local", LOCAL}, {"nil", NIL}, {"not", NOT}, {"or", OR}, {"repeat", REPEAT}, {"return", RETURN}, {"then", THEN}, {"until", UNTIL}, {"while", WHILE} }; #define RESERVEDSIZE (sizeof(reserved)/sizeof(reserved[0])) void luaI_addReserved (void) { int i; for (i=0; i<RESERVEDSIZE; i++) { TaggedString *ts = lua_createstring(reserved[i].name); ts->marked = reserved[i].token; /* reserved word (always > 255) */ } }
定义保留字,或叫关键字。
结构体 name 字段是名字,token 是保留字的值。保留字的值在词法分析的时候会用到。
luaI_addReserved 把所有保留字添加到全局字符串中去。同时设置其为不可回收,也就是把 TaggedString 的 marked 字段设置为上面提到的保留字的值。
luaY_lex 是词法分析的主要部分,它内部是一个循环,输入中的字符一经词法分析之后变成一个个的 token. token 有几种:
一个整数值,在 parser.c 中定义的一些宏,比如 WRONGTOKEN, IF, THEN 之类的, 直接表示它自己的,就是看到这个整数值,它的意思明确的表示了自己.
一个整数值和一个表示内容的数据结构 YYSTYPE luaY_lval,像 NAME, NUMBER 就是此类. 比如 NUMBER,返回一个这个类型则只知道 token 是一个数值,至于具体数值是什么,要看 luaY_lval 的 vFloat 字段.
luaY_lex 就不一行一行的看了,里面相对没有什么难点,照着每个 switch case 一点点来就好。注意就是这里面的和长字符串表示,就是由两个左中括号起头的字符串,这里是特别处理,长字符串中的内容全部保持原样。
词法分析先到这里了。
----------------------------------------
记一下到目前为止的问题:
lex.c
> newvector 内存分配相关的方法
> lua_createstring 是什么? TaggedString 是个什么数据结构?
> luaI_codedebugline 是什么? 调试相关信息有哪些?
inout.c
> luaI_createfixedstring 是什么? 那个 TaggedString 是个什么数据结构?
luac.c
> do_compile 里的 TFunc 是什么?那个初始化 luaI_initTFunc 是什么?
> lua_parser 是什么? do_dump 方法里调的那几个方法又分别是干什么的?
----------------------------------------