main函数中调用了两个非常重要的函数,parse()和generate(),parse()解析thrift文件,生产语法树,即全局变量g_program。generate()通过这棵语法树,生产具体的语言代码。具体看看这两个函数。thrift的词法解析和语法解析用了flex和bison。
void parse(t_program* program, t_program* parent_program) {
// Get scope file path 获取thrift文件的路径
string path = program->get_path();
// Set current dir global, which is used in the include_file function
g_curdir = directory_name(path);
g_curpath = path;
// Open the file
yyin = fopen(path.c_str(), "r");
if (yyin == 0) {
failure("Could not open input file: \"%s\"", path.c_str());
}
// Create new scope and scan for includes
// 进行第一次yyparse,找出所有的include文件。
pverbose("Scanning %s for includes\n", path.c_str());
g_parse_mode = INCLUDES;
g_program = program;
g_scope = program->scope();
try {
yylineno = 1;
if (yyparse() != 0) {
failure("Parser error during include pass.");
}
} catch (string x) {
failure(x.c_str());
}
fclose(yyin);
// Recursively parse all the include programs
vector<t_program*>& includes = program->get_includes();
vector<t_program*>::iterator iter;
for (iter = includes.begin(); iter != includes.end(); ++iter) {
parse(*iter, program);
}
// Parse the program file
// 第二次yyparse,生成语法树
g_parse_mode = PROGRAM;
g_program = program;
g_scope = program->scope();
g_parent_scope = (parent_program != NULL) ? parent_program->scope() : NULL;
g_parent_prefix = program->get_name() + ".";
g_curpath = path;
yyin = fopen(path.c_str(), "r");
if (yyin == 0) {
failure("Could not open input file: \"%s\"", path.c_str());
}
pverbose("Parsing %s for types\n", path.c_str());
yylineno = 1;
try {
if (yyparse() != 0) {
failure("Parser error during types pass.");
}
} catch (string x) {
failure(x.c_str());
}
fclose(yyin);
}
void generate(t_program* program, const vector<string>& generator_strings) { // Oooohh, recursive code generation, hot!! // 是否递归的生成include文件的代码 if (gen_recurse) { const vector<t_program*>& includes = program->get_includes(); for (size_t i = 0; i < includes.size(); ++i) { // Propogate output path from parent to child programs includes[i]->set_out_path(program->get_out_path(), program->is_out_path_absolute()); generate(includes[i], generator_strings); } } // Generate code! try { pverbose("Program: %s\n", program->get_path().c_str()); // Compute fingerprints. generate_all_fingerprints(program); if (dump_docs) { dump_docstrings(program); } // 循环生成不同语言的代码 vector<string>::const_iterator iter; for (iter = generator_strings.begin(); iter != generator_strings.end(); ++iter) { t_generator* generator = t_generator_registry::get_generator(program, *iter); if (generator == NULL) { pwarning(1, "Unable to get a generator for \"%s\".\n", iter->c_str()); } else { pverbose("Generating \"%s\"\n", iter->c_str()); generator->generate_program(); // 不同语言实现不同的函数。 delete generator; } } } catch (string s) { printf("Error: %s\n", s.c_str()); } catch (const char* exc) { printf("Error: %s\n", exc); } }