|
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