|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r61348 - in trunk/libs/spirit/example/scheme: input scheme support test/scheme utree utree/detail
From: joel_at_[hidden]
Date: 2010-04-18 01:24:47
Author: djowel
Date: 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
New Revision: 61348
URL: http://svn.boost.org/trac/boost/changeset/61348
Log:
compiler error handling/reporting
Text files modified:
trunk/libs/spirit/example/scheme/input/error_handler.hpp | 18 ---
trunk/libs/spirit/example/scheme/input/sexpr.hpp | 30 ++++++
trunk/libs/spirit/example/scheme/scheme/compiler.hpp | 172 ++++++++++++++++++++++++++++-----------
trunk/libs/spirit/example/scheme/support/line_pos_iterator.hpp | 2
trunk/libs/spirit/example/scheme/test/scheme/scheme_test1.cpp | 2
trunk/libs/spirit/example/scheme/utree/detail/utree_detail1.hpp | 1
trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp | 14 +++
trunk/libs/spirit/example/scheme/utree/operators.hpp | 18 ++--
trunk/libs/spirit/example/scheme/utree/utree.hpp | 5
9 files changed, 180 insertions(+), 82 deletions(-)
Modified: trunk/libs/spirit/example/scheme/input/error_handler.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/input/error_handler.hpp (original)
+++ trunk/libs/spirit/example/scheme/input/error_handler.hpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -36,23 +36,9 @@
std::cerr << source_file;
if (line != -1)
- {
- if (source_file != "")
- std::cerr << '(' << line << ')';
- else
- std::cerr << '(' << line << ')';
- }
+ std::cerr << '(' << line << ')';
- std::cerr << " : Error! Expecting " << what;
- //~ if (line != -1)
- //~ {
- //~ std::size_t col = get_column(first, err_pos, 4);
- //~ std::cerr << " near column " << col << std::endl;
- //~ }
- //~ else
- //~ {
- std::cerr << std::endl;
- //~ }
+ std::cerr << " : Error! Expecting " << what << std::endl;
}
};
}}
Modified: trunk/libs/spirit/example/scheme/input/sexpr.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/input/sexpr.hpp (original)
+++ trunk/libs/spirit/example/scheme/input/sexpr.hpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -40,10 +40,15 @@
using boost::spirit::qi::lexeme;
using boost::spirit::qi::on_error;
using boost::spirit::qi::fail;
+ using boost::spirit::qi::_val;
using boost::spirit::qi::_1;
using boost::spirit::qi::_2;
using boost::spirit::qi::_3;
using boost::spirit::qi::_4;
+ using boost::spirit::qi::locals;
+ using boost::spirit::qi::raw;
+ using boost::spirit::qi::eps;
+ using boost::spirit::qi::omit;
using boost::spirit::info;
typedef boost::uint32_t uchar; // a unicode code point
@@ -62,6 +67,23 @@
rule<Iterator> start;
};
+ struct save_line_pos_
+ {
+ template <typename Utree, typename Range>
+ struct result { typedef void type; };
+
+ template <typename Range>
+ void operator()(utree& ast, Range const& rng) const
+ {
+ int n = get_line(rng.begin());
+ BOOST_ASSERT(n <= std::numeric_limits<short>::max());
+ ast.tag(n);
+ }
+ };
+
+ boost::phoenix::function<save_line_pos_> const
+ save_line_pos = save_line_pos_();
+
template <typename Iterator,
typename ErrorHandler = input::error_handler<Iterator> >
struct sexpr : grammar<Iterator, sexpr_white_space<Iterator>, utree()>
@@ -75,7 +97,11 @@
start = element.alias();
element = atom | list;
- list = '(' > *element > ')';
+ list %= '('
+ > omit[raw[eps] [save_line_pos(_val, _1)]]
+ > *element
+ > ')'
+ ;
atom = strict_double
| integer
@@ -106,7 +132,7 @@
}
rule<Iterator, sexpr_white_space<Iterator>, utree()>
- start, list, element;
+ start, element, list;
rule<Iterator, int()> integer;
rule<Iterator, utree()> atom;
rule<Iterator, utf8_symbol()> symbol;
Modified: trunk/libs/spirit/example/scheme/scheme/compiler.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/scheme/compiler.hpp (original)
+++ trunk/libs/spirit/example/scheme/scheme/compiler.hpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -9,8 +9,9 @@
#include <vector>
#include <map>
-#include <boost/bind.hpp>
+#include <exception>
+#include <boost/bind.hpp>
#include <scheme/intrinsics.hpp>
#include <scheme/interpreter.hpp>
#include <input/parse_sexpr.hpp>
@@ -18,6 +19,35 @@
namespace scheme
{
///////////////////////////////////////////////////////////////////////////////
+// Exceptions
+///////////////////////////////////////////////////////////////////////////////
+ struct scheme_exception : std::exception {};
+
+ struct identifier_not_found : scheme_exception
+ {
+ virtual const char* what() const throw()
+ {
+ return "scheme: Identifier not found";
+ }
+ };
+
+ struct duplicate_identifier : scheme_exception
+ {
+ virtual const char* what() const throw()
+ {
+ return "scheme: Duplicate identifier";
+ }
+ };
+
+ struct unknown_expression : scheme_exception
+ {
+ virtual const char* what() const throw()
+ {
+ return "scheme: Unknown_expression";
+ }
+ };
+
+///////////////////////////////////////////////////////////////////////////////
// The environment
///////////////////////////////////////////////////////////////////////////////
typedef boost::function<function(actor_list const&)> compiled_function;
@@ -32,8 +62,8 @@
template <typename Function>
void define(std::string const& name, Function const& f)
{
- // $$$ use exceptions here? $$$
- BOOST_ASSERT(definitions.find(name) == definitions.end());
+ if (definitions.find(name) != definitions.end())
+ throw duplicate_identifier();
definitions[name] = compiled_function(f);
}
@@ -60,7 +90,11 @@
// The compiler
///////////////////////////////////////////////////////////////////////////////
function compile(
- utree const& ast, environment& env, actor_list& fragments);
+ utree const& ast,
+ environment& env,
+ actor_list& fragments,
+ int parent_line,
+ std::string const& source_file = "");
struct external_function : composite<external_function>
{
@@ -82,9 +116,16 @@
typedef function result_type;
environment& env;
actor_list& fragments;
+ int line;
+ std::string source_file;
- compiler(environment& env, actor_list& fragments)
- : env(env), fragments(fragments)
+ compiler(
+ environment& env,
+ actor_list& fragments,
+ int line,
+ std::string const& source_file = "")
+ : env(env), fragments(fragments),
+ line(line), source_file(source_file)
{
}
@@ -107,8 +148,7 @@
actor_list flist;
return (*mf)(flist);
}
- // $$$ throw? $$$
- BOOST_ASSERT(false);
+ throw identifier_not_found();
return function();
}
@@ -119,7 +159,7 @@
environment local_env(&this->env);
for (std::size_t i = 0; i < args.size(); ++i)
local_env.define(args[i], boost::bind(arg, i));
- return compile(body, local_env, fragments);
+ return compile(body, local_env, fragments, line, source_file);
}
function define_function(
@@ -137,55 +177,71 @@
template <typename Iterator>
function operator()(boost::iterator_range<Iterator> const& range) const
{
- std::string name(get_symbol(*range.begin()));
-
- if (name == "define")
+ try
{
- std::string fname;
- std::vector<std::string> args;
+ std::string name(get_symbol(*range.begin()));
- Iterator i = range.begin(); ++i;
- if (i->which() == utree_type::list_type)
+ if (name == "define")
{
- // (define (f x) ...body...)
- utree const& decl = *i++;
- Iterator di = decl.begin();
- fname = get_symbol(*di++);
- while (di != decl.end())
- args.push_back(get_symbol(*di++));
+ std::string fname;
+ std::vector<std::string> args;
+
+ Iterator i = range.begin(); ++i;
+ if (i->which() == utree_type::list_type)
+ {
+ // (define (f x) ...body...)
+ utree const& decl = *i++;
+ Iterator di = decl.begin();
+ fname = get_symbol(*di++);
+ while (di != decl.end())
+ args.push_back(get_symbol(*di++));
+ }
+ else
+ {
+ // (define f ...body...)
+ fname = get_symbol(*i++);
+ }
+
+ return define_function(fname, args, *i);
}
- else
+
+ if (name == "lambda")
{
- // (define f ...body...)
- fname = get_symbol(*i++);
+ // (lambda (x) ...body...)
+ Iterator i = range.begin(); ++i;
+ utree const& arg_names = *i++;
+ Iterator ai = arg_names.begin();
+ std::vector<std::string> args;
+ while (ai != arg_names.end())
+ args.push_back(get_symbol(*ai++));
+ return make_lambda(args, *i);
}
- return define_function(fname, args, *i);
- }
+ if (compiled_function* mf = env.find(name))
+ {
+ actor_list flist;
+ Iterator i = range.begin(); ++i;
+ for (; i != range.end(); ++i)
+ flist.push_back(
+ compile(*i, env, fragments, line, source_file));
+ return (*mf)(flist);
+ }
- if (name == "lambda")
- {
- // (lambda (x) ...body...)
- Iterator i = range.begin(); ++i;
- utree const& arg_names = *i++;
- Iterator ai = arg_names.begin();
- std::vector<std::string> args;
- while (ai != arg_names.end())
- args.push_back(get_symbol(*ai++));
- return make_lambda(args, *i);
+ throw unknown_expression();
}
- if (compiled_function* mf = env.find(name))
+ catch (scheme_exception const& x)
{
- actor_list flist;
- Iterator i = range.begin(); ++i;
- for (; i != range.end(); ++i)
- flist.push_back(compile(*i, env, fragments));
- return (*mf)(flist);
+ if (source_file != "")
+ std::cerr << source_file;
+
+ if (line != -1)
+ std::cerr << '(' << line << ')';
+
+ std::cerr << " : Error! " << x.what() << std::endl;
}
- BOOST_ASSERT(false);
- return function(); // $$$ implement me $$$
+ return function();
}
static std::string get_symbol(utree const& s)
@@ -196,20 +252,31 @@
};
inline function compile(
- utree const& ast, environment& env, actor_list& fragments)
+ utree const& ast,
+ environment& env,
+ actor_list& fragments,
+ int parent_line,
+ std::string const& source_file)
{
- return utree::visit(ast, compiler(env, fragments));
+ int line = (ast.which() == utree_type::list_type)
+ ? ast.tag() : parent_line;
+ return utree::visit(ast,
+ compiler(env, fragments, line, source_file));
}
void compile_all(
utree const& ast,
environment& env,
actor_list& results,
- actor_list& fragments)
+ actor_list& fragments,
+ std::string const& source_file = "")
{
+ int line = (ast.which() == utree_type::list_type)
+ ? ast.tag() : 1;
BOOST_FOREACH(utree const& program, ast)
{
- scheme::function f = compile(program, env, fragments);
+ scheme::function
+ f = compile(program, env, fragments, line, source_file);
results.push_back(f);
}
}
@@ -230,14 +297,17 @@
struct interpreter : actor<interpreter>
{
template <typename Source>
- interpreter(Source& in, environment* outer = 0)
+ interpreter(
+ Source& in,
+ std::string const& source_file = "",
+ environment* outer = 0)
{
if (outer == 0)
build_basic_environment(env);
if (input::parse_sexpr_list(in, program))
{
- compile_all(program, env, flist, fragments);
+ compile_all(program, env, flist, fragments, source_file);
}
else
{
Modified: trunk/libs/spirit/example/scheme/support/line_pos_iterator.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/support/line_pos_iterator.hpp (original)
+++ trunk/libs/spirit/example/scheme/support/line_pos_iterator.hpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -17,7 +17,7 @@
// adapter only stores the current line number, nothing else. Unlike
// spirit classic's position_iterator, it does not store the column
// number and does not need an end iterator. The current column can be
- // computed, if needed. Some utilities line oriented are provided
+ // computed, if needed. Some line oriented utilities are provided
// including computation of the current column.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator>
Modified: trunk/libs/spirit/example/scheme/test/scheme/scheme_test1.cpp
==============================================================================
--- trunk/libs/spirit/example/scheme/test/scheme/scheme_test1.cpp (original)
+++ trunk/libs/spirit/example/scheme/test/scheme/scheme_test1.cpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -65,7 +65,7 @@
scheme::build_basic_environment(env);
scheme::actor_list fragments;
scheme::actor_list flist;
- compile_all(program, env, flist, fragments);
+ compile_all(program, env, flist, fragments, filename);
scheme::actor_list::iterator i = flist.begin();
Modified: trunk/libs/spirit/example/scheme/test/scheme/scheme_test1.scm
==============================================================================
Modified: trunk/libs/spirit/example/scheme/utree/detail/utree_detail1.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree/detail/utree_detail1.hpp (original)
+++ trunk/libs/spirit/example/scheme/utree/detail/utree_detail1.hpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -53,6 +53,7 @@
node* first;
node* last;
std::size_t size;
+ short tag;
};
///////////////////////////////////////////////////////////////////////////
Modified: trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp (original)
+++ trunk/libs/spirit/example/scheme/utree/detail/utree_detail2.hpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -258,6 +258,7 @@
first = last = 0;
size = 0;
node* p = other.first;
+ tag = other.tag;
while (p != 0)
{
push_back(p->val);
@@ -1069,10 +1070,21 @@
{
return (get_type() == type::reference_type) ? *p : *this;
}
+
+ inline short utree::tag() const
+ {
+ BOOST_ASSERT(get_type() == type::list_type);
+ return l.tag;
+ }
+
+ inline void utree::tag(short tag)
+ {
+ ensure_list_type();
+ l.tag = tag;
+ }
}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
-
#endif
Modified: trunk/libs/spirit/example/scheme/utree/operators.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree/operators.hpp (original)
+++ trunk/libs/spirit/example/scheme/utree/operators.hpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -150,38 +150,38 @@
// struct utree_print
// {
// typedef void result_type;
-//
+//
// std::ostream& out;
// utree_print(std::ostream& out) : out(out) {}
-//
+//
// void operator()(scheme::nil) const
// {
// out << "nil";
// }
-//
+//
// template <typename T>
// void operator()(T val) const
// {
// out << val;
// }
-//
+//
// void operator()(bool b) const
// {
// out << (b ? "true" : "false");
// }
-//
+//
// void operator()(binary_range const& b) const
// {
// out << "b";
// out.width(2);
// out.fill('0');
-//
+//
// typedef binary_range::const_iterator iterator;
// for (iterator i = b.begin(); i != b.end(); ++i)
// out << std::hex << int((unsigned char)*i);
// out << std::dec;
// }
-//
+//
// void operator()(utf8_string_range const& str) const
// {
// typedef utf8_string_range::const_iterator iterator;
@@ -191,7 +191,7 @@
// out << *i;
// out << '"';
// }
-//
+//
// void operator()(utf8_symbol_range const& str) const
// {
// typedef utf8_symbol_range::const_iterator iterator;
@@ -199,7 +199,7 @@
// for (; i != str.end(); ++i)
// out << *i;
// }
-//
+//
// template <typename Iterator>
// void operator()(boost::iterator_range<Iterator> const& range) const
// {
Modified: trunk/libs/spirit/example/scheme/utree/utree.hpp
==============================================================================
--- trunk/libs/spirit/example/scheme/utree/utree.hpp (original)
+++ trunk/libs/spirit/example/scheme/utree/utree.hpp 2010-04-18 01:24:45 EDT (Sun, 18 Apr 2010)
@@ -153,7 +153,7 @@
typedef utree value_type;
typedef detail::list::node_iterator<utree> iterator;
typedef detail::list::node_iterator<utree const> const_iterator;
- typedef detail::list::node_iterator<boost::reference_wrapper<utree> >
+ typedef detail::list::node_iterator<boost::reference_wrapper<utree> >
ref_iterator;
typedef utree& reference;
typedef utree const& const_reference;
@@ -272,6 +272,9 @@
utree& deref();
utree const& deref() const;
+ short tag() const;
+ void tag(short tag);
+
private:
typedef utree_type type;
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