Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR of work on Django merged #28

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
4 changes: 4 additions & 0 deletions examples/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ project boostache_examples
<include>.
;

exe django
: django.cpp
;

exe example1
: example1.cpp
;
Expand Down
133 changes: 133 additions & 0 deletions examples/django.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* \file django.cpp
*
* A simple example of how to use boostache.
*
* Copyright 2015 Jeroen Habraken
*
* Distributed under 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)
*/
#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS

#include <boost/boostache/boostache.hpp>
#include <boost/boostache/django.hpp>
#include <boost/boostache/frontend/django/grammar_def.hpp> // need to work out header only syntax
#include <boost/boostache/model/helper.hpp>
#include <iostream>
#include <sstream>

namespace boostache = boost::boostache;

struct my_node_t;
using map_t = std::map<std::string,my_node_t>;
using list_t = std::vector<my_node_t>;
struct my_node_t : boost::spirit::extended_variant<
bool
, std::string
, map_t
, list_t
>
{
my_node_t() : base_type() {}
my_node_t(bool rhs) : base_type(rhs) {}
my_node_t(std::string const & rhs) : base_type(rhs) {}
my_node_t(char const * rhs) : base_type(std::string{rhs}) {}
my_node_t(map_t const & rhs) : base_type(rhs) {}
my_node_t(list_t const & rhs) : base_type(rhs) {}
};

int django()
{
// ------------------------------------------------------------------
// Describe the input template. We are going to use django format.
std::string input(
//"try fifdgrst.sefdshcond.another.name: {{fifdgrst.sefdshcond.another.name}}. \n"
//"try another.name: {{another.name}}.\n"
//"{%% for contact in people %%}"
//"My name is {{fifdgrst.sefdshcond.another.name}}.\n"
//"{%% endfor %%}"
//"-----------------------\n"
//"{%% for contact in people %%}"
//"{{contact.job}}\n"
////"now from a nested context: people\n"
////"try fifdgrst.sefdshcond.another.name: {{fifdgrst.sefdshcond.another.name}}. \n"
////"try another.name: {{another.name}}.\n"
//"{%% endfor %%}"
"{%% for contact in people %%}"
"{%% for more_contact in more_people %%}"
"{{more_contact.job}}\n"
//"now from a nested context: people\n"
//"try fifdgrst.sefdshcond.another.name: {{fifdgrst.sefdshcond.another.name}}. \n"
//"try another.name: {{another.name}}.\n"
"{%% endfor %%}"
"{%% endfor %%}"

// "{# This is a comment #}"
// "I am {{pet}} years old."
//"{%% for contact in people %%}"
// "a contact\n"
// "My name is still {{another.name}}. \n\n"
// "{%% endfor %%}"
// "{%% if dontshowme %%}"
// "Yep"
// "{%% else %%}"
// "Nope"
// "{%% endif %%}\n"
);
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// The data model definition
map_t data = {
{"contacts" , map_t{{"foo","gorp"}}},
{"foo" , "bar"},
{"me" , "Daniel"},
{"pet" , "turtles"},
{"lpet" , "Turtles"},
{"people" , list_t{ map_t{{"name" , "Tom"},
{"job" , "sweep floors"} },
map_t{{"name" , "Sue"},
{"job" , "write code"} }
}
},
{"title" , "Multiple Mustaches"},
{"comment" , "this shouldn't be here"},
{"showme" , true},
{"showme2" , true},
{"dontshowme" , false},
{"next_more" , "I like {{pet}}."},
{"another" , map_t{{"name" , "Sam"},
{"ok" , true },
{"not_ok" , false}}
},
{ "more_people" , list_t{ map_t{ { "name" , "Peter" },
{ "job" , "lazy" } },
map_t{ { "name" , "Barbara" },
{ "job" , "chef" } }
}
},
};
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// Load the template.
// This parses the input and compiles the result. The return is the
// compiled data structure
using boostache::load_template;

auto iter = input.begin();
auto templ = load_template<boostache::format::django>(iter, input.end());
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// Apply the compiled template and the data model to generate the result
std::stringstream stream;
boostache::generate(stream, templ, data);
// ------------------------------------------------------------------

// print the result
std::cout << stream.str();

return 0;
}
4 changes: 3 additions & 1 deletion examples/example1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace boostache = boost::boostache;
using map_t = std::map<std::string, std::string>;


int main()
int example1()
{
// ------------------------------------------------------------------
// Describe the input template. We are going to use mustache format.
Expand Down Expand Up @@ -57,4 +57,6 @@ int main()

// print the result
std::cout << stream.str();

return 0;
}
4 changes: 3 additions & 1 deletion examples/example2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ using invoice_t = std::map<std::string, item_list_t>;
// -------------------------------------------------------


int main()
int example2()
{
// ------------------------------------------------------------------
// The template describing an invoice.
Expand Down Expand Up @@ -81,4 +81,6 @@ int main()
// ------------------------------------------------------------------

std::cout << stream.str();

return 0;
}
16 changes: 14 additions & 2 deletions examples/example3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct value_t : boost::spirit::extended_variant< std::string
// -------------------------------------------------------


int main()
int example3()
{
// ------------------------------------------------------------------
// The template describing an invoice.
Expand All @@ -65,7 +65,17 @@ int main()
"\n"
"{{# company}}"
"Company: {{name}}\n"
" {{street}}\n"
"Invoice again: {{invoice_number}}\n"
"{{#invoice_number}}\n"
"has invoice\n"
"{{/invoice_number}}\n"
"{{#paied}}\n"
"has paied\n"
"{{/paied}}\n"
"{{^paied}}\n"
"has not paied\n"
"{{/paied}}\n"
" {{street}}\n"
" {{city}}, {{state}} {{zip}}\n"
"{{/ company}}"
"------------------------------------------------\n"
Expand Down Expand Up @@ -114,4 +124,6 @@ int main()
// ------------------------------------------------------------------

std::cout << stream.str();

return 0;
}
15 changes: 15 additions & 0 deletions examples/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

int example1();
int example2();
int example3();
int django();
int simple_generate2();

int main()
{
//example1();
//example2();
//example3();
django();
//simple_generate2();
}
2 changes: 1 addition & 1 deletion examples/simple_generate2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ namespace extn = bstache::extension;



int main()
int simple_generate2()
{
// ------------------------------------------------------------------
// The input template
Expand Down
144 changes: 144 additions & 0 deletions include/boost/boostache/backend/detail/django_compiler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/**
* \file detail/django_compiler.hpp
*
* Copyright 2014 Michael Caisse : ciere.com
* Copyright 2017 Tobias Loew : die-loews.de
*
* Distributed under 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)
*/
#ifndef BOOST_BOOSTACHE_BACKEND_DETAIL_DJANGO_COMPILER_HPP
#define BOOST_BOOSTACHE_BACKEND_DETAIL_DJANGO_COMPILER_HPP

#include <boost/boostache/vm/engine_ast.hpp>
#include <boost/boostache/frontend/django/ast.hpp>
#include <boost/boostache/backend/detail/django_compiler.hpp>

namespace boost { namespace boostache { namespace backend { namespace django_compiler
{
namespace fe = boost::boostache::frontend;
namespace detail
{
class django_visit
{
public:
typedef vm::ast::node result_type;

django_visit(std::ostream& out)
: out(out)
{}

vm::ast::node operator()(fe::django::ast::undefined) const
{
out << "WHOA! we have an undefined" << std::endl;
return vm::ast::node{};
}

vm::ast::node operator()(fe::django::ast::literal_text const & v) const
{
return vm::ast::literal{v};
}

vm::ast::node operator()(fe::django::ast::variable const & v) const
{
vm::ast::node body = vm::ast::render{v.back()};
for(auto iter = ++v.rbegin(); iter != v.rend(); ++iter)
{
vm::ast::select_context select;
select.tag = *iter;
select.body = std::move(body);
select.make_local = true;
body = std::move(select);
}
return body;
}

vm::ast::node operator()(fe::django::ast::comment const & v) const
{
return vm::ast::literal{};
}

vm::ast::node operator()(fe::django::ast::node_list const & nodes) const
{
vm::ast::node_list node_list;
for(auto const & node : nodes)
{
node_list.nodes.push_back(boost::apply_visitor(*this, node));
}
return node_list;
}

vm::ast::node operator()(fe::django::ast::if_elif_else const & if_elif_else) const
{
vm::ast::node_list then_;
for(auto const & node : if_elif_else.if_.body)
{
then_.nodes.push_back(boost::apply_visitor(*this, node));
}

vm::ast::if_then_else if_then_else;
if_then_else.condition_.name = if_elif_else.if_.condition_.front();
if_then_else.then_ = std::move(then_);
if(static_cast<bool>(if_elif_else.else_))
{
vm::ast::node_list else_;
for(auto const & node : if_elif_else.else_.get())
{
else_.nodes.push_back(boost::apply_visitor(*this, node));
}
if_then_else.else_ = std::move(else_);
}

return if_then_else;
}

vm::ast::node operator()(fe::django::ast::for_in const & for_in) const
{
vm::ast::node_list vm_ast;
for (auto const & node : for_in.body)
{
vm_ast.nodes.push_back(boost::apply_visitor(*this, node));
}

vm::ast::for_each for_each_;
for_each_.name = for_in.iterator;
for_each_.value = vm_ast;

vm::ast::node body = for_each_;
for (auto iter = for_in.set.begin(); iter != for_in.set.end(); ++iter)
{
vm::ast::select_context select;
select.tag = *iter;
select.body = std::move(body);
body = std::move(select);
}
return body;

//out << "WHOA! for_in not yet implemented" << std::endl;
//return vm::ast::node{};
}

vm::ast::node operator()(fe::django::ast::root const & nodes) const
{
vm::ast::node_list node_list;
for(auto const & node : nodes)
{
node_list.nodes.push_back(boost::apply_visitor(*this, node));
}
return node_list;
}

private:
std::ostream& out;
};
}

inline vm::ast::node compile(fe::django::ast::root const & ast)
{
detail::django_visit visit(std::cout);
return visit(ast);
}
}}}}

#endif

Loading