//---------------------------------------------------------------------------

#ifndef edifH
#define edifH

#include <string>
#include <vector>
#include "lexan_edif.h"

typedef std::vector<int> EdifIndices;

class EdifParserClient {
public:
    typedef enum { instCtx, viewCtx, designCtx, netCtx, cellCtx, portCtx } propCtx;

    virtual void haveLibrary     (std::string libname);
    virtual void  endLibrary     (void);
    virtual void haveExternal    (std::string libname);
    virtual void  endExternal    (void);
    virtual void haveDesign      (std::string designName, std::string cellName, std::string libName);
    virtual void  endDesign      (void);
    virtual void haveCell        (std::string cellName);
    virtual void  endCell        (void);
    virtual void haveView        (std::string viewName);
    virtual void  endView        (void);
    virtual void havePort        (std::string portName, EdifIndices& portDims);
    virtual void  endPort	     (void);
    virtual void haveDir	     (std::string portDir);
    virtual void haveInstance    (std::string instName, EdifIndices& instDims, std::string viewName, std::string cellName, std::string libName);
    virtual void  endInstance    (void);    
    virtual bool wantProperty      (propCtx, std::string propName);
    virtual void haveStrProperty   (propCtx, std::string propName, std::string propValue);
    virtual void haveBoolProperty  (propCtx, std::string propName, bool propValue);
    virtual void haveIntProperty   (propCtx, std::string propName, int propValue);
    virtual void haveNet         (std::string netName, EdifIndices& netDims);
    virtual void  endNet         (void);
    virtual void haveJoined      (std::string portName, EdifIndices& portIndices, std::string instName,  EdifIndices& instIndices);

    virtual ~EdifParserClient ();
};

class EdifParser {
public:

private:
    EdifParserClient* client_;
    
    struct Val {			    // value from typedValue
	    int 		lexToken;	// LEX_E_BOOLTOKEN, LEX_E_INTEGERTOKEN, LEX_E_STRINGTOKEN
	    std::string strVal;
	    int 		intVal;
	    bool 		boolVal;
    };
    int token;

    void start();
    void skip (void);			// skip any subtree

    std::string nameDef();
    std::string name();
    std::string rename();
    void edifVersion();
    void edifLevel();
    void keywordMap();
    void keywordLevel();

    std::string a1();
    std::string a2();
    void a3();				// { status | design | library | external }
    void a4();
    void a5();
    void a6();				// { cell }
    void a7();
    void a8();				// { view }
    void a9();				// NETLIST
    void a10();				// { port }
    void a12 ();			// { direction | ... | ... }
    void a13();
    void a14();
    void a15(std::string&, std::string&, std::string&);	// { viewref | viewlist }
    void a15();
    void a16();				// { property }
    void a17(std::string&);
    void a18();				// { portRef }
    void a19(std::string&, EdifIndices&);
    void a20();
    void a21();
    void a22();
    std::string a23();			// INPUT | OUTPUT | INOUT
    void a24();
    void a25();
    void a26();
    void a27();
    void a28();

    void status();
    void written();
    void timestamp();
    void author();
    void program();
    void dataOrigin();
    void version();

    void library();
    void external();
    void technology();
    void numberDefinition();

    void simulationInfo();
    void logicValue();
    void booleanMap();
    int  booleanValue();	// returns LEX_E_TRUE or LEX_E_FALSE

    void cell();
    void cellType();
    void view();
    void viewType();
    void _interface();
    void port();
    void aNameDef (std::string& nm, EdifIndices &dims);
    void array (std::string& arrName, EdifIndices& arrDims);
    void member (std::string& membName, EdifIndices& membIndices);
    void contents();
    void instance();
    void viewRef (std::string&, std::string&, std::string&);
    void viewRef (void);
    std::string nameRef();				            // referenced name
    void cellRef(std::string &, std::string &);		// cell name, library name
    void libraryRef (std::string &);
    void net();
    void joined ();
    void portRef();
    void aNameRef (std::string &nm, EdifIndices& indices);
    void design ();
    void property (EdifParserClient :: propCtx);
    void typedValue(Val &);
    void string_(std::string &s);
    int  integer ();
    bool boolean ();
    void owner();
    void direction();
    void instanceRef(std::string &instName, EdifIndices& instIndices);
    void viewList();

public:
    LexanEdif l;			// position reporting

    void run (std::istream&, const std::string&);	// start the analysis with filename
    EdifParser (EdifParserClient* client): client_(client) {}

    ~EdifParser();
};
#endif
