requirements.hpp 2.94 KB
Newer Older
adelmann's avatar
adelmann committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*=============================================================================
    Adapted from boost spirit mini_c example.

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(REQUIREMENTS_HPP)
#define REQUIREMENTS_HPP

#include "ast.hpp"
#include "error_handler.hpp"
#include <set>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

namespace client { namespace code_gen
{
    struct requirements
    {
        typedef bool result_type;

        template <typename ErrorHandler>
        requirements(ErrorHandler& error_handler_)
        {
            using namespace boost::phoenix::arg_names;
            namespace phx = boost::phoenix;
            using boost::phoenix::function;

            error_handler = function<ErrorHandler>(error_handler_)(
33
                  std::string("Error! "), _2, phx::cref(error_handler_.iters)[_1]);
adelmann's avatar
adelmann committed
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
        }

        bool operator()(ast::nil) { BOOST_ASSERT(0); return false; }
        bool operator()(unsigned int x) { return true; }
        bool operator()(double x) { return true; }
        bool operator()(bool x) { return true; }
        bool operator()(ast::quoted_string const &x) { return true; }

        bool operator()(ast::operation const& x) {
            if (!boost::apply_visitor(*this, x.operand_))
                return false;
            return true;
        }

        bool operator()(ast::unary const& x) {
            if (!boost::apply_visitor(*this, x.operand_))
                return false;
            return true;
        }

        bool operator()(ast::identifier const& x) {
            variables_.insert(x.name);

            return true;
        }

        bool operator()(ast::function_call const& x) {
            functions_.insert(x.function_name.name);

63
            for(ast::function_call_argument const& arg: x.args) {
adelmann's avatar
adelmann committed
64 65 66 67 68 69 70 71 72 73 74 75 76
                if (!boost::apply_visitor(*this, arg))
                    return false;
                //if (!(*this)(arg))
                    //return false;
            }
            return true;
        }

        bool operator()(ast::expression const& x) {

            if (!boost::apply_visitor(*this, x.first))
                return false;

77
            for(ast::operation const& oper: x.rest) {
adelmann's avatar
adelmann committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
                if (!(*this)(oper))
                    return false;
        }

        return true;
    }

    std::set<std::string> variables() { return variables_; }
    std::set<std::string> functions() { return functions_; }

    private:

        boost::function<
            void(int tag, std::string const& what)>
        error_handler;

        std::set<std::string> variables_;
        std::set<std::string> functions_;
    };
}}

99
#endif