Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r69380 - trunk/libs/spirit/example/qi/compiler_tutorial/calc7
From: joel_at_[hidden]
Date: 2011-02-28 06:57:41


Author: djowel
Date: 2011-02-28 06:57:37 EST (Mon, 28 Feb 2011)
New Revision: 69380
URL: http://svn.boost.org/trac/boost/changeset/69380

Log:
Better error handling and reporting.
Text files modified:
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp | 9 +++-
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp | 71 ++++++++++++++++++++++++++++-----------
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp | 5 +-
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp | 17 ++++++---
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp | 38 +++++++++++---------
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp | 2
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp | 22 +++++++-----
   7 files changed, 104 insertions(+), 60 deletions(-)

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp 2011-02-28 06:57:37 EST (Mon, 28 Feb 2011)
@@ -51,13 +51,16 @@
     {
         typedef bool result_type;
 
- template <typename IterList, typename Iterator>
- compiler(client::program& program, IterList const& iters, Iterator last)
+ template <typename ErrorHandler>
+ compiler(client::program& program, ErrorHandler& error_handler_)
           : program(program)
         {
             using namespace boost::phoenix::arg_names;
             using boost::phoenix::cref;
- error_handler = client::error_handler("Error! ", _2, cref(iters)[_1], last);
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, cref(error_handler_.iters)[_1]);
         }
 
         bool operator()(ast::nil) const { BOOST_ASSERT(0); return false; }

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp 2011-02-28 06:57:37 EST (Mon, 28 Feb 2011)
@@ -9,36 +9,64 @@
 
 #include <iostream>
 #include <string>
-#include <boost/spirit/include/phoenix_function.hpp>
+#include <vector>
 
 namespace client
 {
- using boost::phoenix::function;
-
     ///////////////////////////////////////////////////////////////////////////////
     // The error handler
     ///////////////////////////////////////////////////////////////////////////////
- struct error_handler_
+ template <typename Iterator>
+ struct error_handler
     {
- template <typename, typename, typename, typename>
+ template <typename, typename, typename>
         struct result { typedef void type; };
 
- template <typename Message, typename What, typename Iterator>
- void operator()(Message const& message, What const& what
- , Iterator err_pos, Iterator last) const
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
         {
- std::cout
- << message
- << what
- << " here: \""
- << get_line(err_pos, last)
- << "\""
- << std::endl
- ;
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
         }
 
- template <typename Iterator>
- std::string get_line(Iterator err_pos, Iterator last) const
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
         {
             Iterator i = err_pos;
             // position i to the next EOL
@@ -46,10 +74,11 @@
                 ++i;
             return std::string(err_pos, i);
         }
- };
 
- boost::phoenix::function<error_handler_> const
- error_handler = error_handler_();
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
 }
 
 #endif

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp 2011-02-28 06:57:37 EST (Mon, 28 Feb 2011)
@@ -23,6 +23,7 @@
 
 #include <boost/spirit/include/qi.hpp>
 #include "ast.hpp"
+#include "error_handler.hpp"
 #include <vector>
 
 namespace client
@@ -36,7 +37,7 @@
     template <typename Iterator>
     struct expression : qi::grammar<Iterator, ast::expression(), ascii::space_type>
     {
- expression();
+ expression(error_handler<Iterator>& error_handler);
 
         qi::rule<Iterator, ast::expression(), ascii::space_type> expr;
         qi::rule<Iterator, ast::expression(), ascii::space_type> additive_expr;
@@ -44,8 +45,6 @@
         qi::rule<Iterator, ast::operand(), ascii::space_type> unary_expr;
         qi::rule<Iterator, ast::operand(), ascii::space_type> primary_expr;
         qi::rule<Iterator, std::string(), ascii::space_type> identifier;
-
- std::vector<Iterator> iters;
     };
 }
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp 2011-02-28 06:57:37 EST (Mon, 28 Feb 2011)
@@ -7,11 +7,12 @@
 #include "expression.hpp"
 #include "error_handler.hpp"
 #include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
 
 namespace client
 {
     template <typename Iterator>
- expression<Iterator>::expression()
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
       : expression::base_type(expr)
     {
         qi::_1_type _1;
@@ -30,6 +31,10 @@
         using qi::on_error;
         using qi::on_success;
         using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
 
         expr =
             additive_expr.alias()
@@ -76,13 +81,13 @@
         );
 
         // Error handling: on error in expr, call error_handler.
- on_error<fail>(expr, error_handler("Error! Expecting ", _4, _3, _2));
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
 
         // Annotation: on success in primary_expr, call annotation.
- typedef client::annotation<Iterator> annotation_;
- typename function<annotation_>
- annotation = annotation_(iters);
- on_success(primary_expr, annotation(_val, _1));
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
     }
 }
 

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp 2011-02-28 06:57:37 EST (Mon, 28 Feb 2011)
@@ -47,12 +47,14 @@
     iterator_type iter = source.begin();
     iterator_type end = source.end();
 
- client::vmachine vm; // Our virtual machine
- client::program program; // Our VM program
- client::statement<iterator_type> parser; // Our parser
- client::ast::statement ast; // Our AST
- client::compiler
- compile(program, parser.expr.iters, end); // Our compiler
+ client::vmachine vm; // Our virtual machine
+ client::program program; // Our VM program
+ client::ast::statement ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::statement<iterator_type> parser(error_handler); // Our parser
+ client::compiler compile(program, error_handler); // Our compiler
 
     boost::spirit::ascii::space_type space;
     bool success = phrase_parse(iter, end, parser, space, ast);
@@ -60,21 +62,23 @@
     std::cout << "-------------------------\n";
 
     if (success && iter == end)
- success = compile(ast);
- else
- std::cout << "Parse failure\n";
-
- if (success)
     {
- std::cout << "Success\n";
- vm.execute(program());
-
- std::cout << "Results------------------\n\n";
- program.print_variables(vm.get_stack());
+ if (compile(ast))
+ {
+ std::cout << "Success\n";
+ vm.execute(program());
+
+ std::cout << "Results------------------\n\n";
+ program.print_variables(vm.get_stack());
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
     }
     else
     {
- std::cout << "Compile failure\n";
+ std::cout << "Parse failure\n";
     }
 
     std::cout << "-------------------------\n\n";

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp 2011-02-28 06:57:37 EST (Mon, 28 Feb 2011)
@@ -17,7 +17,7 @@
     template <typename Iterator>
     struct statement : qi::grammar<Iterator, ast::statement(), ascii::space_type>
     {
- statement();
+ statement(error_handler<Iterator>& error_handler);
 
         expression<Iterator> expr;
         qi::rule<Iterator, ast::statement(), ascii::space_type> start;

Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp 2011-02-28 06:57:37 EST (Mon, 28 Feb 2011)
@@ -11,8 +11,8 @@
 namespace client
 {
     template <typename Iterator>
- statement<Iterator>::statement()
- : statement::base_type(start)
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(start), expr(error_handler)
     {
         qi::_1_type _1;
         qi::_2_type _2;
@@ -28,6 +28,10 @@
         using qi::on_error;
         using qi::on_success;
         using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
 
         start =
             +(variable_declaration | assignment)
@@ -58,13 +62,13 @@
         );
 
         // Error handling: on error in start, call error_handler.
- on_error<fail>(start, error_handler("Error! Expecting ", _4, _3, _2));
-
- // Annotation: on success in variable, call annotation.
- typedef client::annotation<Iterator> annotation_;
- typename function<annotation_>
- annotation = annotation_(expr.iters);
- on_success(assignment, annotation(_val, _1));
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in assignment, call annotation.
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
     }
 }
 


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