标签:
语法分析器会调用词法分析器。
在语法分析之前,简单的看一下词法分析。
内存管理和 ZIO 输入在词法分析中会用到,因为它们相对比较孤立,不影响主流程的阅读。
上一个版本也看过它们了,这里就不再重复了。
词法分析最重要的函数就是
int luaX_lex (LexState *LS, SemInfo *seminfo);
如果你用其它的词法分析工具生成器,生成的词法分析器也会有个类似的函数。
这个函数主要就是从源代码中读出一个 token 返回给语法分析器。
在语法分析的 next 和 lookhead 中会调用到它:
static void next (LexState *ls) { ls->lastline = ls->linenumber; if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ ls->t = ls->lookahead; /* use this one */ ls->lookahead.token = TK_EOS; /* and discharge it */ } else ls->t.token = luaX_lex(ls, &ls->t.seminfo); /* read next token */ } static void lookahead (LexState *ls) { lua_assert(ls->lookahead.token == TK_EOS); ls->lookahead.token = luaX_lex(ls, &ls->lookahead.seminfo); }
可以看到,返回一个 token 类型和一个表示表示 token 信息的结构体。
typedef union { lua_Number r; TString *ts; } SemInfo; /* semantics information */ typedef struct Token { int token; SemInfo seminfo; } Token;
luaX_lex 返回的就是 Token 结构体中的 token 类型字段。
如果类型字段不足以描述它自己的话,Token 中的 seminfo 字段就派上用场了。
比如:
对于大于小于这种比较运算,直接返回 token 就完事儿了。
case ‘<‘: { next(LS); if (LS->current != ‘=‘) return ‘<‘; else { next(LS); return TK_LE; } } case ‘>‘: { next(LS); if (LS->current != ‘=‘) return ‘>‘; else { next(LS); return TK_GE; } }
而对于像是数值 TK_NUMBER,字符串型 TK_STRING 则需要将具体的 value 设置给 seminfo。
可以认为 Token 结构体表示的为 type-value 或者 key-value 对。
标签:
原文地址:http://my.oschina.net/xhan/blog/500338