#include "copyright.h"
#ifndef TREE_H
#define TREE_H
#include "utils.h"
#include <iostream>
class tree_node {
protected:
int line_number; public:
tree_node();
virtual tree_node *copy() = 0;
virtual void dump(std::ostream &stream, int n) = 0;
int get_line_number();
tree_node *set(tree_node *);
virtual ~tree_node() {}
};
template <class Elem> class list_node;
template <class Elem> class list_node_iterator {
list_node<Elem> *list;
int index;
public:
list_node_iterator(list_node<Elem> *list_) : list(list_), index(0) {}
list_node_iterator(list_node<Elem> *list_, int index_)
: list(list_), index(index_) {}
list_node_iterator<Elem> &operator++() {
++index;
return *this;
}
Elem operator*() const { return list->nth(index); }
bool operator!=(const list_node_iterator<Elem> &rhs) const {
return index != rhs.index;
}
};
template <class Elem> class list_node : public tree_node {
public:
tree_node *copy() { return copy_list(); }
Elem nth(int n);
int first() { return 0; }
int next(int n) { return n + 1; }
int more(int n) { return (n < len()); }
virtual list_node<Elem> *copy_list() = 0;
virtual int len() = 0;
virtual Elem nth_length(int n, int &len) = 0;
static list_node<Elem> *nil();
static list_node<Elem> *single(Elem);
static list_node<Elem> *append(list_node<Elem> *l1, list_node<Elem> *l2);
};
template <class Elem> list_node_iterator<Elem> begin(list_node<Elem> &list) {
return list_node_iterator<Elem>(&list);
}
template <class Elem> list_node_iterator<Elem> end(list_node<Elem> &list) {
return list_node_iterator<Elem>(&list, list.len());
}
template <class Elem> list_node_iterator<Elem> begin(list_node<Elem> *list) {
return list_node_iterator<Elem>(list);
}
template <class Elem> list_node_iterator<Elem> end(list_node<Elem> *list) {
return list_node_iterator<Elem>(list, list->len());
}
template <class Elem> class nil_node : public list_node<Elem> {
public:
list_node<Elem> *copy_list();
int len();
Elem nth_length(int n, int &len);
void dump(std::ostream &stream, int n);
};
template <class Elem> class single_list_node : public list_node<Elem> {
Elem elem;
public:
single_list_node(Elem t) { elem = t; }
list_node<Elem> *copy_list();
int len();
Elem nth_length(int n, int &len);
void dump(std::ostream &stream, int n);
};
template <class Elem> class append_node : public list_node<Elem> {
private:
list_node<Elem> *some, *rest;
public:
append_node(list_node<Elem> *l1, list_node<Elem> *l2) {
some = l1;
rest = l2;
}
list_node<Elem> *copy_list();
int len();
Elem nth_length(int n, int &len);
void dump(std::ostream &stream, int n);
};
template <class Elem> single_list_node<Elem> *list(Elem x);
template <class Elem> append_node<Elem> *cons(Elem x, list_node<Elem> *l);
template <class Elem> append_node<Elem> *xcons(list_node<Elem> *l, Elem x);
template <class Elem> list_node<Elem> *list_node<Elem>::nil() {
return new nil_node<Elem>();
}
template <class Elem> list_node<Elem> *list_node<Elem>::single(Elem e) {
return new single_list_node<Elem>(e);
}
template <class Elem>
list_node<Elem> *list_node<Elem>::append(list_node<Elem> *l1,
list_node<Elem> *l2) {
return new append_node<Elem>(l1, l2);
}
template <class Elem> Elem list_node<Elem>::nth(int n) {
int len;
Elem tmp = nth_length(n, len);
if (tmp) {
return tmp;
}
throw std::runtime_error("nth: outside the range of the list");
}
template <class Elem> list_node<Elem> *nil_node<Elem>::copy_list() {
return new nil_node<Elem>();
}
template <class Elem> int nil_node<Elem>::len() { return 0; }
template <class Elem> Elem nil_node<Elem>::nth_length(int, int &len) {
len = 0;
return NULL;
}
template <class Elem> void nil_node<Elem>::dump(std::ostream &stream, int n) {
stream << pad(n) << "(nil)\n";
}
template <class Elem> list_node<Elem> *single_list_node<Elem>::copy_list() {
return new single_list_node<Elem>((Elem)elem->copy());
}
template <class Elem> int single_list_node<Elem>::len() { return 1; }
template <class Elem> Elem single_list_node<Elem>::nth_length(int n, int &len) {
len = 1;
if (n)
return NULL;
else
return elem;
}
template <class Elem>
void single_list_node<Elem>::dump(std::ostream &stream, int n) {
elem->dump(stream, n);
}
template <class Elem> list_node<Elem> *append_node<Elem>::copy_list() {
return new append_node<Elem>(some->copy_list(), rest->copy_list());
}
template <class Elem> int append_node<Elem>::len() {
return some->len() + rest->len();
}
template <class Elem> Elem append_node<Elem>::nth_length(int n, int &len) {
int rlen;
Elem tmp = some->nth_length(n, len);
if (!tmp) {
tmp = rest->nth_length(n - len, rlen);
len += rlen;
}
return tmp;
}
template <class Elem>
void append_node<Elem>::dump(std::ostream &stream, int n) {
int i, size;
size = len();
stream << pad(n) << "list\n";
for (i = 0; i < size; i++)
this->nth(i)->dump(stream, n + 2);
stream << pad(n) << "(end_of_list)\n";
}
template <class Elem> single_list_node<Elem> *list(Elem x) {
return new single_list_node<Elem>(x);
}
template <class Elem> append_node<Elem> *cons(Elem x, list_node<Elem> *l) {
return new append_node<Elem>(list(x), l);
}
template <class Elem> append_node<Elem> *xcons(list_node<Elem> *l, Elem x) {
return new append_node<Elem>(l, list(x));
}
#endif