filter lambda support

This commit is contained in:
Daniel Sipka 2015-04-22 11:39:07 +02:00
parent bfa6d161bb
commit 0ddf2cd121
10 changed files with 66 additions and 44 deletions

View file

@ -32,8 +32,21 @@ namespace mstch {
}; };
} }
using renderer = std::function<std::string(const std::string&)>;
class lambda {
public:
lambda(std::function<std::string(const std::string&,renderer)> fun): fun(fun) {
}
std::string operator()(const std::string& text, renderer renderer) const {
return fun(text, renderer);
}
private:
std::function<std::string(const std::string&,renderer)> fun;
};
using node = boost::make_recursive_variant< using node = boost::make_recursive_variant<
boost::blank, std::string, int, bool, boost::blank, std::string, int, bool, lambda,
std::shared_ptr<internal::object_t<boost::recursive_variant_>>, std::shared_ptr<internal::object_t<boost::recursive_variant_>>,
std::map<const std::string,boost::recursive_variant_>, std::map<const std::string,boost::recursive_variant_>,
std::vector<boost::recursive_variant_>>::type; std::vector<boost::recursive_variant_>>::type;

View file

@ -1,4 +1,4 @@
find_package(Boost 1.54 REQUIRED) find_package(Boost 1.46 REQUIRED)
include_directories( include_directories(
${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include

View file

@ -12,7 +12,7 @@ state::in_section::in_section(type type, const std::string& section_name):
std::string state::in_section::render(render_context& ctx, const token& token) { std::string state::in_section::render(render_context& ctx, const token& token) {
if(token.token_type() == token::type::section_close) { if(token.token_type() == token::type::section_close) {
if(token.content() == section_name && skipped_openings == 0) { if(token.name() == section_name && skipped_openings == 0) {
auto& node = ctx.get_node(section_name); auto& node = ctx.get_node(section_name);
std::string out; std::string out;
if(m_type == type::normal) { if(m_type == type::normal) {

View file

@ -10,23 +10,23 @@ std::string state::outside_section::render(
{ {
switch(token.token_type()) { switch(token.token_type()) {
case token::type::section_open: case token::type::section_open:
ctx.set_state<in_section>(in_section::type::normal, token.content()); ctx.set_state<in_section>(in_section::type::normal, token.name());
break; break;
case token::type::inverted_section_open: case token::type::inverted_section_open:
ctx.set_state<in_section>(in_section::type::inverted, token.content()); ctx.set_state<in_section>(in_section::type::inverted, token.name());
break; break;
case token::type::variable: case token::type::variable:
return boost::apply_visitor( return boost::apply_visitor(
visitor::render_node(visitor::render_node::flag::escape_html), visitor::render_node(visitor::render_node::flag::escape_html),
ctx.get_node(token.content())); ctx.get_node(token.name()));
case token::type::unescaped_variable: case token::type::unescaped_variable:
return boost::apply_visitor( return boost::apply_visitor(
visitor::render_node(visitor::render_node::flag::none), visitor::render_node(visitor::render_node::flag::none),
ctx.get_node(token.content())); ctx.get_node(token.name()));
case token::type::text: case token::type::text:
return token.content(); return token.raw();
case token::type::partial: case token::type::partial:
return ctx.render_partial(token.content()); return ctx.render_partial(token.name());
default: break; default: break;
} }
return ""; return "";

View file

@ -13,7 +13,6 @@ void template_type::tokenize(const std::string& t) {
std::string::const_iterator tok_end, tok_start = t.begin(); std::string::const_iterator tok_end, tok_start = t.begin();
parse_state pstate = parse_state::start; parse_state pstate = parse_state::start;
unsigned int del_pos = 0; unsigned int del_pos = 0;
bool ws_only = true;
for (std::string::const_iterator it = t.begin(); it != t.end(); ++it) { for (std::string::const_iterator it = t.begin(); it != t.end(); ++it) {
if (pstate == parse_state::start) { if (pstate == parse_state::start) {
if (*it == delim_start[0]) { if (*it == delim_start[0]) {
@ -21,11 +20,8 @@ void template_type::tokenize(const std::string& t) {
tok_end = it; tok_end = it;
del_pos = 1; del_pos = 1;
} else if(*it == '\n') { } else if(*it == '\n') {
tokens.push_back({false, true, ws_only, {tok_start, it + 1}}); tokens.push_back({{tok_start, it + 1}});
ws_only = true;
tok_start = it + 1; tok_start = it + 1;
} else if (*it != ' ' && *it != '\t') {
ws_only = false;
} }
} else if(pstate == parse_state::in_del_start) { } else if(pstate == parse_state::in_del_start) {
if (*it == delim_start[del_pos] && ++del_pos == delim_start.size()) if (*it == delim_start[del_pos] && ++del_pos == delim_start.size())
@ -47,17 +43,15 @@ void template_type::tokenize(const std::string& t) {
} else if(pstate == parse_state::in_del_end) { } else if(pstate == parse_state::in_del_end) {
if (*it == delim_end[del_pos] && ++del_pos == delim_end.size()) { if (*it == delim_end[del_pos] && ++del_pos == delim_end.size()) {
pstate = parse_state::start; pstate = parse_state::start;
tokens.push_back({false, false, ws_only, {tok_start, tok_end}}); tokens.push_back({{tok_start, tok_end}});
tokens.push_back({true, false, false, tokens.push_back({{tok_end, it + 1}, delim_start.size(), delim_end.size()});
{tok_end+delim_start.size(), it-delim_end.size()+1}});
ws_only = true;
tok_start = it + 1; tok_start = it + 1;
} else { } else {
pstate = parse_state::start; pstate = parse_state::start;
} }
} }
} }
tokens.push_back({false, false, ws_only, {tok_start, t.end()}}); tokens.push_back({{tok_start, t.end()}});
} }
void template_type::strip_whitespace() { void template_type::strip_whitespace() {
@ -71,13 +65,17 @@ void template_type::strip_whitespace() {
else if (!(*it).ws_only()) else if (!(*it).ws_only())
non_space = true; non_space = true;
if ((*it).eol()) { if ((*it).eol()) {
if (has_tag && !non_space) if (has_tag && !non_space) {
for (auto line_it = line_begin; line_it != it + 1; ++line_it) auto line_it = line_begin;
if ((*line_it).ws_only()) (*line_it).mark(); for (; !(*line_it).eol(); ++line_it)
if ((*line_it).ws_only())
line_it = tokens.erase(line_it);
if ((*line_it).ws_only())
line_it = tokens.erase(line_it);
it = line_it - 1;
}
non_space = has_tag = false; non_space = has_tag = false;
line_begin = it + 1; line_begin = it + 1;
} }
} }
for (auto it = tokens.begin(); it != tokens.end();)
((*it).marked())?(it = tokens.erase(it)):(++it);
} }

View file

@ -15,23 +15,24 @@ token::type token::token_info(char c) {
} }
} }
token::token(bool is_tag, bool eol, bool ws_only, const std::string& str): token::token(const std::string& str, std::size_t skip_left, std::size_t skip_right):
m_eol(eol), m_ws_only(ws_only), m_marked(false) m_eol(false), m_ws_only(false), m_raw(str)
{ {
if(is_tag) { if(skip_left != 0 && skip_right != 0) {
if(str[0] == '{' && str[str.size() - 1] == '}') { if(str[skip_left] == '{' && str[str.size() - skip_right - 1] == '}') {
m_type = type::unescaped_variable; m_type = type::unescaped_variable;
m_content = {first_not_ws(str.begin() + 1, str.end()), m_name = {first_not_ws(str.begin() + skip_left + 1, str.end() - skip_right),
first_not_ws(str.rbegin() + 1, str.rend()) + 1}; first_not_ws(str.rbegin() + 1 + skip_right, str.rend() - skip_left) + 1};
} else { } else {
auto first = first_not_ws(str.begin(), str.end()); auto first = first_not_ws(str.begin() + skip_left, str.end() - skip_right);
m_type = token_info(*first); m_type = token_info(*first);
if(m_type != type::variable) if(m_type != type::variable)
first = first_not_ws(first + 1, str.end()); first = first_not_ws(first + 1, str.end() - skip_right);
m_content = {first, first_not_ws(str.rbegin(), str.rend()) + 1}; m_name = {first, first_not_ws(str.rbegin() + skip_right, str.rend() - skip_left) + 1};
} }
} else { } else {
m_type = type::text; m_type = type::text;
m_content = str; m_eol = (str.size() > 0 && str[str.size() - 1] == '\n');
m_ws_only = (str.find_first_not_of(" \n\t") == std::string::npos);
} }
} }

View file

@ -9,19 +9,18 @@ namespace mstch {
text, variable, section_open, section_close, inverted_section_open, text, variable, section_open, section_close, inverted_section_open,
unescaped_variable, comment, partial unescaped_variable, comment, partial
}; };
token(bool is_tag, bool eol, bool ws_only, const std::string& str); token(const std::string& str, std::size_t skip_left = 0, std::size_t skip_right = 0);
type token_type() const { return m_type; }; type token_type() const { return m_type; };
const std::string& content() const { return m_content; }; const std::string& raw() const { return m_raw; };
const std::string& name() const { return m_name; };
bool eol() const { return m_eol; } bool eol() const { return m_eol; }
bool ws_only() const { return m_ws_only; } bool ws_only() const { return m_ws_only; }
bool marked() const { return m_marked; }
void mark() { m_marked = true; };
private: private:
type m_type; type m_type;
std::string m_content; std::string m_name;
std::string m_raw;
bool m_eol; bool m_eol;
bool m_ws_only; bool m_ws_only;
bool m_marked;
type token_info(char c); type token_info(char c);
}; };
} }

View file

@ -28,6 +28,18 @@ namespace mstch {
flag m_flag; flag m_flag;
}; };
template<> inline
std::string render_section::operator()<lambda>(const lambda& lam) const {
std::string section_str;
for(auto& token: section)
section_str += token.raw();
return lam(section_str, [this](const std::string& str) {
std::cout << str << std::endl;
std::cout << ctx.render(template_type{str}) << std::endl;
return ctx.render(template_type{str});
});
}
template<> inline template<> inline
std::string render_section::operator()<array>(const array& arr) const { std::string render_section::operator()<array>(const array& arr) const {
std::string out; std::string out;

View file

@ -1,4 +1,4 @@
find_package(Boost 1.54 COMPONENTS program_options REQUIRED) find_package(Boost 1.46 COMPONENTS program_options REQUIRED)
include_directories( include_directories(
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}

View file

@ -8,10 +8,9 @@ public:
} }
mstch::node bold() { mstch::node bold() {
return std::string{""}; return mstch::lambda{[](const std::string& text, mstch::renderer render) {
/*return [](const std::string& text, mstch::renderer render) {
return std::string{"<b>"} + render(text) + std::string{"</b>"}; return std::string{"<b>"} + render(text) + std::string{"</b>"};
};*/ }};
}; };
mstch::node person() { mstch::node person() {