Boost logo

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