#ifndef REPETITION_H
#define REPETITION_H

typedef Universal* ent;
typedef int(*PFC) (ent a,ent b);


class NonEmptyList : public Universal {
  friend class repetition;
  friend class repetition_iterator;
  NonEmptyList *next;
  ent e;
  NonEmptyList (ent a, NonEmptyList *p) 
    { e = a; next = p;}
  };

class repetition : public Universal {
  friend class repetition_iterator;
 private:
  NonEmptyList *last;
  static const char *type;
 public:
  static const char *get_formal_type() { return type; }
  virtual const char *get_type() const { return type; }
  int number_of_parts() const;
  Universal* get_data_member(int index) const;
  int insert(ent a);
  int append(ent a);
  int list_length() const;
  int empty()  const { return (int)last->e; }
  ent get();
  ent car();
  int member(ent a,PFC f);
  NonEmptyList* remove(ent a,PFC f);
  void dremove(ent a,PFC f);
  //    NonEmptyList* cdr();
  NonEmptyList* lisp_append(NonEmptyList* p);
  ent n_th(int a);
  ent lastexp();
  int conc(ent a, ent b);
  void concatenate( repetition* );
  repetition() { last = new NonEmptyList(0,0); last->next = last; }
  repetition(ent a) { last = new NonEmptyList(a,0);
		      last->next = new NonEmptyList(0,last); }
  virtual ~repetition();
  
  Universal* g_copy() const;
  char* g_code( int&,ofstream& ) const;
};
  

class repetition_iterator {
  NonEmptyList *ce; /* current element*/
  repetition *cs;   /* list */
  public:
    repetition_iterator(const repetition &s)
      { cs = (repetition*) &s;
	ce = cs->last->next;
	if( !ce->next->e )
	  ce = 0;
      }
    ent operator()() {
      return ((!ce) ? 0
	            : ((!(ce = ce->next)->e) ? (ce = 0) : ce->e));
                                      // Law violation; friend documents
    }
};

#include "rep-macro.h"

#endif

