|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r61257 - in trunk/libs/spirit/example/scheme: . detail input output test/parse_qiexpr
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-13 16:00:10
Author: hkaiser
Date: 2010-04-13 16:00:09 EDT (Tue, 13 Apr 2010)
New Revision: 61257
URL: http://svn.boost.org/trac/boost/changeset/61257
Log:
Spirit: more work on Qi parser
Text files modified:
trunk/libs/spirit/example/scheme/detail/utree_detail3.hpp | 38 ++++++++-
trunk/libs/spirit/example/scheme/input/qiexpr.hpp | 154 ++++++++++++++++++++++++++++++++++++---
trunk/libs/spirit/example/scheme/output/sexpr.hpp | 9 -
trunk/libs/spirit/example/scheme/scheme_interpreter.hpp | 2
trunk/libs/spirit/example/scheme/test/parse_qiexpr/generate_sexpr_to_ostream.cpp | 12 +++
trunk/libs/spirit/example/scheme/test/parse_qiexpr/input.txt | 14 +++
6 files changed, 204 insertions(+), 25 deletions(-)
Modified: trunk/libs/spirit/example/scheme/detail/utree_detail3.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/detail/utree_detail3.hpp (original)
+++ trunk/libs/spirit/example/scheme/detail/utree_detail3.hpp 2010-04-13 16:00:09 EDT (Tue, 13 Apr 2010)
@@ -26,7 +26,9 @@
SCHEME_GET_UTREE_TYPE(int, utree_type::int_type);
SCHEME_GET_UTREE_TYPE(double, utree_type::double_type);
SCHEME_GET_UTREE_TYPE(utf8_string_range, utree_type::string_type);
+ SCHEME_GET_UTREE_TYPE(utf8_string, utree_type::string_type);
SCHEME_GET_UTREE_TYPE(utf8_symbol_range, utree_type::symbol_type);
+ SCHEME_GET_UTREE_TYPE(utf8_symbol, utree_type::string_type);
SCHEME_GET_UTREE_TYPE(binary_range, utree_type::binary_type);
SCHEME_GET_UTREE_TYPE(boost::iterator_range<utree::iterator>,
utree_type::list_type);
@@ -100,6 +102,16 @@
};
template <>
+ struct get_impl<utf8_string>
+ {
+ typedef utf8_string type;
+ static type call(utree const& x)
+ {
+ return type(x.s.str(), x.s.size());
+ }
+ };
+
+ template <>
struct get_impl<utf8_symbol_range>
{
typedef utf8_symbol_range type;
@@ -110,6 +122,16 @@
};
template <>
+ struct get_impl<utf8_symbol>
+ {
+ typedef utf8_symbol type;
+ static type call(utree const& x)
+ {
+ return type(x.s.str(), x.s.size());
+ }
+ };
+
+ template <>
struct get_impl<binary_range>
{
typedef binary_range type;
@@ -119,20 +141,24 @@
}
};
}
+}
- ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+namespace boost
+{
template <typename T>
- typename detail::get_impl<T>::type
- get(utree const& x)
+ typename scheme::detail::get_impl<T>::type
+ get(scheme::utree const& x)
{
- if (x.which() != detail::get_utree_type<T>::value)
+ if (x.which() !=
+ (scheme::utree_type::info)scheme::detail::get_utree_type<T>::value)
{
- if (x.which() == utree_type::reference_type)
+ if (x.which() == scheme::utree_type::reference_type)
return get<T>(x.deref());
throw boost::bad_get();
}
- return detail::get_impl<T>::call(x);
+ return scheme::detail::get_impl<T>::call(x);
}
}
Modified: trunk/libs/spirit/example/scheme/input/qiexpr.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/input/qiexpr.hpp (original)
+++ trunk/libs/spirit/example/scheme/input/qiexpr.hpp 2010-04-13 16:00:09 EDT (Tue, 13 Apr 2010)
@@ -17,9 +17,15 @@
#include <boost/spirit/include/phoenix_operator.hpp>
#include "../utree.hpp"
+#include "../detail/utree_detail3.hpp"
#include "../utree_operators.hpp"
#include "string.hpp"
+namespace boost { namespace spirit { namespace traits
+{
+ void print_attribute(std::ostream& out, scheme::utree const& val);
+}}}
+
///////////////////////////////////////////////////////////////////////////////
namespace scheme { namespace input
{
@@ -30,6 +36,7 @@
using boost::spirit::qi::eol;
using boost::spirit::qi::_val;
using boost::spirit::qi::_1;
+ using boost::spirit::qi::_2;
using boost::phoenix::push_back;
using boost::phoenix::function;
@@ -61,27 +68,66 @@
return u.front() == symbol;
}
+ inline bool is_list_node(utree const& u, utree const& symbol)
+ {
+ if (u.which() != utree_type::list_type)
+ return false;
+ if (symbol.which() == utree_type::list_type)
+ return u.front() == symbol.front();
+ return u.front() == symbol;
+ }
+
///////////////////////////////////////////////////////////////////////
// ensure the given utree instance represents a list whose first
// element is the symbol this function object has been constructed from
struct make_list_node
{
- template <typename S, typename C>
+ template <typename T1, typename T2 = nil, typename T3 = nil>
struct result { typedef void type; };
explicit make_list_node(char const* symbol_)
: symbol(symbol_)
{}
- void operator()(utree& seq, utree const& element) const
+ // If called with one parameter the given node needs to be
+ // converted into a list whose first element is the symbol.
+ //
+ // i.e:
+ // lit: ("abc") --> (lit "abc")
+ void operator()(utree& u) const
+ {
+ u.push_front(symbol);
+ }
+
+ // If called with two parameters we ensure the given node is a
+ // (new) list whose first element is the symbol and we append the
+ // given element to that list.
+ //
+ // i.e.:
+ // >>: (char_), (char_ "abc") --> (>> (char_) (char_ "abc"))
+ // >>: (>> (char_ "a")), (char_) --> (>> (char_ "a") (char_))
+ void operator()(utree& val, utree const& element) const
{
- if (!is_list_node(seq, symbol)) {
+ if (!is_list_node(val, symbol)) {
utree u;
u.push_back(symbol);
- u.push_back(seq);
- seq = u;
+ if (val.which() != utree_type::nil_type)
+ u.push_back(val);
+ val = u;
+ }
+ val.push_back(element);
+ }
+
+ void operator()(utree& val, utree const& element, utree const& sym) const
+ {
+ if (!is_list_node(val, sym)) {
+ utree u;
+ u.push_back(sym);
+ if (val.which() != utree_type::nil_type)
+ u.push_back(val);
+ val = u;
}
- seq.push_back(element);
+ val.push_back(element);
}
utf8_symbol symbol;
@@ -104,12 +150,21 @@
, "bin", "oct", "hex"
, "bool_", "true_", "false_"
, "long_double", "double_", "float_"
+
+ // binary
+ , "qword", "dword", "word", "byte_"
+ , "little_qword", "little_dword", "little_word"
+ , "big_qword", "big_dword", "big_word"
+
+ // auxiliary
+ , "eol", "eoi", "eps"
, 0
};
// a list of names for all supported parser primitives taking 1 parameter
static char const* const primitives1[] =
{
+ // character parsers
"char_", "lit", "string"
, 0
};
@@ -121,6 +176,23 @@
, 0
};
+ // a list of names for all supported parser directives taking 0 parameter
+ static char const* const directives0[] =
+ {
+ // manage skip parser
+ "lexeme", "skip", "no_skip"
+
+ // case management
+ , "no_case"
+
+ // auxiliary
+ , "omit", "raw"
+
+ // encoding
+ , "ascii", "standard", "standard_wide", "iso8859_1", "unicode"
+ , 0
+ };
+
///////////////////////////////////////////////////////////////////////////
template <typename Iterator>
struct qiexpr : grammar<Iterator, qiexpr_white_space<Iterator>, utree()>
@@ -132,34 +204,71 @@
{
typedef function<detail::make_list_node> make_list_type;
+ make_list_type make_directive = detail::make_list_node("");
+
make_list_type make_sequence = detail::make_list_node(">>");
+ make_list_type make_permutation = detail::make_list_node("^");
make_list_type make_alternative = detail::make_list_node("|");
+ make_list_type make_kleene = detail::make_list_node("*");
+ make_list_type make_plus = detail::make_list_node("+");
+ make_list_type make_optional = detail::make_list_node("-");
+ make_list_type make_and_pred = detail::make_list_node("&");
+ make_list_type make_not_pred = detail::make_list_node("!");
+
+ make_list_type make_literal = detail::make_list_node("lit");
+
start = -alternative;
// A | B
alternative =
- sequence [ _val = _1 ]
- >> *( '|' >> sequence [ make_alternative(_val, _1) ] )
+ permutation [ _val = _1 ]
+ >> *( '|' >> permutation [ make_alternative(_val, _1) ] )
+ ;
+
+ // A ^ B
+ permutation =
+ sequence [ _val = _1 ]
+ >> *( "^" >> sequence [ make_permutation(_val, _1) ] )
;
// A >> B
sequence =
- term [ _val = _1 ]
- >> *( ">>" >> term [ make_sequence(_val, _1) ] )
+ unary_term [ _val = _1 ]
+ >> *( ">>" >> unary_term [ make_sequence(_val, _1) ] )
+ ;
+
+ // unary operators
+ unary_term =
+ '*' >> term [ make_kleene(_val, _1) ]
+ | '+' >> term [ make_plus(_val, _1) ]
+ | '-' >> term [ make_optional(_val, _1) ]
+ | '&' >> term [ make_and_pred(_val, _1) ]
+ | '!' >> term [ make_not_pred(_val, _1) ]
+ | term [ _val = _1 ]
;
// A, (A)
term =
primitive
+ | directive
| '(' >> alternative >> ')'
;
+ // any parser directive
+ directive =
+ (directive0 >> '[' >> alternative >> ']')
+ [
+ make_directive(_val, _2, _1)
+ ]
+ ;
+
// any primitive parser
- primitive =
+ primitive %=
primitive2 >> '(' >> literal >> ',' >> literal >> ')'
| primitive1 >> '(' >> literal >> ')'
| primitive0 // taking no parameter
+ | literal [ make_literal(_val) ]
;
// a literal (either 'x' or "abc")
@@ -189,11 +298,32 @@
u.push_back(utf8_symbol(*p));
primitive2.add(*p, u);
}
+
+ for (char const* const* p = directives0; *p; ++p)
+ {
+ utree u = utree(utf8_symbol(*p));
+ directive0.add(*p, u);
+ }
+
+#if defined(BOOST_SPIRIT_DEBUG)
+ start.name("name"); debug(start);
+ directive.name("directive"); debug(directive);
+ primitive.name("primitive"); debug(primitive);
+ unary_term.name("unary_term"); debug(unary_term);
+ term.name("term"); debug(term);
+ literal.name("literal"); debug(literal);
+ alternative.name("alternative"); debug(alternative);
+ permutation.name("permutation"); debug(permutation);
+ sequence.name("sequence"); debug(sequence);
+#endif
}
typedef rule<Iterator, qiexpr_white_space<Iterator>, utree()> rule_type;
- rule_type start, alternative, sequence, primitive, term, literal;
+ rule_type start, directive, primitive, unary_term, term, literal;
+ rule_type alternative, permutation, sequence;
+
+ symbols<char_type, utree> directive0, directive1;
symbols<char_type, utree> primitive0, primitive1, primitive2;
scheme::input::string<Iterator> string_lit;
};
Modified: trunk/libs/spirit/example/scheme/output/sexpr.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/output/sexpr.hpp (original)
+++ trunk/libs/spirit/example/scheme/output/sexpr.hpp 2010-04-13 16:00:09 EDT (Tue, 13 Apr 2010)
@@ -19,12 +19,9 @@
namespace boost { namespace spirit { namespace traits
{
// the specialization below tells Spirit to handle scheme::utree as if it
- // where a 'real' variant
- template <typename T>
- struct not_is_variant;
-
+ // where a 'real' variant (in the context of karma)
template <>
- struct not_is_variant<scheme::utree>
+ struct not_is_variant<scheme::utree, karma::domain>
: mpl::false_ {};
// The specializations below tell Spirit to verify whether an attribute
@@ -175,7 +172,7 @@
string_ = '"' << string << '"';
symbol = string;
byte_str = 'b' << *right_align(2, '0')[hex2];
- nil_ = eps;
+ nil_ = eps << "<nil>";
}
typedef boost::iterator_range<utree::const_iterator> utree_list;
Modified: trunk/libs/spirit/example/scheme/scheme_interpreter.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/scheme_interpreter.hpp (original)
+++ trunk/libs/spirit/example/scheme/scheme_interpreter.hpp 2010-04-13 16:00:09 EDT (Tue, 13 Apr 2010)
@@ -1,4 +1,4 @@
-/*=============================================================================
+/*=============================================================================
Copyright (c) 2001-2010 Joel de Guzman
Distributed under the Boost Software License, Version 1.0. (See accompanying
Modified: trunk/libs/spirit/example/scheme/test/parse_qiexpr/generate_sexpr_to_ostream.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/test/parse_qiexpr/generate_sexpr_to_ostream.cpp (original)
+++ trunk/libs/spirit/example/scheme/test/parse_qiexpr/generate_sexpr_to_ostream.cpp 2010-04-13 16:00:09 EDT (Tue, 13 Apr 2010)
@@ -8,9 +8,21 @@
#include <fstream>
+///////////////////////////////////////////////////////////////////////////////
// explicit template instantiation for the function parse_sexpr
namespace scheme { namespace output
{
template bool generate_sexpr(BOOST_TYPEOF(std::cout)&, utree const& result);
}}
+///////////////////////////////////////////////////////////////////////////////
+// this is needed if grammar debugging is on
+#if defined(BOOST_SPIRIT_DEBUG)
+namespace boost { namespace spirit { namespace traits
+{
+ void print_attribute(std::ostream& out, scheme::utree const& val)
+ {
+ scheme::output::generate_sexpr(out, val);
+ }
+}}}
+#endif
Modified: trunk/libs/spirit/example/scheme/test/parse_qiexpr/input.txt
==============================================================================
--- trunk/libs/spirit/example/scheme/test/parse_qiexpr/input.txt (original)
+++ trunk/libs/spirit/example/scheme/test/parse_qiexpr/input.txt 2010-04-13 16:00:09 EDT (Tue, 13 Apr 2010)
@@ -8,6 +8,8 @@
char_("abc")
char_('a')
char_('a', 'b')
+'a'
+"abc"
// sequences
char_ >> char_
@@ -23,4 +25,16 @@
char_ >> (char_('a') | char_('a', 'b'))
char_ >> char_('a') | char_('a', 'b')
(char_ >> char_('a')) | char_('a', 'b')
+
+// unary operators
+*double_
++long_
+&int_ >> double_
+!int_ >> *double_
+char_ >> *(',' >> char_)
+
+// directives
+lexeme[*double_]
+
+
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk