thrift的编译器2

从元明
2023-12-01

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

}



 类似资料: