python 语法树生成过程

来源:互联网 发布:西安网络家装设计公司 编辑:程序博客网 时间:2024/06/06 06:29

直接上代码,语法树在C语言里面,就是这个样子:

typedef struct _mp_parse_t {    mp_parse_node_t root;    struct _mp_parse_chunk_t *chunk;} mp_parse_tree_t;

先行知识:

语法(分析)树可以以图形化的方式告诉我们一个start symbol 如何产生(drive) 一串字符, 如果一个非终结符A, 有如下产生式

(production) A -> XYZ, 那么它的分析树将有四个node(节点), A作为parent, X, Y, Z 作为其孩子结点。X,Y, Z ,按照从左到右的

顺序


最后,对于一个上下文无法语法,一个分析树具有如下属性:

1, 根节点由起始符号标识

2. 每一个叶子节点都由终结符或者E(空)标识。

3, 每一个内部节点都是非终结符。


假设源代码是"import uefi".

第一步我们会预先load进来三个字符。

    // preload characters    lex->chr0 = stream_next_byte(stream_data);    lex->chr1 = stream_next_byte(stream_data);    lex->chr2 = stream_next_byte(stream_data);

打开ascii 表即可知道 105(i), 109 (m) 112 (p).

接下来,预先load 一个完整的token.

mp_lexer_next_token_into(lex, true);


然后看看load 进来的token 里面有没有关键字。

这时候,就能看到我们第一次得到的lex.


有了lex之后,我们调用

 mp_parse_tree_t parse_tree = mp_parse(lex, 0);

来做词法分析。

原材料是lex. input kind, 由一个叫parser 的机器来处理。

typedef struct _parser_t {    parse_error_t parse_error;    size_t rule_stack_alloc;    size_t rule_stack_top;    rule_stack_t *rule_stack;    size_t result_stack_alloc;    size_t result_stack_top;    mp_parse_node_t *result_stack;    mp_lexer_t *lexer;    mp_parse_tree_t tree;    mp_parse_chunk_t *cur_chunk;    #if MICROPY_COMP_CONST    mp_map_t consts;    #endif} parser_t;


很显然,一开始,我们要对这台机器进行初始化。

    parser.parse_error = PARSE_ERROR_NONE;    parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT;    parser.rule_stack_top = 0;    parser.rule_stack = m_new_maybe(rule_stack_t, parser.rule_stack_alloc);    parser.result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT;    parser.result_stack_top = 0;    parser.result_stack = m_new_maybe(mp_parse_node_t, parser.result_stack_alloc);    parser.lexer = lex;    parser.tree.chunk = NULL;    parser.cur_chunk = NULL;


 parser.lexer  = lex ,相当于把原材料丢给它。

接下来去生成第一个rule. 放到rule stack 里面。

STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {    if (parser->parse_error) {        return;    }    if (parser->rule_stack_top >= parser->rule_stack_alloc) {        rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC, true);        if (rs == NULL) {            parser->parse_error = PARSE_ERROR_MEMORY;            return;        }        parser->rule_stack = rs;        parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC;    }    rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];    rs->src_line = src_line;    rs->rule_id = rule->rule_id;    rs->arg_i = arg_i;}

此时 src_line 等于1, rule_id 等于0, arg_i 等于0.


 简答来说, parse 过程就是一个for()循环里面放一个switch 。

rule->act & RULE_ACT_KIND_MASK 第一次计算出来,为0x10, 所以落到 case RULE_ACT_OR:这一句。




 


0 0
原创粉丝点击