Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61580 - in trunk/libs/spirit/example/scheme: example/generate_qiexpr example/parse_qiexpr qi
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-26 13:34:01


Author: hkaiser
Date: 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
New Revision: 61580
URL: http://svn.boost.org/trac/boost/changeset/61580

Log:
Spirit: added Qi rules and grammars to Qi parser
Text files modified:
   trunk/libs/spirit/example/scheme/example/generate_qiexpr/generate_qi_test.cpp | 2
   trunk/libs/spirit/example/scheme/example/generate_qiexpr/input.txt | 2
   trunk/libs/spirit/example/scheme/example/parse_qiexpr/generate_sexpr_to_ostream.cpp | 1
   trunk/libs/spirit/example/scheme/example/parse_qiexpr/parse_qi_test.cpp | 88 ++++++++++++++++++++++++++++++++++-----
   trunk/libs/spirit/example/scheme/example/parse_qiexpr/parse_qiexpr.cpp | 4 +
   trunk/libs/spirit/example/scheme/qi/parse_qiexpr.hpp | 8 +++
   trunk/libs/spirit/example/scheme/qi/parse_qiexpr_impl.hpp | 30 +++++++++++++
   trunk/libs/spirit/example/scheme/qi/qiexpr_parser.hpp | 70 ++++++++++++++++++++++++++++---
   8 files changed, 182 insertions(+), 23 deletions(-)

Modified: trunk/libs/spirit/example/scheme/example/generate_qiexpr/generate_qi_test.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/example/generate_qiexpr/generate_qi_test.cpp (original)
+++ trunk/libs/spirit/example/scheme/example/generate_qiexpr/generate_qi_test.cpp 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
@@ -29,7 +29,7 @@
         str += '\n';
 
         scheme::utree result;
- if (scheme::input::parse_qiexpr(str, result))
+ if (scheme::input::parse_qi_expr(str, result))
         {
             std::string str;
             if (scheme::output::generate_qiexpr(result, str))

Modified: trunk/libs/spirit/example/scheme/example/generate_qiexpr/input.txt
==============================================================================
--- trunk/libs/spirit/example/scheme/example/generate_qiexpr/input.txt (original)
+++ trunk/libs/spirit/example/scheme/example/generate_qiexpr/input.txt 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
@@ -1,3 +1,5 @@
+int_ >> *(('+' >> int_) | ('-' >> int_))
+
 // Copyright (c) 2001-2010 Hartmut Kaiser
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying

Modified: trunk/libs/spirit/example/scheme/example/parse_qiexpr/generate_sexpr_to_ostream.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/example/parse_qiexpr/generate_sexpr_to_ostream.cpp (original)
+++ trunk/libs/spirit/example/scheme/example/parse_qiexpr/generate_sexpr_to_ostream.cpp 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
@@ -13,6 +13,7 @@
 namespace scheme { namespace output
 {
     template bool generate_sexpr(BOOST_TYPEOF(std::cout)&, utree const& result);
+ template bool generate_sexpr_list(BOOST_TYPEOF(std::cout)&, utree const& result);
 }}
 
 ///////////////////////////////////////////////////////////////////////////////

Modified: trunk/libs/spirit/example/scheme/example/parse_qiexpr/parse_qi_test.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/example/parse_qiexpr/parse_qi_test.cpp (original)
+++ trunk/libs/spirit/example/scheme/example/parse_qiexpr/parse_qi_test.cpp 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
@@ -11,15 +11,79 @@
 #include <fstream>
 #include <iterator>
 
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/lexical_cast.hpp>
+
 #include <utree/utree.hpp>
 #include <qi/parse_qiexpr.hpp>
 #include <output/generate_sexpr.hpp>
 
 ///////////////////////////////////////////////////////////////////////////////
+bool parse_rhs(std::string const& str, scheme::utree& result)
+{
+ if (scheme::input::parse_qi_expr(str, result))
+ {
+ if (scheme::output::generate_sexpr(std::cout, result))
+ {
+ std::cout << std::endl;
+ return true;
+ }
+ else
+ {
+ std::cout << "generate error" << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << "parse error" << std::endl;
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool parse_rule(std::string str)
+{
+ // construct a rule
+ str = "name = " + str;
+
+ // parse it
+ scheme::utree result;
+ if (scheme::input::parse_qi_rule(str, result))
+ {
+ if (scheme::output::generate_sexpr(std::cout, result))
+ {
+ std::cout << std::endl;
+ return true;
+ }
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool parse_grammar(std::string str)
+{
+ // parse it
+ scheme::utree result;
+// if (scheme::input::parse_qi_grammar(str, result))
+ scheme::input::parse_qi_grammar(str, result);
+ {
+ if (scheme::output::generate_sexpr_list(std::cout, result))
+ {
+ std::cout << std::endl;
+ return true;
+ }
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Main program
 ///////////////////////////////////////////////////////////////////////////////
 int main(int argc, char **argv)
 {
+ std::string rules;
+ int i = 0;
+
     std::string str;
     while (std::getline(std::cin, str))
     {
@@ -27,22 +91,22 @@
             break;
         str += '\n';
 
+ bool r = false;
         scheme::utree result;
- if (scheme::input::parse_qiexpr(str, result))
+ BOOST_TEST(r = parse_rhs(str, result));
+ if (r && result.which() != scheme::utree_type::nil_type)
         {
- if (scheme::output::generate_sexpr(std::cout, result))
+ BOOST_TEST(r = parse_rule(str));
+ if (r)
             {
- std::cout << std::endl;
- }
- else
- {
- std::cout << "generate error" << std::endl;
+ rules += "rule" + boost::lexical_cast<std::string>(++i)
+ + " = " + str + "\n";
             }
         }
- else
- {
- std::cout << "parse error" << std::endl;
- }
     }
- return 0;
+
+ // now test grammar rule
+ BOOST_TEST(parse_grammar(rules));
+
+ return boost::report_errors();
 }

Modified: trunk/libs/spirit/example/scheme/example/parse_qiexpr/parse_qiexpr.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/example/parse_qiexpr/parse_qiexpr.cpp (original)
+++ trunk/libs/spirit/example/scheme/example/parse_qiexpr/parse_qiexpr.cpp 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
@@ -11,6 +11,8 @@
 // explicit template instantiation for the function parse_qiexpr
 namespace scheme { namespace input
 {
- template bool parse_qiexpr(std::string const&, utree& result);
+ template bool parse_qi_expr(std::string const&, utree& result);
+ template bool parse_qi_rule(std::string const&, utree& result);
+ template bool parse_qi_grammar(std::string const&, utree& result);
 }}
 

Modified: trunk/libs/spirit/example/scheme/qi/parse_qiexpr.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/qi/parse_qiexpr.hpp (original)
+++ trunk/libs/spirit/example/scheme/qi/parse_qiexpr.hpp 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
@@ -11,7 +11,13 @@
 namespace scheme { namespace input
 {
     template <typename String>
- bool parse_qiexpr(String const& str, utree& result);
+ bool parse_qi_expr(String const& str, utree& result);
+
+ template <typename String>
+ bool parse_qi_rule(String const& str, utree& result);
+
+ template <typename String>
+ bool parse_qi_grammar(String const& str, utree& result);
 }}
 
 #endif

Modified: trunk/libs/spirit/example/scheme/qi/parse_qiexpr_impl.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/qi/parse_qiexpr_impl.hpp (original)
+++ trunk/libs/spirit/example/scheme/qi/parse_qiexpr_impl.hpp 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
@@ -17,7 +17,7 @@
 {
     ///////////////////////////////////////////////////////////////////////////
     template <typename String>
- bool parse_qiexpr(String const& str, utree& result)
+ bool parse_qi_expr(String const& str, utree& result)
     {
         typedef typename String::const_iterator iterator_type;
 
@@ -28,6 +28,34 @@
         iterator_type end = str.end();
         return phrase_parse(begin, end, p, ws, result) && begin == end;
     }
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename String>
+ bool parse_qi_rule(String const& str, utree& result)
+ {
+ typedef typename String::const_iterator iterator_type;
+
+ scheme::qi::qiexpr_parser<iterator_type> p;
+ scheme::qi::qiexpr_white_space<iterator_type> ws;
+
+ iterator_type begin = str.begin();
+ iterator_type end = str.end();
+ return phrase_parse(begin, end, p.rule_, ws, result) && begin == end;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename String>
+ bool parse_qi_grammar(String const& str, utree& result)
+ {
+ typedef typename String::const_iterator iterator_type;
+
+ scheme::qi::qiexpr_parser<iterator_type> p;
+ scheme::qi::qiexpr_white_space<iterator_type> ws;
+
+ iterator_type begin = str.begin();
+ iterator_type end = str.end();
+ return phrase_parse(begin, end, p.grammar_, ws, result) && begin == end;
+ }
 }}
 
 #endif

Modified: trunk/libs/spirit/example/scheme/qi/qiexpr_parser.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/qi/qiexpr_parser.hpp (original)
+++ trunk/libs/spirit/example/scheme/qi/qiexpr_parser.hpp 2010-04-26 13:33:59 EDT (Mon, 26 Apr 2010)
@@ -40,6 +40,7 @@
     using boost::spirit::qi::_val;
     using boost::spirit::qi::_1;
     using boost::spirit::qi::_2;
+ using boost::spirit::qi::lexeme;
     using boost::phoenix::push_back;
 
     ///////////////////////////////////////////////////////////////////////////
@@ -84,7 +85,7 @@
         // element is the symbol this function object has been constructed from
         struct make_list_node
         {
- template <typename T1, typename T2 = nil, typename T3 = nil>
+ template <typename T1, typename T2 = nil>
             struct result { typedef void type; };
 
             explicit make_list_node(char const* symbol_)
@@ -120,6 +121,15 @@
                 val.push_back(element);
             }
 
+ utf8_symbol symbol;
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ struct make_directive_node
+ {
+ template <typename T1, typename T2, typename T3>
+ struct result { typedef void type; };
+
             void operator()(utree& val, utree const& element, utree const& sym) const
             {
                 if (!is_list_node(val, sym)) {
@@ -131,8 +141,29 @@
                 }
                 val.push_back(element);
             }
+ };
 
- utf8_symbol symbol;
+ ///////////////////////////////////////////////////////////////////////
+ // this creates a scheme definition:
+ //
+ // i.e. (define (_1) exp)
+ struct make_define_node
+ {
+ template <typename T1, typename T2, typename T3>
+ struct result { typedef void type; };
+
+ explicit make_define_node() : define_("define") {}
+
+ void operator()(utree& val, utree const& name, utree const& exp) const
+ {
+ val.push_back(define_);
+ utree n;
+ n.push_back(name);
+ val.push_back(n);
+ val.push_back(exp);
+ }
+
+ utf8_symbol define_;
         };
     }
 
@@ -144,12 +175,16 @@
         typedef typename boost::detail::iterator_traits<Iterator>::value_type
             char_type;
 
- qiexpr_parser() : qiexpr_parser::base_type(start)
+ qiexpr_parser() : qiexpr_parser::base_type(rhs)
         {
             namespace phoenix = boost::phoenix;
             typedef phoenix::function<detail::make_list_node> make_list_type;
+ typedef phoenix::function<detail::make_directive_node> make_directive_type;
+ typedef phoenix::function<detail::make_define_node> make_define_type;
+
+ make_directive_type make_directive = detail::make_directive_node();
 
- make_list_type make_directive = detail::make_list_node("");
+ make_define_type make_define = detail::make_define_node();
 
             make_list_type make_sequence = detail::make_list_node("qi:>>");
             make_list_type make_permutation = detail::make_list_node("qi:^");
@@ -163,7 +198,20 @@
 
             make_list_type make_literal = detail::make_list_node("qi:lit");
 
- start = -alternative;
+ // grammar definition
+ grammar_ = +rule_
+ ;
+
+ // rule definition
+ rule_ =
+ (symbol >> '=' >> alternative)
+ [
+ make_define(_val, _1, _2)
+ ]
+ ;
+
+ // right hand side of a rule (any parser expression)
+ rhs = -alternative;
 
             // A | B
             alternative =
@@ -222,6 +270,9 @@
                 | string_lit.char_lit [ phoenix::push_back(_val, _1) ]
                 ;
 
+ std::string exclude = std::string(" ();\"\x01-\x1f\x7f") + '\0';
+ symbol = lexeme[+(~char_(exclude))];
+
             // fill the symbol tables with all known primitive parser names
             std::string name("qi:");
             for (char const* const* p = primitives0; *p; ++p)
@@ -251,12 +302,15 @@
                 directive0.add(*p, u);
             }
 
- BOOST_SPIRIT_DEBUG_NODE(start);
+ BOOST_SPIRIT_DEBUG_NODE(grammar_);
+ BOOST_SPIRIT_DEBUG_NODE(rule_);
+ BOOST_SPIRIT_DEBUG_NODE(rhs);
             BOOST_SPIRIT_DEBUG_NODE(directive);
             BOOST_SPIRIT_DEBUG_NODE(primitive);
             BOOST_SPIRIT_DEBUG_NODE(unary_term);
             BOOST_SPIRIT_DEBUG_NODE(term);
             BOOST_SPIRIT_DEBUG_NODE(literal);
+ BOOST_SPIRIT_DEBUG_NODE(symbol);
             BOOST_SPIRIT_DEBUG_NODE(alternative);
             BOOST_SPIRIT_DEBUG_NODE(permutation);
             BOOST_SPIRIT_DEBUG_NODE(sequence);
@@ -264,8 +318,10 @@
 
         typedef rule<Iterator, qiexpr_white_space<Iterator>, utree()> rule_type;
 
- rule_type start, directive, primitive, unary_term, term, literal;
+ rule_type grammar_, rule_;
+ rule_type rhs, directive, primitive, unary_term, term, literal;
         rule_type alternative, permutation, sequence;
+ rule<Iterator, utf8_symbol()> symbol;
 
         symbols<char_type, utree> directive0, directive1;
         symbols<char_type, utree> primitive0, primitive1, primitive2;


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