summaryrefslogtreecommitdiff
path: root/tools/quickbook/src/syntax_highlight.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/quickbook/src/syntax_highlight.cpp')
-rw-r--r--tools/quickbook/src/syntax_highlight.cpp400
1 files changed, 238 insertions, 162 deletions
diff --git a/tools/quickbook/src/syntax_highlight.cpp b/tools/quickbook/src/syntax_highlight.cpp
index 2e790f5bb1..e618c07dd6 100644
--- a/tools/quickbook/src/syntax_highlight.cpp
+++ b/tools/quickbook/src/syntax_highlight.cpp
@@ -14,7 +14,9 @@
#include <boost/spirit/include/classic_loops.hpp>
#include "grammar.hpp"
#include "grammar_impl.hpp" // Just for context stuff. Should move?
-#include "actions_class.hpp"
+#include "state.hpp"
+#include "actions.hpp"
+#include "utils.hpp"
#include "files.hpp"
#include "input_path.hpp"
@@ -22,102 +24,100 @@ namespace quickbook
{
namespace cl = boost::spirit::classic;
- // quickbook::actions is used in a few places here, as 'escape_actions'.
- // It's named differently to distinguish it from the syntax highlighting
- // actions, declared below.
-
- // Syntax Highlight Actions
-
- struct span
+ template <typename T, typename Value>
+ struct member_action_value
{
- // Decorates c++ code fragments
+ typedef void(T::*member_function)(Value);
- span(char const* name, collector& out)
- : name(name), out(out) {}
+ T& l;
+ member_function mf;
- void operator()(parse_iterator first, parse_iterator last) const;
+ member_action_value(T& l, member_function mf) : l(l), mf(mf) {}
- char const* name;
- collector& out;
+ void operator()(Value v) const {
+ (l.*mf)(v);
+ }
};
- struct span_start
+ template <typename T>
+ struct member_action
{
- span_start(char const* name, collector& out)
- : name(name), out(out) {}
+ typedef void(T::*member_function)(parse_iterator, parse_iterator);
- void operator()(parse_iterator first, parse_iterator last) const;
+ T& l;
+ member_function mf;
- char const* name;
- collector& out;
- };
+ member_action(T& l, member_function mf) : l(l), mf(mf) {}
- struct span_end
- {
- span_end(collector& out)
- : out(out) {}
-
- void operator()(parse_iterator first, parse_iterator last) const;
-
- collector& out;
+ void operator()(parse_iterator first, parse_iterator last) const {
+ (l.*mf)(first, last);
+ }
};
- struct unexpected_char
+ template <typename T, typename Arg1>
+ struct member_action1
{
- // Handles unexpected chars in c++ syntax
+ typedef void(T::*member_function)(parse_iterator, parse_iterator, Arg1);
- unexpected_char(
- collector& out
- , quickbook::actions& escape_actions)
- : out(out)
- , escape_actions(escape_actions) {}
+ T& l;
+ member_function mf;
- void operator()(parse_iterator first, parse_iterator last) const;
-
- collector& out;
- quickbook::actions& escape_actions;
- };
+ member_action1(T& l, member_function mf) : l(l), mf(mf) {}
- struct plain_char
- {
- // Prints a single plain char.
- // Converts '<' to "&lt;"... etc See utils.hpp
+ struct impl
+ {
+ member_action1 a;
+ Arg1 value;
- plain_char(collector& out)
- : out(out) {}
+ impl(member_action1& a, Arg1 value) :
+ a(a), value(value)
+ {}
- void operator()(char ch) const;
- void operator()(parse_iterator first, parse_iterator last) const;
+ void operator()(parse_iterator first, parse_iterator last) const {
+ (a.l.*a.mf)(first, last, value);
+ }
+ };
- collector& out;
+ impl operator()(Arg1 a1) {
+ return impl(*this, a1);
+ }
};
- struct pre_escape_back
- {
- // Escapes back from code to quickbook (Pre)
-
- pre_escape_back(actions& escape_actions)
- : escape_actions(escape_actions) {}
-
- void operator()(parse_iterator first, parse_iterator last) const;
-
- actions& escape_actions;
- };
+ // Syntax Highlight Actions
- struct post_escape_back
+ struct syntax_highlight_actions
{
- // Escapes back from code to quickbook (Post)
-
- post_escape_back(collector& out, actions& escape_actions)
- : out(out), escape_actions(escape_actions) {}
-
- void operator()(parse_iterator first, parse_iterator last) const;
-
- collector& out;
- actions& escape_actions;
+ quickbook::collector out;
+ quickbook::state& state;
+ do_macro_action do_macro_impl;
+
+ // State
+ bool support_callouts;
+ string_ref marked_text;
+
+ syntax_highlight_actions(quickbook::state& state, bool is_block) :
+ out(), state(state),
+ do_macro_impl(out, state),
+ support_callouts(is_block && (qbk_version_n >= 107u ||
+ state.current_file->is_code_snippets)),
+ marked_text()
+ {}
+
+ void span(parse_iterator, parse_iterator, char const*);
+ void span_start(parse_iterator, parse_iterator, char const*);
+ void span_end(parse_iterator, parse_iterator);
+ void unexpected_char(parse_iterator, parse_iterator);
+ void plain_char(parse_iterator, parse_iterator);
+ void pre_escape_back(parse_iterator, parse_iterator);
+ void post_escape_back(parse_iterator, parse_iterator);
+ void do_macro(std::string const&);
+
+ void mark_text(parse_iterator, parse_iterator);
+ void callout(parse_iterator, parse_iterator);
};
- void span::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::span(parse_iterator first,
+ parse_iterator last, char const* name)
{
out << "<phrase role=\"" << name << "\">";
while (first != last)
@@ -125,27 +125,30 @@ namespace quickbook
out << "</phrase>";
}
- void span_start::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::span_start(parse_iterator first,
+ parse_iterator last, char const* name)
{
out << "<phrase role=\"" << name << "\">";
while (first != last)
detail::print_char(*first++, out.get());
}
- void span_end::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::span_end(parse_iterator first,
+ parse_iterator last)
{
while (first != last)
detail::print_char(*first++, out.get());
out << "</phrase>";
}
- void unexpected_char::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::unexpected_char(parse_iterator first,
+ parse_iterator last)
{
- file_position const pos = escape_actions.current_file->position_of(first.base());
+ file_position const pos = state.current_file->position_of(first.base());
- detail::outwarn(escape_actions.current_file->path, pos.line)
+ detail::outwarn(state.current_file->path, pos.line)
<< "in column:" << pos.column
- << ", unexpected character: " << detail::utf8(first, last)
+ << ", unexpected character: " << std::string(first.base(), last.base())
<< "\n";
// print out an unexpected character
@@ -155,26 +158,42 @@ namespace quickbook
out << "</phrase>";
}
- void plain_char::operator()(char ch) const
+ void syntax_highlight_actions::plain_char(parse_iterator first,
+ parse_iterator last)
{
- detail::print_char(ch, out.get());
+ while (first != last)
+ detail::print_char(*first++, out.get());
}
- void plain_char::operator()(parse_iterator first, parse_iterator last) const
+ void syntax_highlight_actions::pre_escape_back(parse_iterator,
+ parse_iterator)
{
- while (first != last)
- detail::print_char(*first++, out.get());
+ state.phrase.push(); // save the stream
+ }
+
+ void syntax_highlight_actions::post_escape_back(parse_iterator,
+ parse_iterator)
+ {
+ out << state.phrase.str();
+ state.phrase.pop(); // restore the stream
+ }
+
+ void syntax_highlight_actions::do_macro(std::string const& v)
+ {
+ do_macro_impl(v);
}
- void pre_escape_back::operator()(parse_iterator, parse_iterator) const
+ void syntax_highlight_actions::mark_text(parse_iterator first,
+ parse_iterator last)
{
- escape_actions.phrase.push(); // save the stream
+ marked_text = string_ref(first.base(), last.base());
}
- void post_escape_back::operator()(parse_iterator, parse_iterator) const
+ void syntax_highlight_actions::callout(parse_iterator, parse_iterator)
{
- out << escape_actions.phrase.str();
- escape_actions.phrase.pop(); // restore the stream
+ out << state.add_callout(qbk_value(state.current_file,
+ marked_text.begin(), marked_text.end()));
+ marked_text.clear();
}
// Syntax
@@ -225,45 +244,63 @@ namespace quickbook
}
// Grammar for C++ highlighting
- struct cpp_highlight
- : public cl::grammar<cpp_highlight>
+ struct cpp_highlight : public cl::grammar<cpp_highlight>
{
- cpp_highlight(collector& out, actions& escape_actions)
- : out(out), escape_actions(escape_actions) {}
+ cpp_highlight(syntax_highlight_actions& actions)
+ : actions(actions) {}
template <typename Scanner>
struct definition
{
definition(cpp_highlight const& self)
- : g(self.escape_actions.grammar())
+ : g(self.actions.state.grammar())
{
+ member_action1<syntax_highlight_actions, char const*>
+ span(self.actions, &syntax_highlight_actions::span),
+ span_start(self.actions, &syntax_highlight_actions::span_start);
+ member_action<syntax_highlight_actions>
+ span_end(self.actions, &syntax_highlight_actions::span_end),
+ unexpected_char(self.actions, &syntax_highlight_actions::unexpected_char),
+ plain_char(self.actions, &syntax_highlight_actions::plain_char),
+ pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
+ post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back),
+ mark_text(self.actions, &syntax_highlight_actions::mark_text),
+ callout(self.actions, &syntax_highlight_actions::callout);
+ member_action_value<syntax_highlight_actions, std::string const&>
+ do_macro(self.actions, &syntax_highlight_actions::do_macro);
+ error_action error(self.actions.state);
+
program
=
- *( (+cl::space_p) [plain_char(self.out)]
+ *( (+cl::space_p) [plain_char]
| macro
| escape
- | preprocessor [span("preprocessor", self.out)]
+ | preprocessor [span("preprocessor")]
+ | cl::eps_p(ph::var(self.actions.support_callouts))
+ >> ( line_callout [callout]
+ | inline_callout [callout]
+ )
| comment
- | keyword [span("keyword", self.out)]
- | identifier [span("identifier", self.out)]
- | special [span("special", self.out)]
- | string_ [span("string", self.out)]
- | char_ [span("char", self.out)]
- | number [span("number", self.out)]
- | cl::repeat_p(1)[cl::anychar_p]
- [unexpected_char(self.out, self.escape_actions)]
+ | keyword [span("keyword")]
+ | identifier [span("identifier")]
+ | special [span("special")]
+ | string_ [span("string")]
+ | char_ [span("char")]
+ | number [span("number")]
+ | u8_codepoint_p [unexpected_char]
)
;
macro =
// must not be followed by alpha or underscore
- cl::eps_p(self.escape_actions.macro
+ cl::eps_p(self.actions.state.macro
>> (cl::eps_p - (cl::alpha_p | '_')))
- >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ >> self.actions.state.macro
+ [do_macro]
;
escape =
- cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ cl::str_p("``") [pre_escape_back]
>>
(
(
@@ -275,29 +312,46 @@ namespace quickbook
)
|
(
- cl::eps_p [self.escape_actions.error]
+ cl::eps_p [error]
>> *cl::anychar_p
)
- ) [post_escape_back(self.out, self.escape_actions)]
+ ) [post_escape_back]
;
preprocessor
= '#' >> *cl::space_p >> ((cl::alpha_p | '_') >> *(cl::alnum_p | '_'))
;
+ inline_callout
+ = cl::confix_p(
+ "/*<" >> *cl::space_p,
+ (*cl::anychar_p) [mark_text],
+ ">*/"
+ )
+ ;
+
+ line_callout
+ = cl::confix_p(
+ "/*<<" >> *cl::space_p,
+ (*cl::anychar_p) [mark_text],
+ ">>*/"
+ )
+ >> *cl::space_p
+ ;
+
comment
- = cl::str_p("//") [span_start("comment", self.out)]
+ = cl::str_p("//") [span_start("comment")]
>> *( escape
| (+(cl::anychar_p - (cl::eol_p | "``")))
- [plain_char(self.out)]
+ [plain_char]
)
- >> cl::eps_p [span_end(self.out)]
- | cl::str_p("/*") [span_start("comment", self.out)]
+ >> cl::eps_p [span_end]
+ | cl::str_p("/*") [span_start("comment")]
>> *( escape
| (+(cl::anychar_p - (cl::str_p("*/") | "``")))
- [plain_char(self.out)]
+ [plain_char]
)
- >> (!cl::str_p("*/")) [span_end(self.out)]
+ >> (!cl::str_p("*/")) [span_end]
;
keyword
@@ -308,7 +362,7 @@ namespace quickbook
= +cl::chset_p("~!%^&*()+={[}]:;,<.>?/|\\-")
;
- string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\');
+ string_char = ('\\' >> u8_codepoint_p) | (cl::anychar_p - '\\');
string_
= !cl::as_lower_d['l'] >> cl::confix_p('"', *string_char, '"')
@@ -333,7 +387,9 @@ namespace quickbook
}
cl::rule<Scanner>
- program, macro, preprocessor, comment, special, string_,
+ program, macro, preprocessor,
+ inline_callout, line_callout, comment,
+ special, string_,
char_, number, identifier, keyword, escape,
string_char;
@@ -343,50 +399,63 @@ namespace quickbook
start() const { return program; }
};
- collector& out;
- actions& escape_actions;
+ syntax_highlight_actions& actions;
};
// Grammar for Python highlighting
// See also: The Python Reference Manual
// http://docs.python.org/ref/ref.html
- struct python_highlight
- : public cl::grammar<python_highlight>
+ struct python_highlight : public cl::grammar<python_highlight>
{
- python_highlight(collector& out, actions& escape_actions)
- : out(out), escape_actions(escape_actions) {}
+ python_highlight(syntax_highlight_actions& actions)
+ : actions(actions) {}
template <typename Scanner>
struct definition
{
definition(python_highlight const& self)
- : g(self.escape_actions.grammar())
+ : g(self.actions.state.grammar())
{
+ member_action1<syntax_highlight_actions, char const*>
+ span(self.actions, &syntax_highlight_actions::span),
+ span_start(self.actions, &syntax_highlight_actions::span_start);
+ member_action<syntax_highlight_actions>
+ span_end(self.actions, &syntax_highlight_actions::span_end),
+ unexpected_char(self.actions, &syntax_highlight_actions::unexpected_char),
+ plain_char(self.actions, &syntax_highlight_actions::plain_char),
+ pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
+ post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back),
+ mark_text(self.actions, &syntax_highlight_actions::mark_text),
+ callout(self.actions, &syntax_highlight_actions::callout);
+ member_action_value<syntax_highlight_actions, std::string const&>
+ do_macro(self.actions, &syntax_highlight_actions::do_macro);
+ error_action error(self.actions.state);
+
program
=
- *( (+cl::space_p) [plain_char(self.out)]
+ *( (+cl::space_p) [plain_char]
| macro
| escape
| comment
- | keyword [span("keyword", self.out)]
- | identifier [span("identifier", self.out)]
- | special [span("special", self.out)]
- | string_ [span("string", self.out)]
- | number [span("number", self.out)]
- | cl::repeat_p(1)[cl::anychar_p]
- [unexpected_char(self.out, self.escape_actions)]
+ | keyword [span("keyword")]
+ | identifier [span("identifier")]
+ | special [span("special")]
+ | string_ [span("string")]
+ | number [span("number")]
+ | u8_codepoint_p [unexpected_char]
)
;
macro =
// must not be followed by alpha or underscore
- cl::eps_p(self.escape_actions.macro
+ cl::eps_p(self.actions.state.macro
>> (cl::eps_p - (cl::alpha_p | '_')))
- >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ >> self.actions.state.macro
+ [do_macro]
;
escape =
- cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ cl::str_p("``") [pre_escape_back]
>>
(
(
@@ -398,19 +467,19 @@ namespace quickbook
)
|
(
- cl::eps_p [self.escape_actions.error]
+ cl::eps_p [error]
>> *cl::anychar_p
)
- ) [post_escape_back(self.out, self.escape_actions)]
+ ) [post_escape_back]
;
comment
- = cl::str_p("#") [span_start("comment", self.out)]
+ = cl::str_p("#") [span_start("comment")]
>> *( escape
| (+(cl::anychar_p - (cl::eol_p | "``")))
- [plain_char(self.out)]
+ [plain_char]
)
- >> cl::eps_p [span_end(self.out)]
+ >> cl::eps_p [span_end]
;
keyword
@@ -429,7 +498,7 @@ namespace quickbook
= ! string_prefix >> (long_string | short_string)
;
- string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\');
+ string_char = ('\\' >> u8_codepoint_p) | (cl::anychar_p - '\\');
short_string
= cl::confix_p('\'', * string_char, '\'') |
@@ -468,40 +537,47 @@ namespace quickbook
start() const { return program; }
};
- collector& out;
- actions& escape_actions;
+ syntax_highlight_actions& actions;
};
// Grammar for plain text (no actual highlighting)
- struct teletype_highlight
- : public cl::grammar<teletype_highlight>
+ struct teletype_highlight : public cl::grammar<teletype_highlight>
{
- teletype_highlight(collector& out, actions& escape_actions)
- : out(out), escape_actions(escape_actions) {}
+ teletype_highlight(syntax_highlight_actions& actions)
+ : actions(actions) {}
template <typename Scanner>
struct definition
{
definition(teletype_highlight const& self)
- : g(self.escape_actions.grammar())
+ : g(self.actions.state.grammar())
{
+ member_action<syntax_highlight_actions>
+ plain_char(self.actions, &syntax_highlight_actions::plain_char),
+ pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
+ post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back);
+ member_action_value<syntax_highlight_actions, std::string const&>
+ do_macro(self.actions, &syntax_highlight_actions::do_macro);
+ error_action error(self.actions.state);
+
program
=
*( macro
| escape
- | cl::repeat_p(1)[cl::anychar_p] [plain_char(self.out)]
+ | u8_codepoint_p [plain_char]
)
;
macro =
// must not be followed by alpha or underscore
- cl::eps_p(self.escape_actions.macro
+ cl::eps_p(self.actions.state.macro
>> (cl::eps_p - (cl::alpha_p | '_')))
- >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)]
+ >> self.actions.state.macro
+ [do_macro]
;
escape =
- cl::str_p("``") [pre_escape_back(self.escape_actions)]
+ cl::str_p("``") [pre_escape_back]
>>
(
(
@@ -513,10 +589,10 @@ namespace quickbook
)
|
(
- cl::eps_p [self.escape_actions.error]
+ cl::eps_p [error]
>> *cl::anychar_p
)
- ) [post_escape_back(self.out, self.escape_actions)]
+ ) [post_escape_back]
;
}
@@ -528,32 +604,32 @@ namespace quickbook
start() const { return program; }
};
- collector& out;
- actions& escape_actions;
+ syntax_highlight_actions& actions;
};
std::string syntax_highlight(
parse_iterator first,
parse_iterator last,
- actions& escape_actions,
- std::string const& source_mode)
+ quickbook::state& state,
+ std::string const& source_mode,
+ bool is_block)
{
- quickbook::collector temp;
+ syntax_highlight_actions syn_actions(state, is_block);
// print the code with syntax coloring
if (source_mode == "c++")
{
- cpp_highlight cpp_p(temp, escape_actions);
+ cpp_highlight cpp_p(syn_actions);
boost::spirit::classic::parse(first, last, cpp_p);
}
else if (source_mode == "python")
{
- python_highlight python_p(temp, escape_actions);
+ python_highlight python_p(syn_actions);
boost::spirit::classic::parse(first, last, python_p);
}
else if (source_mode == "teletype")
{
- teletype_highlight teletype_p(temp, escape_actions);
+ teletype_highlight teletype_p(syn_actions);
boost::spirit::classic::parse(first, last, teletype_p);
}
else
@@ -562,7 +638,7 @@ namespace quickbook
}
std::string str;
- temp.swap(str);
+ syn_actions.out.swap(str);
return str;
}