#ifndef LIST_H
#define LIST_H

#include <string>

class List;
class Atom;

class ListItem {
public:
	virtual bool atomic()=0;
	virtual std::string getString()=0;
	virtual int getInt()=0;
	virtual double getDouble()=0;
	virtual List *getList()=0;
	virtual std::string firstString()=0;
	virtual List *firstList()=0;
	virtual void findAndReplace(std::string find, std::string replace)=0;
private:
};

class List : public ListItem {
public:
	List(int lineNumber = -1);
	List(List *list);
	~List();
	bool atomic() {return false;}
	
	ListItem *first();
	List *rest();
	
	std::string getString();
	int getInt();
	double getDouble();

    std::string getRestString();
	
	List* copy();

	List *cons(ListItem *first);
	List *snoc(ListItem *last);
    
	void findAndReplace(std::string find, std::string replace);

	bool empty() {return (!_item);}
	
	List *getList() {return this;}
	
	std::string firstString();
	int firstInt();
	double firstDouble();
	
	List *firstList();
protected:
//	std::list<ListItem*> _list;
	ListItem *_item;
	List *_next;
	int _lineNumber;
};

class Atom : public ListItem {
public:
	Atom(std::string aString, int lineNumber = -1);
	Atom(int anInt, int lineNumber = -1);
	Atom(double aDouble, int lineNumber = -1);
	Atom(Atom *atom);

	bool atomic() {return true;}
	std::string getString() {return _string;}
	int getInt();
	double getDouble();
	List *getList();
	std::string firstString();
	List *firstList();

	void findAndReplace(std::string find, std::string replace);
protected:
	std::string _string;
	int _lineNumber;
};

#endif
