// node.hpp
// Copyright (c) 2007-2009 Ben Hanson (http://www.benhanson.net/)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_LEXER_NODE_HPP
#define BOOST_LEXER_NODE_HPP

#include <assert.h>
#include "../../containers/ptr_vector.hpp"
#include "../../runtime_error.hpp"
#include "../../size_t.hpp"
#include <stack>
#include <vector>

namespace boost
{
namespace lexer
{
namespace detail
{
class node
{
public:
    enum type {LEAF, SEQUENCE, SELECTION, ITERATION, END};

    typedef std::stack<bool> bool_stack;
    typedef std::stack<node *> node_stack;
    // stack and vector not owner of node pointers
    typedef std::stack<const node *> const_node_stack;
    typedef std::vector<node *> node_vector;
    typedef ptr_vector<node> node_ptr_vector;

    node () :
        _nullable (false)
    {
    }

    node (const bool nullable_) :
        _nullable (nullable_)
    {
    }

    virtual ~node ()
    {
    }

    bool nullable () const
    {
        return _nullable;
    }

    void append_firstpos (node_vector &firstpos_) const
    {
        firstpos_.insert (firstpos_.end (),
            _firstpos.begin (), _firstpos.end ());
    }

    void append_lastpos (node_vector &lastpos_) const
    {
        lastpos_.insert (lastpos_.end (),
            _lastpos.begin (), _lastpos.end ());
    }

    virtual void append_followpos (const node_vector &/*followpos_*/)
    {
        throw runtime_error ("Internal error node::append_followpos()");
    }

    node *copy (node_ptr_vector &node_ptr_vector_) const
    {
        node *new_root_ = 0;
        const_node_stack node_stack_;
        bool_stack perform_op_stack_;
        bool down_ = true;
        node_stack new_node_stack_;

        node_stack_.push (this);

        while (!node_stack_.empty ())
        {
            while (down_)
            {
                down_ = node_stack_.top ()->traverse (node_stack_,
                    perform_op_stack_);
            }

            while (!down_ && !node_stack_.empty ())
            {
                const node *top_ = node_stack_.top ();

                top_->copy_node (node_ptr_vector_, new_node_stack_,
                    perform_op_stack_, down_);

                if (!down_) node_stack_.pop ();
            }
        }

        assert (new_node_stack_.size () == 1);
        new_root_ = new_node_stack_.top ();
        new_node_stack_.pop ();
        return new_root_;
    }

    virtual type what_type () const = 0;

    virtual bool traverse (const_node_stack &node_stack_,
        bool_stack &perform_op_stack_) const = 0;

    node_vector &firstpos ()
    {
        return _firstpos;
    }

    const node_vector &firstpos () const
    {
        return _firstpos;
    }

    // _lastpos modified externally, so not const &
    node_vector &lastpos ()
    {
        return _lastpos;
    }

    virtual bool end_state () const
    {
        return false;
    }

    virtual std::size_t id () const
    {
        throw runtime_error ("Internal error node::id()");
    }

    virtual std::size_t unique_id () const
    {
        throw runtime_error ("Internal error node::unique_id()");
    }

    virtual std::size_t lexer_state () const
    {
        throw runtime_error ("Internal error node::state()");
    }

    virtual std::size_t token () const
    {
        throw runtime_error ("Internal error node::token()");
    }

    virtual void greedy (const bool /*greedy_*/)
    {
        throw runtime_error ("Internal error node::token(bool)");
    }

    virtual bool greedy () const
    {
        throw runtime_error ("Internal error node::token()");
    }

    virtual const node_vector &followpos () const
    {
        throw runtime_error ("Internal error node::followpos()");
    }

    virtual node_vector &followpos ()
    {
        throw runtime_error ("Internal error node::followpos()");
    }

protected:
    const bool _nullable;
    node_vector _firstpos;
    node_vector _lastpos;

    virtual void copy_node (node_ptr_vector &node_ptr_vector_,
        node_stack &new_node_stack_, bool_stack &perform_op_stack_,
        bool &down_) const = 0;

private:
    node (node const &); // No copy construction.
    node &operator = (node const &); // No assignment.
};
}
}
}

#endif
