#ifndef AST_HH #define AST_HH #include #include #include #include "refcount.hh" namespace AbSyn { class Term; class BindingTerm; class PairTerm; class AppTerm; class SkipTerm; class OpAppTerm; class OperatorDirective; class UseDirective; class Cases; class SeqTerm; class Symbol; class Fixity; class Form; class Visitor { public: virtual ~Visitor() {} virtual void symbol(Symbol *) = 0; virtual void binding(BindingTerm *) = 0; virtual void pair(PairTerm *) = 0; virtual void app(AppTerm *) = 0; virtual void seq(SeqTerm *) = 0; //virtual void cases(Cases *) = 0; virtual void form(Form *) = 0; virtual void skip(SkipTerm *) = 0; virtual void op(OpAppTerm *) { throw std::string("OP visited; not implemented"); } virtual void opdirective(OperatorDirective *) { throw std::string("OP directive visited; not implemented"); } virtual void usedirective(UseDirective *) { throw std::string("USE directive visited; not implemented"); } }; class AST { AST(AST const &); AST & operator=(AST const &); protected: AST() {} public: virtual ~AST() {} virtual Term & toTerm() throw (std::bad_cast) { throw std::bad_cast(); } virtual Cases & toCases() throw (std::bad_cast) { throw std::bad_cast(); } virtual SeqTerm & toSeqTerm() throw (std::bad_cast) { throw std::bad_cast(); } virtual Symbol & toSymbol() throw (std::bad_cast) { throw std::bad_cast(); } virtual Fixity & toFixity() throw (std::bad_cast) { throw std::bad_cast(); } }; inline safe_ptr toTerm(safe_ptr ptr) throw (std::bad_cast) { Term * tmp = &ptr.release()->toTerm(); return safe_ptr(tmp); } inline safe_ptr toCases(safe_ptr cases) throw (std::bad_cast) { Cases * tmp = &cases.release()->toCases(); return safe_ptr(tmp); } inline safe_ptr toSeqTerm(safe_ptr cases) throw (std::bad_cast) { SeqTerm * tmp = &cases.release()->toSeqTerm(); return safe_ptr(tmp); } inline safe_ptr toSymbol(safe_ptr sym) throw (std::bad_cast) { Symbol * tmp = &sym.release()->toSymbol(); return safe_ptr(tmp); } inline safe_ptr toFixity(safe_ptr fix) throw (std::bad_cast) { Fixity * tmp = &fix.release()->toFixity(); return safe_ptr(tmp); } class Term : public AST { Term(Term const &); Term & operator=(Term const &); bool parenthesized; protected: Term() : parenthesized(false) {} public: void makeParenthesized() { parenthesized = true; } Term & toTerm() throw (std::bad_cast) { return *this; } virtual void accept(Visitor &) = 0; }; class Symbol : public Term { public: typedef std::vector path_t; Symbol(std::string sym, path_t path = path_t()) : sym(sym), path(path) {} Symbol & toSymbol() throw (std::bad_cast) { return *this; } friend safe_ptr operator+(Symbol const & a, Symbol const & b); safe_ptr no_path() const { return safe_ptr(new Symbol(sym)); } virtual void accept(Visitor & v) { v.symbol(this); } std::string get_sym() const { return sym; } path_t const & get_path() const { return path; } private: std::string sym; path_t path; Symbol(Symbol const &); Symbol & operator=(Symbol const &); }; inline safe_ptr operator+(Symbol const & a, Symbol const & b) { safe_ptr rv(new Symbol(b.sym, a.path)); rv->path.insert(rv->path.end(), b.path.begin(), b.path.end()); rv->path.insert(rv->path.end(), b.sym); return rv; } class BindingTerm : public Term { safe_ptr pat; safe_ptr val; bool exported; BindingTerm(BindingTerm const &); BindingTerm & operator=(BindingTerm const &); public: BindingTerm(safe_ptr pat, safe_ptr val, bool exported = false) : pat(::AbSyn::toTerm(pat)), val(::AbSyn::toTerm(val)), exported(exported) {} bool get_exported() const { return exported; } Term & get_pat() const { return *pat; } Term & get_val() const { return *val; } void accept(Visitor & v) { v.binding(this); } }; class PairTerm : public Term { safe_ptr left; safe_ptr right; PairTerm(PairTerm const &); PairTerm & operator=(PairTerm const &); public: PairTerm(safe_ptr left, safe_ptr right) : left(::AbSyn::toTerm(left)), right(::AbSyn::toTerm(right)) {} void accept(Visitor & v) { v.pair(this); } Term & get_left() const { return *left; } Term & get_right() const { return *right; } }; class AppTerm : public Term { safe_ptr fun; safe_ptr arg; AppTerm(AppTerm const &); AppTerm & operator=(AppTerm const &); public: AppTerm(safe_ptr fun, safe_ptr arg) : fun(::AbSyn::toTerm(fun)), arg(::AbSyn::toTerm(arg)) {} void accept(Visitor & v) { v.app(this); } Term & get_fun() const { return *fun; } Term & get_arg() const { return *arg; } }; class OpAppTerm : public Term { safe_ptr op; safe_ptr larg; safe_ptr rarg; OpAppTerm(OpAppTerm const &); OpAppTerm & operator=(OpAppTerm const &); public: OpAppTerm(safe_ptr op, safe_ptr larg, safe_ptr rarg) : op(::AbSyn::toSymbol(op)), larg(::AbSyn::toTerm(larg)), rarg(::AbSyn::toTerm(rarg)) {} Symbol & get_op() { return *op; } Term & get_larg() { return *larg; } Term & get_rarg() { return *rarg; } void accept(Visitor & v) { return v.op(this); } }; class SeqTerm : public Term { std::vector terms; SeqTerm(SeqTerm const &); SeqTerm & operator=(SeqTerm const &); public: SeqTerm(safe_ptr term) { append(term); } ~SeqTerm() { for (std::vector::iterator it = terms.begin(); it != terms.end(); ++it) { delete *it; } } SeqTerm & toSeqTerm() throw (std::bad_cast) { return *this; } void append(safe_ptr term) { terms.insert(terms.end(), &term->toTerm()); term.release(); } void accept(Visitor & v) { v.seq(this); } class iterator { friend class SeqTerm; std::vector::iterator it; iterator(std::vector::iterator it) : it(it) {} public: Term & operator*() { return **it; } Term * operator->() { return *it; } iterator & operator+=(int n) { it += n; return *this; } iterator & operator-=(int n) { it -= n; return *this; } iterator & operator++() { ++it; return *this; } iterator & operator--() { --it; return *this; } iterator operator++(int) { iterator r = *this; it++; return r; } iterator operator--(int) { iterator r = *this; it--; return r; } bool operator==(iterator const & other) const { return this->it == other.it; } bool operator< (iterator const & other) const { return this->it < other.it; } bool operator> (iterator const & other) const { return this->it > other.it; } bool operator<=(iterator const & other) const { return this->it <= other.it; } bool operator>=(iterator const & other) const { return this->it >= other.it; } bool operator!=(iterator const & other) const { return this->it != other.it; } }; iterator begin() { return iterator(terms.begin()); } iterator end() { return iterator(terms.end()); } }; class Cases : public AST { typedef std::pair guard_t; typedef std::pair > case_t; std::vector cases; static const case_t empty_case; Cases(Cases const &); Cases & operator=(Cases const &); Cases(int) {} public: friend class generator; class generator { std::vector & cases; std::vector::iterator i; std::vector::iterator j; public: generator(Cases & cases) : cases(cases.cases), i(cases.cases.begin()) {} Term & current_pattern() { return *i->first; } Term & current_guard() { return *j->first; } Term & current_expr() { return *j->second; } void first_guard() { j = i->second.begin(); } void next_guard() { ++j; } bool last_guard() { return j == i->second.end(); } void first_case() { i = cases.begin(); } void next_case() { ++i; } bool last_case() { return i == cases.end(); } }; generator gen() { return generator(*this); } static safe_ptr noCases() { return safe_ptr(new Cases(0)); } Cases() { cases.insert(cases.begin(), empty_case); } ~Cases() { for (std::vector::iterator p = cases.begin(); p != cases.end(); ++p) { delete p->first; for (std::vector::iterator q = p->second.begin(); q != p->second.end(); ++q) { delete q->first; delete q->second; } } } Cases & toCases() throw (std::bad_cast) { return *this; } void add_guard(safe_ptr guard_, safe_ptr stmts_) { Term * guard = &guard_.release()->toTerm(); SeqTerm * stmts = &stmts_.release()->toSeqTerm(); std::vector::iterator i = cases.end() - 1; i->second.insert(i->second.end(), guard_t(guard, stmts)); } void finish_case(safe_ptr pat_) { std::vector::iterator i = cases.end() - 1; i->first = &pat_.release()->toTerm(); cases.insert(cases.end(), empty_case); } void append(safe_ptr cases_) { safe_ptr mcases = ::AbSyn::toCases(cases_); cases.erase(cases.end()-1); cases.insert(cases.end(), mcases->cases.begin(), mcases->cases.end()); } //void accept(Visitor & v) { v.cases(this); } }; class Form : public Term { safe_ptr preamble; safe_ptr cases; safe_ptr catches; safe_ptr finally; Form(Form const &); Form & operator=(Form const &); public: Form(safe_ptr preamble, safe_ptr cases, safe_ptr catches, safe_ptr finally) : preamble(::AbSyn::toSeqTerm(preamble)), cases(::AbSyn::toCases(cases)), catches(::AbSyn::toCases(catches)), finally(::AbSyn::toSeqTerm(finally)) {} void accept(Visitor & v) { v.form(this); } SeqTerm & get_preamble() { return *preamble; } Cases::generator cases_gen() { return cases->gen(); } Cases::generator catches_gen() { return catches->gen(); } SeqTerm & get_finally() { return *finally; } }; class SkipTerm : public Term { SkipTerm(SkipTerm const &); SkipTerm & operator=(SkipTerm const &); public: SkipTerm() {} void accept(Visitor & v) { v.skip(this); } }; inline safe_ptr skipTerm() { return safe_ptr(new SkipTerm()); } template class Vector : public AST { std::vector vec; public: ~Vector() { for (typename std::vector::iterator it = vec.begin(); it != vec.end(); ++it) { delete *it; } } void append(safe_ptr p) { T * tmp = &dynamic_cast(*p); vec.insert(vec.end(), tmp); } void append(safe_ptr p) { vec.insert(vec.end(), p); } void swap(Vector & other) { vec.swap(other.vec); } }; class Fixity : public AST { Fixity(Fixity const &); Fixity & operator=(Fixity const &); public: Vector prec, succ; safe_ptr eqv; Fixity() {} Fixity & toFixity() throw (std::bad_cast) { return *this; } }; class OperatorDirective : public Term { public: enum assoc_t { none, left, right }; OperatorDirective(safe_ptr op, assoc_t assoc, safe_ptr fixity) : op(::AbSyn::toSymbol(op)), assoc(assoc), fix(::AbSyn::toFixity(op)) {} private: safe_ptr op; assoc_t assoc; safe_ptr fix; OperatorDirective(OperatorDirective const &); OperatorDirective & operator=(OperatorDirective const &); void accept(Visitor & v) { v.opdirective(this); } }; class UseDirective : public Term { safe_ptr sym; safe_ptr as; UseDirective(UseDirective const &); UseDirective & operator=(UseDirective const &); public: UseDirective(safe_ptr sym_) : sym(::AbSyn::toSymbol(sym_)), as(sym->no_path()) {} UseDirective(safe_ptr sym, safe_ptr as) : sym(::AbSyn::toSymbol(sym)), as(as->toSymbol().no_path()) {} void accept(Visitor & v) { v.usedirective(this); } }; class Module : public AST { safe_ptr name; safe_ptr body; Module(Module const &); Module & operator=(Module const &); public: Module(safe_ptr name, safe_ptr body) : name(::AbSyn::toSymbol(name)), body(::AbSyn::toTerm(body)) {} }; } namespace std { template void swap(AbSyn::Vector & a, AbSyn::Vector & b) { a.swap(b); } }; #endif /* AST_HH */