Skip to content

Commit

Permalink
Implement partials (issue cierelabs#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
Michele Santullo committed Sep 8, 2015
1 parent 04e67ee commit 9f0f0e4
Show file tree
Hide file tree
Showing 19 changed files with 188 additions and 47 deletions.
4 changes: 3 additions & 1 deletion examples/example1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
* A simple example of how to use boostache.
*
* Copyright 2015 Michael Caisse : ciere.com
* Copyright 2015 Michele Santullo
*
* 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/frontend/file_mapper.hpp>
#include <boost/boostache/frontend/stache/grammar_def.hpp> // need to work out header only syntax
#include <boost/boostache/stache.hpp>
#include <boost/boostache/model/helper.hpp>
Expand Down Expand Up @@ -45,7 +47,7 @@ int main()
using boostache::load_template;

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

// ------------------------------------------------------------------
Expand Down
12 changes: 7 additions & 5 deletions examples/example2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* A slightly more complex example.
*
* Copyright 2015 Michael Caisse : ciere.com
* Copyright 2015 Michele Santullo
*
* 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)
Expand All @@ -13,6 +14,7 @@
#include <boost/boostache/boostache.hpp>
#include <boost/boostache/frontend/stache/grammar_def.hpp> // need to work out header only syntax
#include <boost/boostache/stache.hpp>
#include <boost/boostache/frontend/file_mapper.hpp>
#include <boost/boostache/model/helper.hpp>
#include <iostream>
#include <sstream>
Expand All @@ -24,7 +26,7 @@ namespace boostache = boost::boostache;
// -------------------------------------------------------
// The data will be an invoice this time. The invoice
// consists of a list of line items. Each line item
// can be describes as map of string to strings.
// can be described as map of string to strings.
//
using item_t = std::map<std::string, std::string>;
using item_list_t = std::vector<item_t>;
Expand All @@ -36,7 +38,7 @@ int main()
{
// ------------------------------------------------------------------
// The template describing an invoice.
std::string input(
std::string input(
"Invoice"
"\n"
"{{#lines}}"
Expand All @@ -49,13 +51,13 @@ int main()
// ------------------------------------------------------------------
// The data description. invoice_items is a list of maps that
// describe each item.
item_list_t invoice_items = {
item_list_t invoice_items = {
{ {"item_code" , "1234"},
{"description" , "teddy bear"},
{"amount" , "$23"} },
{ {"item_code" , "1235"},
{"description" , "computer"},
{"amount" , "$9"} }
{"amount" , "$9"} }
};

// we need to put the list into a map so that tag 'lines' can
Expand All @@ -70,7 +72,7 @@ int main()
using boostache::load_template;

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

// ------------------------------------------------------------------
Expand Down
11 changes: 7 additions & 4 deletions examples/example3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* clean things up with a variant.
*
* Copyright 2015 Michael Caisse : ciere.com
* Copyright 2015 Michele Santullo
*
* 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)
Expand All @@ -14,6 +15,7 @@
#include <boost/boostache/boostache.hpp>
#include <boost/boostache/frontend/stache/grammar_def.hpp> // need to work out header only syntax
#include <boost/boostache/stache.hpp>
#include <boost/boostache/frontend/file_mapper.hpp>
#include <boost/boostache/model/helper.hpp>
#include <boost/spirit/include/support_extended_variant.hpp>
#include <string>
Expand Down Expand Up @@ -60,7 +62,7 @@ int main()
{
// ------------------------------------------------------------------
// The template describing an invoice.
std::string input(
std::string input(
"Invoice {{invoice_number}}"
"\n"
"{{# company}}"
Expand All @@ -79,7 +81,7 @@ int main()
// ------------------------------------------------------------------
// The data description.

object_t invoice =
object_t invoice =
{{"invoice_number", "1234"},
{"company" , object_t{{"name" , "FizSoft"},
{"street" , "42 Level St."},
Expand All @@ -93,17 +95,18 @@ int main()
{"description" , "Computer"},
{"amount" , "$9"}} }}
};

// ------------------------------------------------------------------

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

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

// ------------------------------------------------------------------
Expand Down
17 changes: 11 additions & 6 deletions include/boost/boostache/backend/detail/stache_compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* \file detail/stache_compiler.hpp
*
* Copyright 2014, 2015 Michael Caisse : ciere.com
* Copyright 2015 Michele Santullo
*
* 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)
Expand All @@ -28,7 +29,7 @@ namespace boost { namespace boostache { namespace backend { namespace stache_com
return( s.find_first_not_of(std::string{" \t\r\n"})
== std::string::npos );
}

class stache_visit
{
public:
Expand Down Expand Up @@ -103,13 +104,17 @@ namespace boost { namespace boostache { namespace backend { namespace stache_com
vm::ast::node operator()(fe::stache::ast::comment const & v) const
{
return vm::ast::nop{};
}
}

vm::ast::node operator()(fe::stache::ast::partial const & v) const
vm::ast::node operator()(fe::stache::ast::partial const & p) const
{
// TODO: need to implement partials
return vm::ast::nop{};
}
vm::ast::node_list node_list;
for (auto const & node : p.nodes)
{
node_list.nodes.push_back(boost::apply_visitor(*this, node));
}
return node_list;
}

vm::ast::node operator()(fe::stache::ast::node_list const & nodes) const
{
Expand Down
14 changes: 8 additions & 6 deletions include/boost/boostache/boostache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* \file boostache.hpp
*
* Copyright 2014 Michael Caisse : ciere.com
* Copyright 2015 Michele Santullo
*
* 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)
Expand All @@ -14,20 +15,21 @@
#include <boost/boostache/backend/stache_compiler.hpp>
#include <boost/boostache/vm/generate.hpp>
#include <istream>
#include <utility>


namespace boost { namespace boostache
{
template <typename Format, typename Iterator>
inline vm::ast::node load_template(Iterator & begin, Iterator const & end)
template <typename Format, typename Iterator, typename PartialFunctor>
inline vm::ast::node load_template(Iterator & begin, Iterator const & end, PartialFunctor mapper_type)
{
return backend::compile(frontend::parse<Format>(begin,end));
return backend::compile(frontend::parse<Format>(begin,end, std::move(mapper_type)));
}

template <typename Format>
inline vm::ast::node load_template(std::istream & input)
template <typename Format, typename PartialFunctor>
inline vm::ast::node load_template(std::istream & input, PartialFunctor mapper_type)
{
return backend::compile(frontend::parse<Format>(input));
return backend::compile(frontend::parse<Format>(input, std::move(mapper_type)));
}

template <typename Stream, typename Context>
Expand Down
67 changes: 67 additions & 0 deletions include/boost/boostache/frontend/file_mapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* \file file_mapper.hpp
*
* Copyright 2015 Michele Santullo
*
* Utility class that maps a partial name to a file on the filesystem.
*
* 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_FILE_MAPPER_HPP
#define BOOST_BOOSTACHE_FILE_MAPPER_HPP

#include <string>
#include <utility>
#include <fstream>

namespace boost { namespace boostache { namespace frontend
{
template <typename CharType>
class file_mapper
{
public:
using string_type = std::basic_string<CharType>;

file_mapper (file_mapper&&) = default;
file_mapper (const file_mapper&) = default;
explicit file_mapper (string_type&& ext=".mustache", string_type&& base_path="") :
extension(std::move(ext)),
base_path(std::move(base_path))
{
}

void set_extension (string_type&& ext)
{
extension = std::move(ext);
}
void set_base_path (string_type&& bpath)
{
base_path = std::move(bpath);
if (!base_path.empty() && base_path.back() != static_cast<CharType>('/') && base_path.back() != static_cast<CharType>('\\'))
base_path += '/';
}

string_type operator() (const string_type& tag) const
{
//TODO: don't open the file every time, add some sort of buffering instead
string_type path(base_path + tag + extension);
std::basic_ifstream<CharType> ifs(path);
ifs.seekg(0, std::ios_base::end);
const auto ssize = ifs.tellg();
ifs.seekg(0, std::ios_base::beg);

string_type retval;
retval.resize(ssize, ' ');
ifs.read(&*retval.begin(), ssize);
ifs.close();
return retval;
}

private:
string_type extension;
string_type base_path;
};
}}}
#endif
17 changes: 10 additions & 7 deletions include/boost/boostache/frontend/parse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* \file parse.hpp
*
* Copyright 2014 Michael Caisse : ciere.com
* Copyright 2015 Michele Santullo
*
* Generic parser entry point. Call parse with the input format
* as the template parameter:
Expand All @@ -17,15 +18,16 @@
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <iostream>
#include <utility>

namespace boost { namespace boostache { namespace frontend
{
template <typename Format, typename Iterator>
typename Format::ast_t parse(Iterator & begin, Iterator const & end)
template <typename Format, typename Iterator, typename PartialFunctor>
typename Format::ast_t parse(Iterator & begin, Iterator const & end, PartialFunctor mapper_type)
{
typename Format::ast_t ast;
typename Format::template grammar_t<Iterator> grammar;
typename Format::template grammar_t<Iterator, PartialFunctor> grammar(std::move(mapper_type));

// TODO mjc : should throw with parse error location
if(!boost::spirit::qi::phrase_parse( begin, end
, grammar
Expand All @@ -38,14 +40,15 @@ namespace boost { namespace boostache { namespace frontend
}


template <typename Format>
typename Format::ast_t parse(std::istream& input)
template <typename Format, typename PartialFunctor>
typename Format::ast_t parse(std::istream& input, PartialFunctor mapper_type)
{
// TODO mjc : store/restore ios state?
input.unsetf(std::ios::skipws);
boost::spirit::istream_iterator iter{input};
return parse<Format>( iter
, boost::spirit::istream_iterator{} );
, boost::spirit::istream_iterator{}
, std::move(mapper_type) );
}
}}}

Expand Down
13 changes: 9 additions & 4 deletions include/boost/boostache/frontend/stache/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*
* Copyright 2014 Michael Caisse : ciere.com
* Copyright 2014 Jeroen Habraken
* Copyright 2015 Michele Santullo
*
* 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)
Expand Down Expand Up @@ -34,9 +35,7 @@ namespace boost { namespace boostache { namespace frontend { namespace stache {
identifier value;
};

struct partial : identifier
{};

struct partial;
struct section;

struct node : boost::spirit::extended_variant<
Expand All @@ -45,7 +44,7 @@ namespace boost { namespace boostache { namespace frontend { namespace stache {
, literal_text
, variable
, boost::recursive_wrapper<section>
, partial
, boost::recursive_wrapper<partial>
>
{
node() : base_type() {}
Expand All @@ -65,6 +64,12 @@ namespace boost { namespace boostache { namespace frontend { namespace stache {
node_list nodes;
};

struct partial
{
identifier name;
node_list nodes;
};

struct root : node_list {};

}}}}}
Expand Down
Loading

0 comments on commit 9f0f0e4

Please sign in to comment.