|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r69378 - trunk/libs/spirit/example/qi/compiler_tutorial/calc7
From: joel_at_[hidden]
Date: 2011-02-28 01:06:53
Author: djowel
Date: 2011-02-28 01:06:50 EST (Mon, 28 Feb 2011)
New Revision: 69378
URL: http://svn.boost.org/trac/boost/changeset/69378
Log:
Better error handling
Text files modified:
trunk/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp | 3
trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp | 89 +++++++++++++++++++++++----------------
trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp | 42 +++++++++++++-----
trunk/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp | 26 +++++++----
trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp | 12 +++--
trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp | 33 ++++++++------
trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp | 8 ++-
7 files changed, 129 insertions(+), 84 deletions(-)
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp 2011-02-28 01:06:50 EST (Mon, 28 Feb 2011)
@@ -40,8 +40,7 @@
x.id = id;
}
- template <typename T>
- void operator()(T& x) const
+ void operator()(...) const
{
// no need for tags
}
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp (original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp 2011-02-28 01:06:50 EST (Mon, 28 Feb 2011)
@@ -9,8 +9,6 @@
#include <boost/foreach.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/assert.hpp>
-#include <iostream>
-#include <string>
namespace client
{
@@ -54,80 +52,99 @@
}
}
- void compiler::operator()(unsigned int x) const
+ bool compiler::operator()(unsigned int x) const
{
program.op(op_int, x);
+ return true;
}
- void compiler::operator()(ast::variable const& x) const
+ bool compiler::operator()(ast::variable const& x) const
{
int const* p = program.find_var(x.name);
if (p == 0)
{
- // $$$ undefined variable throw exception
- std::cout << "undefined variable: " << x.name << std::endl;
+ std::cout << x.id << std::endl;
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
}
program.op(op_load, *p);
+ return true;
}
- void compiler::operator()(ast::operation const& x) const
+ bool compiler::operator()(ast::operation const& x) const
{
- boost::apply_visitor(*this, x.operand_);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
switch (x.operator_)
{
case '+': program.op(op_add); break;
case '-': program.op(op_sub); break;
case '*': program.op(op_mul); break;
case '/': program.op(op_div); break;
- default: BOOST_ASSERT(0); break;
+ default: BOOST_ASSERT(0); return false;
}
+ return true;
}
- void compiler::operator()(ast::signed_ const& x) const
+ bool compiler::operator()(ast::signed_ const& x) const
{
- boost::apply_visitor(*this, x.operand_);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
switch (x.sign)
{
case '-': program.op(op_neg); break;
case '+': break;
- default: BOOST_ASSERT(0); break;
+ default: BOOST_ASSERT(0); return false;
}
+ return true;
}
- void compiler::operator()(ast::expression const& x) const
+ bool compiler::operator()(ast::expression const& x) const
{
- boost::apply_visitor(*this, x.first);
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
BOOST_FOREACH(ast::operation const& oper, x.rest)
{
- (*this)(oper);
+ if (!(*this)(oper))
+ return false;
}
+ return true;
}
- void compiler::operator()(ast::assignment const& x) const
+ bool compiler::operator()(ast::assignment const& x) const
{
- (*this)(x.rhs);
+ if (!(*this)(x.rhs))
+ return false;
int const* p = program.find_var(x.lhs.name);
if (p == 0)
{
- // $$$ undefined variable throw exception
- std::cout << "undefined variable: " << x.lhs.name << std::endl;
+ std::cout << x.lhs.id << std::endl;
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
}
program.op(op_store, *p);
+ return true;
}
- void compiler::operator()(ast::variable_declaration const& x) const
+ bool compiler::operator()(ast::variable_declaration const& x) const
{
int const* p = program.find_var(x.assign.lhs.name);
if (p != 0)
{
- // $$$ duplicate variable throw exception
- std::cout << "duplicate variable: " << x.assign.lhs.name << std::endl;
+ std::cout << x.assign.lhs.id << std::endl;
+ error_handler(x.assign.lhs.id, "Duplicate variable: " + x.assign.lhs.name);
+ return false;
}
- program.add_var(x.assign.lhs.name);
- (*this)(x.assign);
+ bool r = (*this)(x.assign.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ program.add_var(x.assign.lhs.name);
+ program.op(op_store, *program.find_var(x.assign.lhs.name));
+ }
+ return r;
}
- void compiler::operator()(ast::statement const& x) const
+ bool compiler::operator()(ast::statement const& x) const
{
typedef
boost::variant<
@@ -135,22 +152,20 @@
ast::assignment>
statement;
- try
- {
- program.clear();
+ program.clear();
- // op_adstk 0 for now. we'll know how many variables we'll have later
- program.op(op_adstk, 0);
- BOOST_FOREACH(statement const& s, x)
+ // op_adstk 0 for now. we'll know how many variables we'll have later
+ program.op(op_adstk, 0);
+ BOOST_FOREACH(statement const& s, x)
+ {
+ if (!boost::apply_visitor(*this, s))
{
- boost::apply_visitor(*this, s);
+ program.clear();
+ return false;
}
- program[1] = program.nvars(); // now store the actual number of variables
- }
- catch(...)
- {
- program.clear();
}
+ program[1] = program.nvars(); // now store the actual number of variables
+ return true;
}
}
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 01:06:50 EST (Mon, 28 Feb 2011)
@@ -8,8 +8,13 @@
#define BOOST_SPIRIT_CALC7_COMPILER_HPP
#include "ast.hpp"
+#include "error_handler.hpp"
#include <vector>
#include <map>
+#include <boost/function.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
namespace client
{
@@ -44,22 +49,33 @@
///////////////////////////////////////////////////////////////////////////
struct compiler
{
- typedef void result_type;
+ typedef bool result_type;
- compiler(client::program& program)
- : program(program) {}
-
- void operator()(ast::nil) const { BOOST_ASSERT(0); }
- void operator()(unsigned int x) const;
- void operator()(ast::variable const& x) const;
- void operator()(ast::operation const& x) const;
- void operator()(ast::signed_ const& x) const;
- void operator()(ast::expression const& x) const;
- void operator()(ast::assignment const& x) const;
- void operator()(ast::variable_declaration const& x) const;
- void operator()(ast::statement const& x) const;
+ template <typename IterList, typename Iterator>
+ compiler(client::program& program, IterList const& iters, Iterator last)
+ : program(program)
+ {
+ using boost::phoenix::arg_names::_1;
+ using boost::phoenix::arg_names::_2;
+ using boost::phoenix::cref;
+ error_handler = client::error_handler("Error! ", _2, cref(iters)[_1], last);
+ }
+
+ bool operator()(ast::nil) const { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x) const;
+ bool operator()(ast::variable const& x) const;
+ bool operator()(ast::operation const& x) const;
+ bool operator()(ast::signed_ const& x) const;
+ bool operator()(ast::expression const& x) const;
+ bool operator()(ast::assignment const& x) const;
+ bool operator()(ast::variable_declaration const& x) const;
+ bool operator()(ast::statement const& x) const;
client::program& program;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
};
}
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 01:06:50 EST (Mon, 28 Feb 2011)
@@ -7,13 +7,12 @@
#if !defined(BOOST_SPIRIT_CALC7_ERROR_HANDLER_HPP)
#define BOOST_SPIRIT_CALC7_ERROR_HANDLER_HPP
-#include <boost/spirit/include/support_info.hpp>
#include <iostream>
#include <string>
+#include <boost/spirit/include/phoenix_function.hpp>
namespace client
{
- namespace qi = boost::spirit::qi;
using boost::phoenix::function;
///////////////////////////////////////////////////////////////////////////////
@@ -21,23 +20,32 @@
///////////////////////////////////////////////////////////////////////////////
struct error_handler_
{
- template <typename, typename, typename>
+ template <typename, typename, typename, typename>
struct result { typedef void type; };
- template <typename Iterator>
- void operator()(
- boost::spirit::qi::info const& what
+ template <typename Message, typename What, typename Iterator>
+ void operator()(Message const& message, What const& what
, Iterator err_pos, Iterator last) const
{
std::cout
- << "Error! Expecting "
- << what // what failed?
+ << message
+ << what
<< " here: \""
- << std::string(err_pos, last) // iterators to error-pos, end
+ << get_line(err_pos, last)
<< "\""
<< std::endl
;
}
+
+ template <typename Iterator>
+ std::string get_line(Iterator err_pos, Iterator last) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
};
boost::phoenix::function<error_handler_> const
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 01:06:50 EST (Mon, 28 Feb 2011)
@@ -14,12 +14,14 @@
expression<Iterator>::expression()
: expression::base_type(expr)
{
- qi::char_type char_;
- qi::uint_type uint_;
- qi::_val_type _val;
+ qi::_1_type _1;
qi::_2_type _2;
qi::_3_type _3;
qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
qi::raw_type raw;
qi::lexeme_type lexeme;
qi::alpha_type alpha;
@@ -74,13 +76,13 @@
);
// Error handling: on error in expr, call error_handler.
- on_error<fail>(expr, error_handler(_4, _3, _2));
+ on_error<fail>(expr, error_handler("Error! Expecting ", _4, _3, _2));
// 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, _3));
+ on_success(primary_expr, annotation(_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 01:06:50 EST (Mon, 28 Feb 2011)
@@ -47,34 +47,37 @@
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); // Our compiler
+ 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
boost::spirit::ascii::space_type space;
- bool r = phrase_parse(iter, end, parser, space, ast);
+ bool success = phrase_parse(iter, end, parser, space, ast);
- if (r && iter == end)
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ success = compile(ast);
+ else
+ std::cout << "Parsing failed\n";
+
+ if (success)
{
- std::cout << "-------------------------\n";
- std::cout << "Parsing succeeded\n";
- compile(ast);
+ std::cout << "Success\n";
vm.execute(program());
std::cout << "Results------------------\n\n";
program.print_variables(vm.get_stack());
- std::cout << "-------------------------\n\n";
}
else
{
- std::string rest(iter, end);
- std::cout << "-------------------------\n";
- std::cout << "Parsing failed\n";
- std::cout << "-------------------------\n";
+ std::cout << "Compiling failed\n";
}
+ std::cout << "-------------------------\n\n";
return 0;
}
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 01:06:50 EST (Mon, 28 Feb 2011)
@@ -14,10 +14,12 @@
statement<Iterator>::statement()
: statement::base_type(start)
{
- qi::_val_type _val;
+ qi::_1_type _1;
qi::_2_type _2;
qi::_3_type _3;
qi::_4_type _4;
+
+ qi::_val_type _val;
qi::raw_type raw;
qi::lexeme_type lexeme;
qi::alpha_type alpha;
@@ -56,13 +58,13 @@
);
// Error handling: on error in start, call error_handler.
- on_error<fail>(start, error_handler(_4, _3, _2));
+ 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, _3));
+ on_success(assignment, annotation(_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