| // Copyright (c) 2001-2010 Hartmut Kaiser |
| // |
| // 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) |
| |
| #if !defined(BOOST_SPIRIT_QIEXPR_GENERATOR) |
| #define BOOST_SPIRIT_QIEXPR_GENERATOR |
| |
| #include <string> |
| |
| #include <boost/cstdint.hpp> |
| #include <boost/spirit/include/karma.hpp> |
| #include <boost/spirit/include/phoenix.hpp> |
| |
| #include <utree/utree.hpp> |
| #include <utree/operators.hpp> |
| #include <output/utree_traits.hpp> |
| #include <qi/component_names.hpp> |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { namespace spirit { namespace traits |
| { |
| template <typename Out> |
| void print_attribute(Out& out, scheme::utree const& val); |
| }}} |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace scheme { namespace qi |
| { |
| using boost::spirit::karma::grammar; |
| using boost::spirit::karma::rule; |
| using boost::spirit::karma::space_type; |
| using boost::spirit::karma::symbols; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| namespace traits |
| { |
| template <typename Count> |
| struct deref_spec |
| : boost::spirit::result_of::terminal<boost::spirit::tag::repeat(Count)> |
| {}; |
| } |
| |
| template <typename Count> |
| inline typename traits::deref_spec<Count>::type |
| deref_spec(Count const& count) |
| { |
| using boost::spirit::karma::repeat; |
| return repeat(count); |
| } |
| |
| typedef traits::deref_spec<int>::type deref_tag_type; |
| deref_tag_type const deref = deref_spec(1); |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename OutputIterator> |
| struct qiexpr_generator : grammar<OutputIterator, space_type, utree()> |
| { |
| qiexpr_generator() : qiexpr_generator::base_type(start) |
| { |
| namespace phoenix = boost::phoenix; |
| |
| using boost::spirit::karma::eps; |
| using boost::spirit::karma::ascii::string; |
| using boost::spirit::karma::omit; |
| using boost::spirit::karma::_r1; |
| using boost::spirit::karma::strict; |
| using boost::spirit::karma::eol; |
| using boost::phoenix::ref; |
| |
| start = |
| nil |
| | rule_ |
| ; |
| |
| grammar_ = |
| nil |
| | rule_ % eol |
| ; |
| |
| rule_ = |
| &symbol(ref("define")) |
| << deref[rule_name] << '=' << deref[alternative] |
| | alternative |
| ; |
| |
| alternative = |
| &symbol(ref("qi:|")) |
| << '(' << strict[permutation % '|'] << ')' |
| | permutation |
| ; |
| |
| permutation = |
| &symbol(ref("qi:^")) |
| << '(' << strict[sequence % '^'] << ')' |
| | sequence |
| ; |
| |
| sequence = |
| &symbol(ref("qi:>>")) |
| << '(' << strict[term % ">>"] << ')' |
| | term |
| ; |
| |
| term = strict[ |
| unary << '(' << deref[alternative] << ')' |
| | primitive2 << '(' << literal << ',' << literal << ')' |
| | primitive1 << '(' << literal << ')' |
| | primitive0_rule |
| | directive0 << '[' << deref[alternative] << ']' |
| | alternative_rule |
| ]; |
| |
| primitive0_rule = strict[deref[primitive0]]; |
| alternative_rule = alternative; |
| |
| rule_name = strict[deref[any_symbol]]; |
| |
| any_symbol = string; |
| symbol = string(_r1); |
| literal = '"' << string << '"'; |
| nil = eps; |
| |
| // fill the symbol tables with all known primitive parser names |
| std::string name("qi:"); |
| for (char const* const* p = primitives0; *p; ++p) |
| primitive0.add(utf8_symbol(name + *p)); |
| |
| for (char const* const* p = primitives1; *p; ++p) |
| primitive1.add(utf8_symbol(name + *p)); |
| |
| for (char const* const* p = primitives2; *p; ++p) |
| primitive2.add(utf8_symbol(name + *p)); |
| |
| for (char const* const* p = unary_names; *p; ++p) |
| unary.add(utf8_symbol(name + *p)); |
| |
| for (char const* const* p = directives0; *p; ++p) |
| directive0.add(utf8_symbol(name + *p)); |
| |
| BOOST_SPIRIT_DEBUG_NODE(start); |
| BOOST_SPIRIT_DEBUG_NODE(grammar_); |
| BOOST_SPIRIT_DEBUG_NODE(rule_); |
| BOOST_SPIRIT_DEBUG_NODE(rule_name); |
| BOOST_SPIRIT_DEBUG_NODE(alternative); |
| BOOST_SPIRIT_DEBUG_NODE(permutation); |
| BOOST_SPIRIT_DEBUG_NODE(sequence); |
| BOOST_SPIRIT_DEBUG_NODE(term); |
| BOOST_SPIRIT_DEBUG_NODE(nil); |
| BOOST_SPIRIT_DEBUG_NODE(literal); |
| BOOST_SPIRIT_DEBUG_NODE(symbol); |
| BOOST_SPIRIT_DEBUG_NODE(any_symbol); |
| BOOST_SPIRIT_DEBUG_NODE(primitive0_rule); |
| BOOST_SPIRIT_DEBUG_NODE(alternative_rule); |
| } |
| |
| typedef rule<OutputIterator, space_type, utree()> delimiting_rule_type; |
| |
| delimiting_rule_type start, alternative, permutation, sequence, term; |
| delimiting_rule_type grammar_, rule_; |
| delimiting_rule_type rule_name, primitive0_rule, alternative_rule; |
| rule<OutputIterator, scheme::nil()> nil; |
| rule<OutputIterator, scheme::utf8_string()> literal; |
| rule<OutputIterator, scheme::utf8_symbol(std::string)> symbol; |
| rule<OutputIterator, scheme::utf8_symbol()> any_symbol; |
| |
| symbols<scheme::utf8_symbol> unary, directive0; |
| symbols<scheme::utf8_symbol> primitive0, primitive1, primitive2; |
| }; |
| }} |
| |
| #endif |
| |
| |
| |