#ifndef __LispParser__
#define __LispParser__
#include "Forwards.hpp"
#include "Token.hpp"
#include "Lib/Exception.hpp"
#include "Lib/List.hpp"
namespace Shell {
using namespace Lib;
class LispLexer;
class LispParser
{
public:
enum Tag {
ATOM = 0,
LIST = 1
};
struct Expression {
USE_ALLOCATOR(Expression);
Tag tag;
std::string str;
List<Expression*>* list;
int line;
int col;
explicit Expression(Tag t, int line = -1, int col = -1)
: tag(t), str("?"), list(0), line(line), col(col) {}
Expression(Tag t, std::string s, int line = -1, int col = -1)
: tag(t), str(s), list(0), line(line), col(col) {}
std::string toString(bool outerParentheses=true) const;
std::string highlightSubexpression(Expression* expr) const;
std::string getPosition() const;
bool isList() const { return tag==LIST; }
bool isAtom() const { return tag==ATOM; }
};
typedef Lib::List<Expression*> EList;
explicit LispParser(LispLexer& lexer);
Expression* parse();
void parse(EList**);
class Exception
: public Lib::ParsingRelatedException
{
public:
Exception (std::string message,const Token&);
void cry (std::ostream&) const override;
~Exception () override {}
protected:
std::string _message;
};
private:
LispLexer& _lexer;
int _balance;
};
typedef LispParser::Expression LExpr;
typedef List<LExpr*> LExprList;
class ErrorThrowingLispListReader {
public:
ErrorThrowingLispListReader(LExpr* e, LExpr* root)
: e(e), root(root), it(LExprList::Iterator(e->list))
{ ASS(e->isList()); }
bool hasNext() { return it.hasNext(); }
LExpr* readExpr();
std::string readAtom();
LExpr* readList();
bool tryAcceptAtom(std::string atom);
void acceptEOL();
private:
LExpr* e;
LExpr* root;
LExprList::Iterator it;
};
}
#endif