前言

入口

rb_iseq_compile_with_option 函数是语法分析与中间代码生成的入口,这里仅列出和语法分析 & 中间代码生成相关的代码块

// iseq.c

rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line,
    const struct rb_block *base_block, VALUE opt) {
    ...
    // 声明一个函数指针 parse
    NODE *(*parse)(VALUE parser, VALUE fame, VALUE file, int start);
    // 语法分析树根节点
    NODE *INITIALIZED node;
    if (RB_TYPE_P(src, T_FILE)) {
        parse = rb_parser_compile_file_path;
    } else {
        parse = rb_parser_compile_string_path;
    }
    // 创建语法分析器对象
    const VALUE parser = rb_parser_new();
    rb_parser_set_context(parser, base_block, FALSE);
    // 调用 parse 函数指针指向的语法分析函数,返回 AST 根节点
    node = (*parse)(parser, file, src, ln);
    iseq = rb_iseq_new_with_opt(node, label, file, absolute_path, line, parent, type, &option);
    return iseq;
}

语法分析

rb_parser_compile_file_path

rb_parser_compile_string_path

该函数用于解析一段包含 Ruby 源代码的字符串:

// ripper.c

NODE* rb_parser_compile_string_path(VALUE vparser, VALUE f, VALUE s, int line)
{
    must_be_ascii_compatible(s);
    return parser_compile_string(vparser, f, s, line);
}

简单起见,我们直接列出 parser_compile_string 的调用栈

parser_compile_string @ ripper.c
    yycompile @ ripper.c
        yycompile0 @ ripper.c

yycompile0 会调用 yyparse(实际上是 ruby_yyparse 的宏定义),进入 YACC 语法分析器自动生成的代码

中间代码生成

rb_iseq_new_with_opt

rb_iseq_new_with_opt 函数根据语法分析生成的 AST 生成中间代码并保存在 rb_iseq_t 结构体中,详细部分可以参考Ruby 2.x 源代码分析:语法分析 & 中间代码生成 之 数据结构


xingpingz
122 声望64 粉丝

博学,审问,慎思,明辨,力行