阅读词法分析器 添加相应注释

This commit is contained in:
ranchuan
2024-10-21 19:21:54 +08:00
parent f0aa32fbfb
commit 1f31eb2c14
5 changed files with 62 additions and 19 deletions

View File

@@ -48,17 +48,25 @@
/*
** add 1 to char to allow index -1 (EOZ)
luai_ctype_ 是一个表 里面存储的字符属性,
这个表可以快速获得字符属性
*/
#define testprop(c,p) (luai_ctype_[(c)+1] & (p))
/*
** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_'
*/
// 字母和下划线
#define lislalpha(c) testprop(c, MASK(ALPHABIT))
// 字母 下划线 数字
#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT)))
// 数字
#define lisdigit(c) testprop(c, MASK(DIGITBIT))
// 空白字符
#define lisspace(c) testprop(c, MASK(SPACEBIT))
// 可打印字符
#define lisprint(c) testprop(c, MASK(PRINTBIT))
// 16进制数字
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
@@ -67,6 +75,8 @@
** for '.'. That is enough for Lua needs. ('check_exp' ensures that
** the character either is an upper-case letter or is unchanged by
** the transformation, which holds for lower-case letters and '.'.)
在ASCII中这个'ltolower'对于字母字符和'.'都是正确的。这足以满足Lua的需求。
'check_exp'确保字符要么是大写字母,要么不受转换的影响,这适用于小写字母和'.'。)
*/
#define ltolower(c) \
check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \

View File

@@ -199,7 +199,7 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
** =======================================================
*/
// 如果当前字符等于c则获取下一个字符 返回1否则仅返回0
static int check_next1 (LexState *ls, int c) {
if (ls->current == c) {
next(ls);
@@ -212,6 +212,8 @@ static int check_next1 (LexState *ls, int c) {
/*
** Check whether current char is in set 'set' (with two chars) and
** saves it
如果当前字符是set中两个字符中任意一个 则把当前字符保存到缓冲区中获取下一个字符返回1
否则仅返回0
*/
static int check_next2 (LexState *ls, const char *set) {
lua_assert(set[2] == '\0');
@@ -228,13 +230,17 @@ static int check_next2 (LexState *ls, const char *set) {
** This function is quite liberal in what it accepts, as 'luaO_str2num'
** will reject ill-formed numerals. Roughly, it accepts the following
** pattern:
这个函数在接受什么方面非常自由因为“luaO_str2num”将拒绝格式错误的数字。
大致上,它接受以下模式
**
** %d(%x|%.|([Ee][+-]?))* | 0[Xx](%x|%.|([Pp][+-]?))*
**
** The only tricky part is to accept [+-] only after a valid exponent
** mark, to avoid reading '3-4' or '0xe+1' as a single number.
唯一棘手的部分是只在有效的指数标记后接受[+-]以避免将“3-4”或“0xe+1”读取为单个数字。
**
** The caller might have already read an initial dot.
调用者可能已经读取了初始点。
*/
static int read_numeral (LexState *ls, SemInfo *seminfo) {
TValue obj;
@@ -273,6 +279,10 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
** sequence is well formed, return its number of '='s + 2; otherwise,
** return 1 if it is a single bracket (no '='s and no 2nd bracket);
** otherwise (an unfinished '[==...') return 0.
读取序列“[=*[”或“]=*]”,保留最后一个括号。
如果序列格式良好,则返回其编号'='s+2
否则,如果它是一个单括号(没有'='和第二个括号则返回1
否则(未完成的“[==…”返回0。
*/
static size_t skip_sep (LexState *ls) {
size_t count = 0;
@@ -327,7 +337,7 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) {
luaZ_bufflen(ls->buff) - 2 * sep);
}
// 字符串已经结束了,但是最近字符不是 EOZ 则报错
static void esccheck (LexState *ls, int c, const char *msg) {
if (!c) {
if (ls->current != EOZ)
@@ -561,18 +571,22 @@ static int llex (LexState *ls, SemInfo *seminfo) {
do {
save_and_next(ls);
} while (lislalnum(ls->current));
// 如果表中已经存在这个字符 则直接返回这个字符,否则创建
ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
luaZ_bufflen(ls->buff));
seminfo->ts = ts;
if (isreserved(ts)) /* reserved word? */
// 保留字符直接返回其 token编码
return ts->extra - 1 + FIRST_RESERVED;
else {
// 不是保留字则类型为名称
return TK_NAME;
}
}
else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */
int c = ls->current;
next(ls);
// 单字节符号直接返回原值
return c;
}
}
@@ -581,6 +595,7 @@ static int llex (LexState *ls, SemInfo *seminfo) {
}
// 解析下一个token
void luaX_next (LexState *ls) {
ls->lastline = ls->linenumber;
if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
@@ -591,7 +606,7 @@ void luaX_next (LexState *ls) {
ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
}
// 向前解析一个token
int luaX_lookahead (LexState *ls) {
lua_assert(ls->lookahead.token == TK_EOS);
ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);

View File

@@ -131,7 +131,7 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
}
}
// hex字符转数字
int luaO_hexavalue (int c) {
if (lisdigit(c)) return c - '0';
else return (ltolower(c) - 'a') + 10;
@@ -319,7 +319,7 @@ size_t luaO_str2num (const char *s, TValue *o) {
return (e - s) + 1; /* success; return string size */
}
// utf8编码去除编码头
int luaO_utf8esc (char *buff, unsigned long x) {
int n = 1; /* number of bytes put in buffer (backwards) */
lua_assert(x <= 0x7FFFFFFFu);

View File

@@ -19,49 +19,66 @@
** variable/expression. It has a description of its "main" value plus a
** list of conditional jumps that can also produce its value (generated
** by short-circuit operators 'and'/'or').
表达式和变量描述符。变量和表达式的代码生成可以延迟以进行优化;
“expdesc”结构描述了一个潜在的延迟变量/表达式。
它有一个“主”值的描述,还有一个条件跳转列表,这些跳转也可以产生它的值(由短路运算符和“/”或“生成)。
*/
/* kinds of variables/expressions */
// 变量/表达式的种类
typedef enum {
// 空表
VVOID, /* when 'expdesc' describes the last expression of a list,
this kind means an empty list (so, no expression) */
VNIL, /* constant nil */
VTRUE, /* constant true */
VFALSE, /* constant false */
VNIL, /* constant nil 空类型*/
VTRUE, /* constant true */
VFALSE, /* constant false */
VK, /* constant in 'k'; info = index of constant in 'k' */
VKFLT, /* floating constant; nval = numerical float value */
VKINT, /* integer constant; ival = numerical integer value */
VKFLT, /* floating constant; nval = numerical float value 浮点数*/
VKINT, /* integer constant; ival = numerical integer value 定点数*/
// 字符串
VKSTR, /* string constant; strval = TString address;
(string is fixed by the lexer) */
// 表达式在寄存器中有值
VNONRELOC, /* expression has its value in a fixed register;
info = result register */
// 局部变量
VLOCAL, /* local variable; var.ridx = register index;
var.vidx = relative index in 'actvar.arr' */
// 全局变量?
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
// 常量
VCONST, /* compile-time <const> variable;
info = absolute index in 'actvar.arr' */
// 已编号的变量
VINDEXED, /* indexed variable;
ind.t = table register;
ind.idx = key's R index */
// 已编号的全局变量?
VINDEXUP, /* indexed upvalue;
ind.t = table upvalue;
ind.idx = key's K index */
// 已编号的整形常量
VINDEXI, /* indexed variable with constant integer;
ind.t = table register;
ind.idx = key's value */
// 已编号的字符串
VINDEXSTR, /* indexed variable with literal string;
ind.t = table register;
ind.idx = key's K index */
// 跳转指令
VJMP, /* expression is a test/comparison;
info = pc of corresponding jump instruction */
// 表达式可以把结果放在任意一个寄存器
VRELOC, /* expression can put result in any register;
info = instruction pc */
VCALL, /* expression is a function call; info = instruction pc */
VVARARG /* vararg expression; info = instruction pc */
VCALL, /* expression is a function call; info = instruction pc 表达式是一个函数*/
VVARARG /* vararg expression; info = instruction pc 参数表达式*/
} expkind;
// 变量
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR)
// 已编号的变量
#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR)
@@ -87,12 +104,12 @@ typedef struct expdesc {
/* kinds of variables */
#define VDKREG 0 /* regular */
#define RDKCONST 1 /* constant */
#define RDKTOCLOSE 2 /* to-be-closed */
#define RDKCTC 3 /* compile-time constant */
#define VDKREG 0 /* regular 正则*/
#define RDKCONST 1 /* constant 常数*/
#define RDKTOCLOSE 2 /* to-be-closed 闭包*/
#define RDKCTC 3 /* compile-time constant 编译时常数*/
/* description of an active local variable */
/* description of an active local variable 描述一个活动的局部变量*/
typedef union Vardesc {
struct {
TValuefields; /* constant value (if it is a compile-time constant) */
@@ -106,7 +123,7 @@ typedef union Vardesc {
/* description of pending goto statements and label statements */
/* description of pending goto statements and label statements 未决goto语句和标签语句的描述*/
typedef struct Labeldesc {
TString *name; /* label identifier */
int pc; /* position in code */

View File

@@ -31,6 +31,7 @@
/*
** test whether a string is a reserved word
是否是保留字
*/
#define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0)