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);
}
}