#ifndef _re_h
#define _re_h

/* $Log:        RE.H $
Revision 1.1  92/08/20  15:50:30  Anthony_Scian
.

 * Revision 1.1  1992/08/20  17:14:07  peter
 * Initial revision
 *
 */

#include <iostream.h>
#include "useful.h"
#include "ins.h"

struct CharPtn {
    uint        card;
    CharPtn     *fix;
    CharPtn     *nxt;
};

struct CharSet {
    CharPtn     *fix;
    CharPtn     *freeHead, **freeTail;
    CharPtn     *rep[nChars];
    CharPtn     ptn[nChars];
};

class Range {
public:
    Range       *next;
    uint        lb, ub;         // [lb,ub)
public:
    Range(uint l, uint u) : next(NULL), lb(l), ub(u)
        { }
    Range(Range &r) : next(NULL), lb(r.lb), ub(r.ub)
        { }
    friend ostream& operator<<(ostream&, const Range&);
    friend ostream& operator<<(ostream&, const Range*);
};

inline ostream& operator<<(ostream &o, const Range *r){
        return r? o << *r : o;
}

class RegExp {
public:
    uint        size;
public:
    virtual char *typeOf() = 0;
    RegExp *isA(char *t)
        { return typeOf() == t? this : NULL; }
    virtual void split(CharSet&) = 0;
    virtual void calcSize(Char*) = 0;
    virtual uint fixedLength();
    virtual void compile(Char*, Ins*) = 0;
    virtual void display(ostream&) const = 0;
    friend ostream& operator<<(ostream&, const RegExp&);
    friend ostream& operator<<(ostream&, const RegExp*);
};

inline ostream& operator<<(ostream &o, const RegExp &re){
    re.display(o);
    return o;
}

inline ostream& operator<<(ostream &o, const RegExp *re){
    return o << *re;
}

class NullOp: public RegExp {
public:
    static char *type;
public:
    char *typeOf()
        { return type; }
    void split(CharSet&);
    void calcSize(Char*);
    uint fixedLength();
    void compile(Char*, Ins*);
    void display(ostream &o) const {
        o << "_";
    }
};

class MatchOp: public RegExp {
public:
    static char *type;
    Range       *match;
public:
    MatchOp(Range *m) : match(m)
        { }
    char *typeOf()
        { return type; }
    void split(CharSet&);
    void calcSize(Char*);
    uint fixedLength();
    void compile(Char*, Ins*);
    void display(ostream&) const;
};

class RuleOp: public RegExp {
private:
    RegExp      *exp;
public:
    RegExp      *ctx;
    static char *type;
    Ins         *ins;
    uint        accept;
    String      code;
    uint        line;
public:
    RuleOp(RegExp*, RegExp*, uint, const SubString&, uint);
    char *typeOf()
        { return type; }
    void split(CharSet&);
    void calcSize(Char*);
    void compile(Char*, Ins*);
    void display(ostream &o) const {
        o << exp << "/" << ctx << ";";
    }
};

class AltOp: public RegExp {
private:
    RegExp      *exp1, *exp2;
public:
    static char *type;
public:
    AltOp(RegExp *e1, RegExp *e2)
        { exp1 = e1;  exp2 = e2; }
    char *typeOf()
        { return type; }
    void split(CharSet&);
    void calcSize(Char*);
    uint fixedLength();
    void compile(Char*, Ins*);
    void display(ostream &o) const {
        o << exp1 << "|" << exp2;
    }
    friend RegExp *mkAlt(RegExp*, RegExp*);
};

class CatOp: public RegExp {
private:
    RegExp      *exp1, *exp2;
public:
    static char *type;
public:
    CatOp(RegExp *e1, RegExp *e2)
        { exp1 = e1;  exp2 = e2; }
    char *typeOf()
        { return type; }
    void split(CharSet&);
    void calcSize(Char*);
    uint fixedLength();
    void compile(Char*, Ins*);
    void display(ostream &o) const {
        o << exp1 << exp2;
    }
};

class CloseOp: public RegExp {
private:
    RegExp      *exp;
public:
    static char *type;
public:
    CloseOp(RegExp *e)
        { exp = e; }
    char *typeOf()
        { return type; }
    void split(CharSet&);
    void calcSize(Char*);
    void compile(Char*, Ins*);
    void display(ostream &o) const {
        o << exp << "+";
    }
};

#endif
