📄 actions.cpp
字号:
phrase << "<imageobject><imagedata "; phrase << attr_text; phrase << " fileref=\""; while (first != last) detail::print_char(*first++, phrase.get()); phrase << "\"></imagedata></imageobject>"; // Also add a textobject -- use the basename of the image file. // This will mean we get "alt" attributes of the HTML img. phrase << "<textobject><phrase>"; detail::print_string(fs::basename(img_path), phrase.get()); phrase << "</phrase></textobject>"; phrase << "</inlinemediaobject>"; } void macro_identifier_action::operator()(iterator first, iterator last) const { actions.macro_id.assign(first, last); actions.phrase.push(); // save the phrase } void macro_definition_action::operator()(iterator first, iterator last) const { actions.macro.add( actions.macro_id.begin() , actions.macro_id.end() , actions.phrase.str()); actions.phrase.pop(); // restore the phrase } void template_body_action::operator()(iterator first, iterator last) const { BOOST_ASSERT(actions.template_info.size()); if (actions.templates.find_top_scope(actions.template_info[0])) { boost::spirit::file_position const pos = first.get_position(); detail::outerr(pos.file,pos.line) << "Template Redefinition: " << actions.template_info[0] << std::endl; } actions.template_info.push_back(std::string(first, last)); actions.templates.add( actions.template_info[0] , boost::make_tuple(actions.template_info, first.get_position())); actions.template_info.clear(); } namespace { bool break_arguments( std::vector<std::string>& template_info , std::vector<std::string> const& template_ , boost::spirit::file_position const& pos ) { if (template_.size()-1 != template_info.size()) { while (template_.size()-1 != template_info.size()) { // Try to break the last argument at the first space found // and push it into the back of template_info. Do this // recursively until we have all the expected number of // arguments, or if there are no more spaces left. std::string& str = template_info.back(); std::string::size_type l_pos = str.find_first_of(" \t\r\n"); if (l_pos == std::string::npos) break; std::string first(str.begin(), str.begin()+l_pos); std::string::size_type r_pos = str.find_first_not_of(" \t\r\n", l_pos); std::string second(str.begin()+r_pos, str.end()); str = first; template_info.push_back(second); } if (template_.size()-1 != template_info.size()) { detail::outerr(pos.file, pos.line) << "Invalid number of arguments passed. Expecting: " << template_.size()-2 << " argument(s), got: " << template_info.size()-1 << " argument(s) instead." << std::endl; return false; } } return true; } std::pair<bool, std::vector<std::string>::const_iterator> get_arguments( std::vector<std::string>& template_info , std::vector<std::string> const& template_ , boost::spirit::file_position const& pos , quickbook::actions& actions ) { std::vector<std::string>::const_iterator arg = template_info.begin()+1; std::vector<std::string>::const_iterator tpl = template_.begin()+1; // Store each of the argument passed in as local templates: while (arg != template_info.end()) { std::vector<std::string> tinfo; tinfo.push_back(*tpl); tinfo.push_back(*arg); template_symbol template_(tinfo, pos); if (template_symbol* p = actions.templates.find_top_scope(*tpl)) { detail::outerr(pos.file,pos.line) << "Duplicate Symbol Found" << std::endl; return std::make_pair(false, tpl); } else { actions.templates.add(*tpl, template_); } ++arg; ++tpl; } return std::make_pair(true, tpl); } bool parse_template( std::string& body , std::string& result , boost::spirit::file_position const& template_pos , quickbook::actions& actions ) { simple_phrase_grammar<quickbook::actions> phrase_p(actions); block_grammar<quickbook::actions, true> block_p(actions); // How do we know if we are to parse the template as a block or // a phrase? We apply a simple heuristic: if the body starts with // a newline, then we regard it as a block, otherwise, we parse // it as a phrase. std::string::const_iterator iter = body.begin(); while (iter != body.end() && ((*iter == ' ') || (*iter == '\t'))) ++iter; // skip spaces and tabs bool is_block = (iter != body.end()) && ((*iter == '\r') || (*iter == '\n')); bool r = false; if (actions.template_escape) { // escape the body of the template // we just copy out the literal body result = body; r = true; } else if (!is_block) { // do a phrase level parse iterator first(body.begin(), body.end(), actions.filename.native_file_string().c_str()); first.set_position(template_pos); iterator last(body.end(), body.end()); r = boost::spirit::parse(first, last, phrase_p).full; actions.phrase.swap(result); } else { // do a block level parse // ensure that we have enough trailing newlines to eliminate // the need to check for end of file in the grammar. body.push_back('\n'); body.push_back('\n'); while (iter != body.end() && ((*iter == '\r') || (*iter == '\n'))) ++iter; // skip initial newlines iterator first(iter, body.end(), actions.filename.native_file_string().c_str()); first.set_position(template_pos); iterator last(body.end(), body.end()); r = boost::spirit::parse(first, last, block_p).full; actions.out.swap(result); } return r; } } void do_template_action::operator()(iterator first, iterator) const { boost::spirit::file_position const pos = first.get_position(); ++actions.template_depth; if (actions.template_depth > actions.max_template_depth) { detail::outerr(pos.file,pos.line) << "Infinite loop detected" << std::endl; --actions.template_depth; return; } std::string result; actions.push(); // scope the actions' states { template_symbol const* symbol = actions.templates.find(actions.template_info[0]); BOOST_ASSERT(symbol); std::vector<std::string> template_ = boost::get<0>(*symbol); boost::spirit::file_position template_pos = boost::get<1>(*symbol); std::vector<std::string> template_info; std::swap(template_info, actions.template_info); /////////////////////////////////// // Break the arguments if (!break_arguments(template_info, template_, pos)) { actions.pop(); // restore the actions' states --actions.template_depth; return; } /////////////////////////////////// // Prepare the arguments as local templates bool get_arg_result; std::vector<std::string>::const_iterator tpl; boost::tie(get_arg_result, tpl) = get_arguments(template_info, template_, pos, actions); if (!get_arg_result) { actions.pop(); // restore the actions' states --actions.template_depth; return; } /////////////////////////////////// // parse the template body: std::string body; body.assign(tpl->begin(), tpl->end()); body.reserve(body.size()+2); // reserve 2 more if (!parse_template(body, result, template_pos, actions)) { boost::spirit::file_position const pos = first.get_position(); detail::outerr(pos.file,pos.line) << "Expanding template:" << template_info[0] << std::endl << "------------------begin------------------" << std::endl << body << "------------------end--------------------" << std::endl << std::endl; actions.pop(); // restore the actions' states --actions.template_depth; return; } } actions.pop(); // restore the actions' states actions.phrase << result; // print it!!! --actions.template_depth; } void link_action::operator()(iterator first, iterator last) const { iterator save = first; phrase << tag; while (first != last) detail::print_char(*first++, phrase.get()); phrase << "\">"; // Yes, it is safe to dereference last here. When we // reach here, *last is certainly valid. We test if // *last == ']'. In which case, the url is the text. // Example: [@http://spirit.sourceforge.net/] if (*last == ']') { first = save; while (first != last) detail::print_char(*first++, phrase.get()); } } void variablelist_action::operator()(iterator, iterator) const { actions.out << "<variablelist>\n"; actions.out << "<title>"; std::string::iterator first = actions.table_title.begin(); std::string::iterator last = actions.table_title.end(); while (first != last) detail::print_char(*first++, actions.out.get()); actions.out << "</title>\n"; std::string str; actions.phrase.swap(str); actions.out << str; actions.out << "</variablelist>\n"; actions.table_span = 0; actions.table_header.clear(); actions.table_title.clear(); } void start_varlistitem_action::operator()(char) const { phrase << start_varlistitem_; phrase.push(); } void end_varlistitem_action::operator()(char) const { std::string str; temp_para.swap(str); phrase.pop(); phrase << str << end_varlistitem_; } void table_action::operator()(iterator, iterator) const { std::string::iterator first = actions.table_title.begin(); std::string::iterator last = actions.table_title.end(); bool has_title = first != last; if (has_title) { actions.out << "<table frame=\"all\">\n"; actions.out << "<title>"; while (first != last) detail::print_char(*first++, actions.out.get()); actions.out << "</title>"; } else { actions.out << "<informaltable frame=\"all\">\n"; } actions.out << "<tgroup cols=\"" << actions.table_span << "\">\n"; if (!actions.table_header.empty()) { actions.out << "<thead>" << actions.table_header << "</thead>\n"; } actions.out << "<tbody>\n"; std::string str; actions.phrase.swap(str); actions.out << str; actions.out << "</tbody>\n" << "</tgroup>\n"; if (has_title) { actions.out << "</table>\n"; } else { actions.out << "</informaltable>\n"; } actions.table_span = 0; actions.table_header.clear(); actions.table_title.clear(); } void start_row_action::operator()(char) const { // the first row is the header if (header.empty() && !phrase.str().empty()) { phrase.swap(header); } phrase << start_row_; span = 0; } void start_row_action::operator()(iterator f, iterator) const { (*this)(*f); } void start_col_action::operator()(char) const { phrase << start_cell_; phrase.push(); ++span; } void end_col_action::operator()(char) const { std::string str; temp_para.swap(str); phrase.pop(); phrase << str << end_cell_; } void begin_section_action::operator()(iterator first, iterator last) const { if (section_id.empty()) section_id = detail::make_identifier(first, last); if (section_level != 0) qualified_section_id += '.'; else BOOST_ASSERT(qualified_section_id.empty()); qualified_section_id += section_id; ++section_level; if (qbk_version_n < 103) // version 1.2 and below { out << "\n<section id=\"" << library_id << "." << section_id << "\">\n"; } else // version 1.3 and above { out << "\n<section id=\"" << library_id << "." << qualified_section_id << "\">\n"; } std::string str; phrase.swap(str); if (qbk_version_n < 103) // version 1.2 and below { out << "<title>" << str << "</title>\n"; } else // version 1.3 and above { out << "<title>" << "<link linkend=\"" << library_id << "." << qualified_section_id << "\">" << str << "</link>" << "</title>\n" ; } } void end_section_action::operator()(iterator first, iterator last) const { out << "</section>"; --section_level; if (section_level < 0) { boost::spirit::file_position const pos = first.get_position(); detail::outerr(pos.file,pos.line) << "Mismatched [endsect] near column " << pos.column << ".\n"; // $$$ TODO: somehow fail parse else BOOST_ASSERT(std::string::npos != n) // $$$ below will assert.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -