From 35cae039f40ac236048ea651268ef9d1581323eb Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 19 Mar 2011 19:13:38 +0000 Subject: [PATCH] Quickbook: support escapes in simple markup. [SVN r70204] --- src/actions.cpp | 13 ++++---- src/actions.hpp | 2 +- src/main_grammar.cpp | 53 +++++++++++++++++++++++---------- src/post_process.cpp | 42 ++++++++------------------ src/post_process.hpp | 16 ++++++---- src/quickbook.cpp | 14 ++++++++- test/simple_markup.gold | 15 ++++++++++ test/simple_markup.quickbook | 12 ++++++++ test/unit/Jamfile.v2 | 1 + test/unit/post_process_test.cpp | 30 +++++++++++++++++++ 10 files changed, 138 insertions(+), 60 deletions(-) create mode 100644 test/unit/post_process_test.cpp diff --git a/src/actions.cpp b/src/actions.cpp index 8ee3611..1e6df91 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -308,11 +308,10 @@ namespace quickbook content.get_boostbook(), anchor + "-heading", linkend); } - void simple_phrase_action::operator()(iterator first, iterator last) const + void simple_phrase_action::operator()(char mark) const { if(!actions.output_pre(out)) return; - char mark = *first; int tag = mark == '*' ? phrase_tags::bold : mark == '/' ? phrase_tags::italic : @@ -323,18 +322,18 @@ namespace quickbook assert(tag != 0); detail::markup markup = detail::markups[tag]; - std::string str( - boost::next(first.base()), - boost::prior(last.base())); + value_consumer values = actions.values.get(); + value content = values.consume(); + values.finish(); out << markup.pre; - if (std::string const* ptr = find(macro, str.c_str())) + if (std::string const* ptr = find(macro, content.get_quickbook().c_str())) { out << *ptr; } else { - detail::print_string(str, out.get()); + out << content.get_boostbook(); } out << markup.post; } diff --git a/src/actions.hpp b/src/actions.hpp index 99d7619..7f82f21 100644 --- a/src/actions.hpp +++ b/src/actions.hpp @@ -142,7 +142,7 @@ namespace quickbook , macro(macro) , actions(actions) {} - void operator()(iterator first, iterator last) const; + void operator()(char) const; collector& out; string_symbols const& macro; diff --git a/src/main_grammar.cpp b/src/main_grammar.cpp index 643ea57..168e72f 100644 --- a/src/main_grammar.cpp +++ b/src/main_grammar.cpp @@ -101,7 +101,7 @@ namespace quickbook top_level, blocks, paragraph_separator, code, code_line, blank_line, hr, list, list_item, element, - escape, + nested_char, escape, inline_code, template_, code_block, macro, @@ -122,7 +122,8 @@ namespace quickbook }; cl::rule - simple_markup, simple_markup_end; + simple_markup; + cl::rule simple_markup_end; element_info::type_enum element_type; cl::rule element_rule; @@ -381,7 +382,8 @@ namespace quickbook ; local.simple_markup = - ( cl::chset<>("*/_=") [local.simple_markup.mark = ph::arg1] + cl::chset<>("*/_=") [local.simple_markup.mark = ph::arg1] + >> cl::eps_p(cl::graph_p) // graph_p must follow first mark >> lookback [ cl::anychar_p >> ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark)) @@ -392,17 +394,24 @@ namespace quickbook // by space or punctuation or the // mark character or a the start. ] - >> cl::graph_p // graph_p must follow first mark - >> *(cl::anychar_p - local.simple_markup_end(local.simple_markup.mark)) - >> cl::f_ch_p(local.simple_markup.mark) - ) [actions.simple_markup] + >> actions.values.save() + [ + actions.scoped_output() + [ + (*( ~cl::eps_p(local.simple_markup_end) + >> local.nested_char + )) [actions.docinfo_value(ph::arg1, ph::arg2)] + ] + >> cl::f_ch_p(local.simple_markup.mark) + [actions.simple_markup] + ] ; local.simple_markup_end = ( lookback[cl::graph_p] // final mark must be preceeded by // graph_p - >> cl::f_ch_p(local.simple_markup_end.mark) - >> ~cl::eps_p(cl::f_ch_p(local.simple_markup_end.mark)) + >> cl::f_ch_p(local.simple_markup.mark) + >> ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark)) // final mark not be followed by // the same character. >> (cl::space_p | cl::punct_p | cl::end_p) @@ -452,6 +461,19 @@ namespace quickbook ] ; + local.nested_char = + cl::str_p("\\n") [actions.break_] + | "\\ " // ignore an escaped space + | '\\' >> cl::punct_p [actions.raw_char] + | "\\u" >> cl::repeat_p(4) + [cl::chset<>("0-9a-fA-F")] + [actions.escape_unicode] + | "\\U" >> cl::repeat_p(8) + [cl::chset<>("0-9a-fA-F")] + [actions.escape_unicode] + | cl::anychar_p [actions.plain_char] + ; + local.escape = cl::str_p("\\n") [actions.break_] | cl::str_p("\\ ") // ignore an escaped space @@ -540,13 +562,12 @@ namespace quickbook ; phrase_end = - ']' | - cl::if_p(var(actions.no_eols)) - [ - cl::eol_p >> *cl::blank_p >> cl::eol_p - // Make sure that we don't go - ] // past a single block, except - ; // when preformatted. + ']' + | cl::eps_p(var(actions.no_eols)) + >> cl::eol_p >> *cl::blank_p >> cl::eol_p + ; // Make sure that we don't go + // past a single block, except + // when preformatted. comment = "[/" >> *(local.dummy_block | (cl::anychar_p - ']')) >> ']' diff --git a/src/post_process.cpp b/src/post_process.cpp index d8a8dc1..3c77351 100644 --- a/src/post_process.cpp +++ b/src/post_process.cpp @@ -7,7 +7,6 @@ http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #include "post_process.hpp" -#include "input_path.hpp" #include #include #include @@ -403,6 +402,9 @@ namespace quickbook void do_end_tag(iter_type f, iter_type l) const { + if (state.tags.empty()) + throw quickbook::post_process_failure("Mismatched tags."); + bool is_flow_tag = state.is_flow_tag(state.tags.top()); if (!is_flow_tag) { @@ -419,9 +421,8 @@ namespace quickbook int indent; }; - int post_process( + std::string post_process( std::string const& in - , std::ostream& out , int indent , int linewidth) { @@ -430,36 +431,17 @@ namespace quickbook if (linewidth == -1) linewidth = 80; // set default to 80 - try + std::string tidy; + tidy_compiler state(tidy, linewidth); + tidy_grammar g(state, indent); + cl::parse_info r = parse(in.begin(), in.end(), g, cl::space_p); + if (r.full) { - std::string tidy; - tidy_compiler state(tidy, linewidth); - tidy_grammar g(state, indent); - cl::parse_info r = parse(in.begin(), in.end(), g, cl::space_p); - if (r.full) - { - out << tidy; - return 0; - } - else - { - // fallback! - ::quickbook::detail::outerr() - << "Warning: Post Processing Failed." - << std::endl; - out << in; - return 1; - } + return tidy; } - - catch(...) + else { - // fallback! - ::quickbook::detail::outerr() - << "Post Processing Failed." - << std::endl; - out << in; - return 1; + throw quickbook::post_process_failure("Post Processing Failed."); } } } diff --git a/src/post_process.hpp b/src/post_process.hpp index cfe220f..5b63ba2 100644 --- a/src/post_process.hpp +++ b/src/post_process.hpp @@ -9,16 +9,22 @@ #if !defined(BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP) #define BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP -#include #include +#include namespace quickbook { - int post_process( + std::string post_process( std::string const& in - , std::ostream& out - , int indent - , int linewidth); + , int indent = -1 + , int linewidth = -1); + + class post_process_failure : std::runtime_error + { + public: + post_process_failure(std::string const& error) + : std::runtime_error(error) {} + }; } #endif // BOOST_SPIRIT_QUICKBOOK_POST_PROCESS_HPP diff --git a/src/quickbook.cpp b/src/quickbook.cpp index cf31886..d08cb3d 100644 --- a/src/quickbook.cpp +++ b/src/quickbook.cpp @@ -150,7 +150,19 @@ namespace quickbook if (pretty_print) { - result = post_process(buffer.str(), fileout, indent, linewidth); + try + { + fileout << post_process(buffer.str(), indent, linewidth); + } + catch (quickbook::post_process_failure&) + { + // fallback! + ::quickbook::detail::outerr() + << "Post Processing Failed." + << std::endl; + fileout << buffer.str(); + return 1; + } } else { diff --git a/test/simple_markup.gold b/test/simple_markup.gold index 9cdca67..2cb0481 100644 --- a/test/simple_markup.gold +++ b/test/simple_markup.gold @@ -31,5 +31,20 @@ _Should not underline escaped markup_. _or this escaped_ markup form. + + Matti Meikäläinen + + + replaced + + + replaced + + + _macro_ + + + /not italic/ + diff --git a/test/simple_markup.quickbook b/test/simple_markup.quickbook index c275d23..9f4268f 100644 --- a/test/simple_markup.quickbook +++ b/test/simple_markup.quickbook @@ -2,6 +2,8 @@ [quickbook 1.5] ] +[def _macro_ replaced] + [section Simple Markup] /italic/ *bold* _underline_ =teletype= @@ -21,4 +23,14 @@ not_underlined_ _Should not underline '''escaped''' markup_. _or this '''escaped_ markup''' form. +=Matti Meik\u00E4l\u00E4inen= + +=_macro_= + +__macro__ + +=_mac\ ro_= + +/not italic\/ + [endsect] \ No newline at end of file diff --git a/test/unit/Jamfile.v2 b/test/unit/Jamfile.v2 index 310aebc..78a7845 100644 --- a/test/unit/Jamfile.v2 +++ b/test/unit/Jamfile.v2 @@ -5,3 +5,4 @@ project quickbook-unit-tests ; run values_test.cpp ../../src/values.cpp ; +run post_process_test.cpp ../../src/post_process.cpp ; diff --git a/test/unit/post_process_test.cpp b/test/unit/post_process_test.cpp new file mode 100644 index 0000000..737d233 --- /dev/null +++ b/test/unit/post_process_test.cpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2011 Daniel James + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +#include "post_process.hpp" +#include + +#define EXPECT_EXCEPTION(test, msg) \ + try { \ + test; \ + BOOST_ERROR(msg); \ + } \ + catch(quickbook::post_process_failure&) { \ + } + +int main() +{ + EXPECT_EXCEPTION( + quickbook::post_process(""), + "Succeeded with unbalanced tag"); + EXPECT_EXCEPTION( + quickbook::post_process("<"), + "Succeeded with badly formed tag"); + + return boost::report_errors(); +}