本章我们来看table的基本操作

1. 一个简单的例子

local a = {1,2,3}
a[6] = 1
a["aaa"]= 1

1.1 执行我们的例子

gafq test/hello.gafq

1.有了上一节的基础我们直接来到词法分析处

//gparser.c
// 解释器,解释文件内容
Proto *gafqY_parser(gafq_State *L, ZIO *z, Mbuffer *buff, const char *name)
{
    struct LexState lexstate;
    struct FuncState funcstate;
    gafqX_next(&lexstate); // 读取第一个token
}

2.词法分析

glex.c

void gafqX_next(LexState *ls)
{
    ...
    ls->t.token = glex(ls, &ls->t.seminfo); 读取下一个token
    ...
}

// 读取下一个token, 词法分析 SemInfo是语义信息
static int glex(LexState *ls, SemInfo *seminfo)
{
    gafqZ_resetbuffer(ls->buff);
    for (;;)
    {
        switch (ls->current)// 首先我们的例子第一个字节是local中的l 这里ls_current = 108 就是l的ascii码
        {
        default:
        {
            // 判断是字母
            if (isalpha(ls->current) || ls->current == '_')
            {
                TString *ts;
                // 循环如果接下去的字符是数字,字符或者下划线就不断读取
                do
                {
                    save_and_next(ls);
                } while (isalnum(ls->current) || ls->current == '_');
                // 前面的读取操作,到这里,我们的ls->buff 等于 local
                ts = gafqX_newstring(ls, gafqZ_buffer(ls->buff), gafqZ_bufflen(ls->buff));
                if (ts->tsv.reserved > 0) // 这里得到的字符串ts 的值是12, 认为这是一个关键字
                    return ts->tsv.reserved - 1 + FIRST_RESERVED;

            }
        }
        }
    }
}

3.回到1中,读取了第一个token是local 12, 开始解析整个文件chunk

// 解释器,解释文件内容
3.1 Proto *gafqY_parser(gafq_State *L, ZIO *z, Mbuffer *buff, const char *name)
{
    ...
    gafqX_next(&lexstate);
    chunk(&lexstate);
    ...
}

// 这里是解析代码块?
3.2 static void chunk(LexState *ls)
{
    -- 不是结尾就不断解析
    while (!islast && !block_follow(ls->t.token))
    {
        islast = statement(ls);
    }
}

// 判断当前的token, 根据token获取接下去解析的规则?
3.3 static int statement(LexState *ls)
{
    switch (ls->t.token)
    {
    case TK_LOCAL:
    {                                
        gafqX_next(ls);                // 跳过local的token
        localstat(ls);
        return 0;
    }
    }
}

3.4 static void localstat(LexState *ls)
{
    ...
    if (testnext(ls, '=')) // 跳过 61 '='
        nexps = explist1(ls, &e); // 准备解析 = 后面的东西
    ...
}

//解析参数列表?, 变量的值
3.5 static int explist1(LexState *ls, expdesc *v)
{
    ...
    expr(ls, v); // 285(TK_NAME)
    while (testnext(ls, ','))
    {
        gafqK_exp2nextreg(ls->fs, v);
        expr(ls, v);
        n++;
    }
    return n;
}

3.6 static BinOpr subexpr(LexState *ls, expdesc *v, unsigned int limit)
{
    uop = getunopr(ls->t.token); // 这里现在token是123
    simpleexp(ls, v); // 认为后面是简单类型
}


3.7 static void simpleexp(LexState *ls, expdesc *v)
{
    switch (ls->t.token) // token = 123
    {
    case '{':
    {
        constructor(ls, v);
        return;
    }
}

// 这里解析{ 之后的东西, 认为是个table
3.8 static void constructor(LexState *ls, expdesc *t)
{
    checknext(ls, '{');
    do
    {
        gafq_assert(cc.v.k == VVOID || cc.tostore > 0);
        if (ls->t.token == '}')
            break;
        switch (ls->t.token) // 接下去是个数字 token = 284
        {
        default:
        {
            listfield(ls, &cc);
            break;
        }
        }
    } while (testnext(ls, ',') || testnext(ls, ';'));
}


3.9 static void listfield(LexState *ls, struct ConsControl *cc)
{
    expr(ls, &cc->v);
}

3.10 static BinOpr subexpr(LexState *ls, expdesc *v, unsigned int limit)
{
    ...
    simpleexp(ls, v);
    ...
}

//简单类型, 数字 | 字符串 | nil | 对 | 错 |  ... |  { | 函数体 |
3.11 static void simpleexp(LexState *ls, expdesc *v)
{
    switch (ls->t.token) // token = 284
    {
    case TK_NUMBER:
    {
        init_exp(v, VKNUM, 0);
        v->u.nval = ls->t.seminfo.r;
        break;
    }
    }
    gafqX_next(ls); // 之后token = 44
}

// 回到了3.18的地方
3.12 // 这里解析{ 之后的东西, 认为是个table
static void constructor(LexState *ls, expdesc *t)
{

    checknext(ls, '{');
    do
    {
        gafq_assert(cc.v.k == VVOID || cc.tostore > 0);
        if (ls->t.token == '}')
            break;
        closelistfield(fs, &cc);
        switch (ls->t.token)
        {
        case TK_NAME:
        { /* may be listfields or recfields */
            gafqX_lookahead(ls);
            if (ls->lookahead.token != '=') /* expression? */
                listfield(ls, &cc);
            else
                recfield(ls, &cc);
            break;
        }
        case '[':
        { /* constructor_item -> recfield */
            recfield(ls, &cc);
            break;
        }
        default:
        { /* constructor_part -> listfield */
            listfield(ls, &cc);
            break;
        }
        }
    } while (testnext(ls, ',') || testnext(ls, ';'));// 遇到,或者;就跳过
}

3.13 一路解析完回到了3.2的地方 开始解析 例子 a[6] = 1
static void chunk(LexState *ls)
{
    while (!islast && !block_follow(ls->t.token))
    {
        islast = statement(ls); // 现在的token是新的一样 token=285  TK_NAME
        testnext(ls, ';');
    }
}

// 3.14
static int statement(LexState *ls)
{
    switch (ls->t.token) // token=285  TK_NAME
    {
    default:
    {
        exprstat(ls);
        return 0;
    }
    }
}

// 3.15 表达式解析
static void exprstat(LexState *ls)
{
    ...
    primaryexp(ls, &v.v);
    ...
}

// 3.16 表达式解析
static void primaryexp(LexState *ls, expdesc *v)
{
    prefixexp(ls, v);
}

// 3.17 解析 变量名 或者是()
static void prefixexp(LexState *ls, expdesc *v)
{
    switch (ls->t.token)
    {
    case TK_NAME:
    {
        singlevar(ls, v);
        return;
    }
    }
}

// 3.18 简单的变量名
static void singlevar(LexState *ls, expdesc *var)
{
    TString *varname = str_checkname(ls); // 检查是TK_NAME就跳下一个
}

// 3.19 回到 3.16的地方
// 表达式解析
static void primaryexp(LexState *ls, expdesc *v)
{
    prefixexp(ls, v);
    for (;;)
    {
        switch (ls->t.token)  现在tokens是91
        {
        case '[':
        { /* `[' exp1 `]' */
            expdesc key;
            yindex(ls, &key);
        }

    }
}


// 3.20 解析a[6] 中[]中间的表达式
static void yindex(LexState *ls, expdesc *v)
{
    gafqX_next(ls);
    expr(ls, v); // 解析出里面的表达是 284(TK_NUMBER)
    gafqK_exp2val(ls->fs, v);
    checknext(ls, ']');
}


// 3.21 回到3.15的地方,开始解析 a[6] 后面的东西
static void exprstat(LexState *ls)
{
    ...
    primaryexp(ls, &v.v);
    ...
    assignment(ls, &v, 1); //到这里token等于61
}


//3.22 从exprstat来, 这里是计算变量赋值表达式
static void assignment(LexState *ls, struct LHS_assign *lh, int nvars)
{
    expdesc e;

        int nexps;
        checknext(ls, '=');
        nexps = explist1(ls, &e);
    }

}

//3.23  解析参数列表?, 变量的值
static int explist1(LexState *ls, expdesc *v)
{

    expr(ls, v);
    return n;
}

3.24 一路解析完回到了3.2的地方 开始解析 例子a["aaa"]= 1
static void chunk(LexState *ls)
{
    while (!islast && !block_follow(ls->t.token))
    {
        islast = statement(ls); // 现在的token是新的一样 token=285  TK_NAME
        testnext(ls, ';');
    }
}

//3.25
static int statement(LexState *ls)
{
    switch (ls->t.token)
    {
    default:
    {
        exprstat(ls);
    }
    }
}
//3.26
static void exprstat(LexState *ls)
{
    primaryexp(ls, &v.v); // 解析 a["aaa"] 部分
    assignment(ls, &v, 1); // 解析 = 1部分
}




4.解析出的token是什么

// 我们的例子
local a = {1,2,3}
a[6] = 1
a["aaa"]= 1

268(TK_LOCAL) -> 285(TK_NAME) -> 61('=') -> 123('{') -> 284(TK_NUMBER) -> 44(',') -> 284(TK_NUMBER) -> 44(',') -> 284(TK_NUMBER) -> 125('}')
285(TK_NAME) -> 91('[') -> 284(TK_NUMBER) -> 93(']') -> 61('=') -> 284(TK_NUMBER)
285(TK_NAME) -> 91('[') -> 286(TK_STRING) -> 93(']') -> 61('=') -> 284(TK_NUMBER)

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注