$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r67372 - trunk/libs/spirit/example/qi
From: hartmut.kaiser_at_[hidden]
Date: 2010-12-20 14:32:42
Author: hkaiser
Date: 2010-12-20 14:32:40 EST (Mon, 20 Dec 2010)
New Revision: 67372
URL: http://svn.boost.org/trac/boost/changeset/67372
Log:
Spirit: adding examples demonstrating parsing with utree
Added:
   trunk/libs/spirit/example/qi/calc_utree_ast.cpp
      - copied, changed from r67358, /trunk/libs/spirit/example/qi/calc_utree.cpp
   trunk/libs/spirit/example/qi/calc_utree_naive.cpp   (contents, props changed)
Text files modified: 
   trunk/libs/spirit/example/qi/Jamfile            |     2 +                                       
   trunk/libs/spirit/example/qi/calc_utree.cpp     |    72 +++++++++++++++++++++++++++++++-------- 
   trunk/libs/spirit/example/qi/calc_utree_ast.cpp |    72 +++++++++++++++++++++++++++++++-------- 
   3 files changed, 115 insertions(+), 31 deletions(-)
Modified: trunk/libs/spirit/example/qi/Jamfile
==============================================================================
--- trunk/libs/spirit/example/qi/Jamfile	(original)
+++ trunk/libs/spirit/example/qi/Jamfile	2010-12-20 14:32:40 EST (Mon, 20 Dec 2010)
@@ -62,6 +62,8 @@
     calc7/calc7c.cpp
     ;
 
+exe calc_utree_naive : calc_utree_naive.cpp ;
+exe calc_utree_ast : calc_utree_ast.cpp ;
 exe calc_utree : calc_utree.cpp ;
 
 exe mini_c_interp :
Modified: trunk/libs/spirit/example/qi/calc_utree.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/calc_utree.cpp	(original)
+++ trunk/libs/spirit/example/qi/calc_utree.cpp	2010-12-20 14:32:40 EST (Mon, 20 Dec 2010)
@@ -1,6 +1,6 @@
 /*=============================================================================
-    Copyright (c) 2001-2010 Hartmut Kaiser
-    Copyright (c) 2001-2010 Joel de Guzman
+    Copyright (c) 2001-2011 Hartmut Kaiser
+    Copyright (c) 2001-2011 Joel de Guzman
 
     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)
@@ -21,10 +21,52 @@
 #include <boost/config/warning_disable.hpp>
 #include <boost/spirit/include/qi.hpp>
 #include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
 
 #include <iostream>
 #include <string>
 
+#if BOOST_PHOENIX_VERSION == 0x2000
+namespace boost { namespace phoenix 
+{
+    // There's a bug in the Phoenix V2 type deduction mechanism that prevents 
+    // correct return type deduction for for the math operations below. Newer
+    // versions of Phoenix will be switching to BOOST_TYPEOF. In the meantime, 
+    // we will use the specializations helping with return type deduction 
+    // below:
+    template <>
+    struct result_of_plus<spirit::utree&, spirit::utree&> 
+    { 
+        typedef spirit::utree type; 
+    };
+
+    template <>
+    struct result_of_minus<spirit::utree&, spirit::utree&> 
+    { 
+        typedef spirit::utree type; 
+    };
+
+    template <>
+    struct result_of_multiplies<spirit::utree&, spirit::utree&> 
+    { 
+        typedef spirit::utree type; 
+    };
+
+    template <>
+    struct result_of_divides<spirit::utree&, spirit::utree&> 
+    { 
+        typedef spirit::utree type; 
+    };
+
+    template <>
+    struct result_of_negate<spirit::utree&> 
+    { 
+        typedef spirit::utree type; 
+    };
+}}
+#endif
+
 namespace client
 {
     namespace qi = boost::spirit::qi;
@@ -40,27 +82,28 @@
         calculator() : calculator::base_type(expression)
         {
             using qi::uint_;
-            using qi::char_;
+            using qi::_val;
+            using qi::_1;
 
             expression =
-                term
-                >> *(   (char_('+') >> term)
-                    |   (char_('-') >> term)
+                term                            [_val = _1]
+                >> *(   ('+' >> term            [_val = _val + _1])
+                    |   ('-' >> term            [_val = _val - _1])
                     )
                 ;
 
             term =
-                factor
-                >> *(   (char_('*') >> factor)
-                    |   (char_('/') >> factor)
+                factor                          [_val = _1]
+                >> *(   ('*' >> factor          [_val = _val * _1])
+                    |   ('/' >> factor          [_val = _val / _1])
                     )
                 ;
 
             factor =
-                uint_
-                |   char_('(') >> expression >> char_(')')
-                |   (char_('-') >> factor)
-                |   (char_('+') >> factor)
+                uint_                           [_val = _1]
+                |   '(' >> expression           [_val = _1] >> ')'
+                |   ('-' >> factor              [_val = -_1])
+                |   ('+' >> factor              [_val = _1])
                 ;
 
             BOOST_SPIRIT_DEBUG_NODE(expression);
@@ -75,8 +118,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 //  Main program
 ///////////////////////////////////////////////////////////////////////////////
-int
-main()
+int main()
 {
     std::cout << "/////////////////////////////////////////////////////////\n\n";
     std::cout << "Expression parser...\n\n";
Copied: trunk/libs/spirit/example/qi/calc_utree_ast.cpp (from r67358, /trunk/libs/spirit/example/qi/calc_utree.cpp)
==============================================================================
--- /trunk/libs/spirit/example/qi/calc_utree.cpp	(original)
+++ trunk/libs/spirit/example/qi/calc_utree_ast.cpp	2010-12-20 14:32:40 EST (Mon, 20 Dec 2010)
@@ -1,6 +1,6 @@
 /*=============================================================================
-    Copyright (c) 2001-2010 Hartmut Kaiser
-    Copyright (c) 2001-2010 Joel de Guzman
+    Copyright (c) 2001-2011 Hartmut Kaiser
+    Copyright (c) 2001-2011 Joel de Guzman
 
     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)
@@ -19,8 +19,10 @@
 // #define BOOST_SPIRIT_DEBUG
 
 #include <boost/config/warning_disable.hpp>
-#include <boost/spirit/include/qi.hpp>
 #include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
 
 #include <iostream>
 #include <string>
@@ -31,6 +33,44 @@
     namespace ascii = boost::spirit::ascii;
     namespace spirit = boost::spirit;
 
+    struct expr
+    {
+        template <typename T1, typename T2>
+        struct result { typedef void type; };
+
+        expr(char op) : op(op) {}
+
+        void operator()(spirit::utree& expr, spirit::utree const& rhs) const
+        {
+            spirit::utree lhs;
+            lhs.swap(expr);
+            expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
+            expr.push_back(lhs);
+            expr.push_back(rhs);
+        }
+
+        char const op;
+    };
+    boost::phoenix::function<expr> const plus = expr('+');
+    boost::phoenix::function<expr> const minus = expr('-');
+    boost::phoenix::function<expr> const times = expr('*');
+    boost::phoenix::function<expr> const divide = expr('/');
+
+    struct negate_expr
+    {
+        template <typename T1, typename T2>
+        struct result { typedef void type; };
+
+        void operator()(spirit::utree& expr, spirit::utree const& rhs) const
+        {
+            char const op = '-';
+            expr.clear();
+            expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
+            expr.push_back(rhs);
+        }
+    };
+    boost::phoenix::function<negate_expr> neg;
+
     ///////////////////////////////////////////////////////////////////////////////
     //  Our calculator grammar
     ///////////////////////////////////////////////////////////////////////////////
@@ -40,27 +80,28 @@
         calculator() : calculator::base_type(expression)
         {
             using qi::uint_;
-            using qi::char_;
+            using qi::_val;
+            using qi::_1;
 
             expression =
-                term
-                >> *(   (char_('+') >> term)
-                    |   (char_('-') >> term)
+                term                            [_val = _1]
+                >> *(   ('+' >> term            [plus(_val, _1)])
+                    |   ('-' >> term            [minus(_val, _1)])
                     )
                 ;
 
             term =
-                factor
-                >> *(   (char_('*') >> factor)
-                    |   (char_('/') >> factor)
+                factor                          [_val = _1]
+                >> *(   ('*' >> factor          [times(_val, _1)])
+                    |   ('/' >> factor          [divide(_val, _1)])
                     )
                 ;
 
             factor =
-                uint_
-                |   char_('(') >> expression >> char_(')')
-                |   (char_('-') >> factor)
-                |   (char_('+') >> factor)
+                uint_                           [_val = _1]
+                |   '(' >> expression           [_val = _1] >> ')'
+                |   ('-' >> factor              [neg(_val, _1)])
+                |   ('+' >> factor              [_val = _1])
                 ;
 
             BOOST_SPIRIT_DEBUG_NODE(expression);
@@ -75,8 +116,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 //  Main program
 ///////////////////////////////////////////////////////////////////////////////
-int
-main()
+int main()
 {
     std::cout << "/////////////////////////////////////////////////////////\n\n";
     std::cout << "Expression parser...\n\n";
Added: trunk/libs/spirit/example/qi/calc_utree_naive.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc_utree_naive.cpp	2010-12-20 14:32:40 EST (Mon, 20 Dec 2010)
@@ -0,0 +1,132 @@
+/*=============================================================================
+    Copyright (c) 2001-2011 Hartmut Kaiser
+    Copyright (c) 2001-2011 Joel de Guzman
+
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  Plain calculator example demonstrating the grammar. The parser is a
+//  syntax checker only and does not do any semantic evaluation.
+//
+//  [ JDG May 10, 2002 ]        spirit1
+//  [ JDG March 4, 2007 ]       spirit2
+//  [ HK November 30, 2010 ]    spirit2/utree
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// This rather naive example demonstrates that you can pass an instance of a 
+// utree as the attribute for almost any grammar. As the result the utree will
+// be filled with the parse tree as generated during the parsing. This is most 
+// of the time not what's desired, but is usually a good first step in order to
+// prepare your grammar to generate a customized AST. See the calc_utree_ast
+// example for a modified version of this grammar filling the attribute with a
+// AST (abstract syntax tree) representing the math expression as matched from 
+// the input.
+
+// #define BOOST_SPIRIT_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/support_utree.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+    namespace qi = boost::spirit::qi;
+    namespace ascii = boost::spirit::ascii;
+    namespace spirit = boost::spirit;
+
+    ///////////////////////////////////////////////////////////////////////////////
+    //  Our calculator grammar
+    ///////////////////////////////////////////////////////////////////////////////
+    template <typename Iterator>
+    struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
+    {
+        calculator() : calculator::base_type(expression)
+        {
+            using qi::uint_;
+            using qi::char_;
+
+            expression =
+                term
+                >> *(   (char_('+') >> term)
+                    |   (char_('-') >> term)
+                    )
+                ;
+
+            term =
+                factor
+                >> *(   (char_('*') >> factor)
+                    |   (char_('/') >> factor)
+                    )
+                ;
+
+            factor =
+                uint_
+                |   char_('(') >> expression >> char_(')')
+                |   (char_('-') >> factor)
+                |   (char_('+') >> factor)
+                ;
+
+            BOOST_SPIRIT_DEBUG_NODE(expression);
+            BOOST_SPIRIT_DEBUG_NODE(term);
+            BOOST_SPIRIT_DEBUG_NODE(factor);
+        }
+
+        qi::rule<Iterator, ascii::space_type, spirit::utree()> expression, term, factor;
+    };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Expression parser...\n\n";
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+    using boost::spirit::ascii::space;
+    using boost::spirit::utree;
+    typedef std::string::const_iterator iterator_type;
+    typedef client::calculator<iterator_type> calculator;
+
+    calculator calc; // Our grammar
+
+    std::string str;
+    while (std::getline(std::cin, str))
+    {
+        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+            break;
+
+        std::string::const_iterator iter = str.begin();
+        std::string::const_iterator end = str.end();
+        utree ut;
+        bool r = phrase_parse(iter, end, calc, space, ut);
+
+        if (r && iter == end)
+        {
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing succeeded: " << ut << "\n";
+            std::cout << "-------------------------\n";
+        }
+        else
+        {
+            std::string rest(iter, end);
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing failed\n";
+            std::cout << "stopped at: \": " << rest << "\"\n";
+            std::cout << "-------------------------\n";
+        }
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+