//--------------------------------------------------------------------------
#include <stdexcept>
#include "edif_parser.h"
#include "lexan_edif.h"
#include "config.h"
using namespace std;
//---------------------------------------------------------------------------
void EdifParser::run (std::istream& in, const string& nof) {
    l.init (in, nof);	// initiate lexical analysis
    token = l.NextToken();
    start ();			// may throw SyntaxException, KWException, NotYetException, 
    l.CheckToken (token,LEX_E_NULL);
}
//---------------------------------------------------------------------------
void EdifParser::start()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_EDIF);
   token = l.NextToken();
   nameDef();			// EDIF file name definition
   edifVersion();
   edifLevel();
   keywordMap();
   a3();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
std::string EdifParser::nameDef() {
    std::string s;
    switch(token) {
       case LEX_E_LPA:
	   switch(l.LookAhead()) {
	       case LEX_E_NAME:   return name();
	       case LEX_E_RENAME: return rename();
	       default:
		   throw SyntaxException (
				  TokenReason(l, token,  LEX_E_RENAME, LEX_E_NAME), 
				  LexPosition(l));
	   }
	   break;
       default:
	   s=l.Lex_AStr;
	   token = l.NextToken();
	   return s;
    }
    return "";
}
//---------------------------------------------------------------------------
std::string EdifParser::name()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_NAME);
   token = l.CheckNextToken(LEX_E_IDENT);
   std::string s=l.Lex_AStr;
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
   return s;
}
//---------------------------------------------------------------------------
std::string EdifParser::rename()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_RENAME);
   token = l.NextToken();
   std::string s,s1;
   s = a1();
   a2();
   l.CheckToken(token, LEX_E_RPA);
   token = l.NextToken();
   return s;
}
//---------------------------------------------------------------------------
void EdifParser::edifVersion()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_EDIFVERSION);
   token = l.CheckNextToken(LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken(LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken(LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::edifLevel()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_EDIFLEVEL);
   token = l.CheckNextToken(LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::keywordMap()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_KEYWORDMAP);
   token = l.NextToken();
   keywordLevel();
   l.CheckToken(token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::keywordLevel()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_KEYWORDLEVEL);
   token = l.CheckNextToken(LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
std::string EdifParser::a1()
{
   l.CheckToken (token, LEX_E_IDENT, LEX_E_LPA);
   std::string s;
   switch(token)
   {
    case LEX_E_IDENT:
      s=l.Lex_AStr;
      token = l.NextToken();
      break;
    case LEX_E_LPA:
      return name();
      break;
    default:
      break;
   }
   return s;
}
//---------------------------------------------------------------------------
std::string EdifParser::a2()
{
   l.CheckToken (token, LEX_E_STRINGTOKEN);
   std::string s=l.Lex_AStr;
   token = l.NextToken();
   return s;
}
//---------------------------------------------------------------------------
void EdifParser::a3() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_STATUS:   status();   break;
	    case LEX_E_LIBRARY:  library();  break;
	    case LEX_E_EXTERNAL: external(); break;
	    case LEX_E_DESIGN:   design();   break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a4()
{
   written();
}
//---------------------------------------------------------------------------
void EdifParser::a5() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_AUTHOR:  author(); 	break;
	    case LEX_E_PROGRAM: program(); 	break;
	    case LEX_E_DATAORIGIN: dataOrigin(); 	break;
	    default:  return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a6() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_CELL: cell(); break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a7()
{
   l.CheckToken (token, LEX_E_TIE, LEX_E_RIPPER, LEX_E_GENERIC);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::a8() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_VIEW: view(); break;
	    case LEX_E_PROPERTY: property (EdifParserClient :: cellCtx); break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a9()
{
   l.CheckToken (token, LEX_E_NETLIST);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::a10() {
    while (true)
	switch(token) {
	    case LEX_E_LPA: port(); break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a12() {		// possibly other values
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_DIRECTION: direction(); break;
	    case LEX_E_PROPERTY: property (EdifParserClient :: portCtx); break;
	    default:  return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a13() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_CONTENTS: contents(); 	   break;
	    case LEX_E_PROPERTY: property (EdifParserClient :: viewCtx); break;
	    default: return;
    }
}
//---------------------------------------------------------------------------
void EdifParser::a14() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_INSTANCE: instance(); break;
	    case LEX_E_NET:      net();      break;
	    default:  return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a15 (std::string& viewName, std::string& cellName, std::string& libName) {
    l.CheckToken (token, LEX_E_LPA);
    switch(l.LookAhead()) {
	case LEX_E_VIEWREF:
	    viewRef(viewName, cellName, libName);
	    break;
	case LEX_E_VIEWLIST:
	    throw KWException (KWReason(l), LexPosition(l));		// NOT IMPLEMENTED
	    viewList();			// de facto is caused by unimplemented arrays
	    break;
	default:
	    break;
   }
}
//---------------------------------------------------------------------------
void EdifParser::a15 () {
    l.CheckToken (token, LEX_E_LPA);
    switch(l.LookAhead()) {
	case LEX_E_VIEWREF:
	    viewRef ();
	    break;
	case LEX_E_VIEWLIST:
	    throw KWException (KWReason(l), LexPosition(l));		// NOT IMPLEMENTED
	    viewList();			// de facto is caused by unimplemented arrays
	    break;
	default:
	    break;
    }
}
//---------------------------------------------------------------------------
void EdifParser::a16() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_PROPERTY: property(EdifParserClient :: instCtx); break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a17(std::string &nm) {
    switch(l.LookAhead()) {
	case LEX_E_LIBRARYREF: libraryRef(nm); break;
	default: return;
    }
}
//---------------------------------------------------------------------------
void EdifParser::a18() {
    while (true)
	switch(l.LookAhead()){
	    case LEX_E_PORTREF: portRef(); break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a19 (std::string &instName, EdifIndices& instIndices) {
    switch(l.LookAhead()) {
	case LEX_E_INSTANCEREF: instanceRef(instName, instIndices);  break;	// instance port
	default: break;						// defined entity port
    }
}
//---------------------------------------------------------------------------
void EdifParser::a20() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_PROPERTY: property (EdifParserClient :: netCtx); break;
	    default:  return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a21() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_PROPERTY: property (EdifParserClient :: designCtx); break;
	    default:  return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a22() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_OWNER: owner(); break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
std::string EdifParser::a23()
{
   l.CheckToken (token, LEX_E_INPUT, LEX_E_OUTPUT, LEX_E_INOUT);
   std::string dir = l.Lex_AStr;
   token = l.NextToken();
   return dir;
}
//---------------------------------------------------------------------------
void EdifParser::a24() {
    switch(token) {
	case LEX_E_LPA: a15(); break;
	default: return;
    }
}
//---------------------------------------------------------------------------
void EdifParser::a25() {
    switch(l.LookAhead()) {
	case LEX_E_INSTANCEREF:
	    throw NotYetException (NotYetReason("[instanceRef|viewRef] in instanceRef"), LexPosition(l));
	    break;
	case LEX_E_VIEWREF:
	    throw NotYetException (NotYetReason("[instanceRef|viewRef] in instanceRef"), LexPosition(l));
	    viewRef();
	    break;
	default:
	    return;
   }
}
//---------------------------------------------------------------------------
void EdifParser::a26() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_LOGICVALUE: logicValue(); break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a27() {
    while (true)
	switch(l.LookAhead()) {
	    case LEX_E_BOOLEANMAP: booleanMap(); break;
	    default: return;
	}
}
//---------------------------------------------------------------------------
void EdifParser::a28() {
    switch(l.LookAhead()) {
	case LEX_E_VERSION: version(); break;
	default: return;
    }
}
//---------------------------------------------------------------------------
void EdifParser::status()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken (LEX_E_STATUS);
   token = l.NextToken();
   a4();
   l.CheckToken(token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::written()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken (LEX_E_WRITTEN);
   token = l.NextToken();
   timestamp();
   a5();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::timestamp()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken (LEX_E_TIMESTAMP);
   token = l.CheckNextToken (LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken (LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken (LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken (LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken (LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken (LEX_E_INTEGERTOKEN);
   token = l.CheckNextToken (LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::author()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken (LEX_E_AUTHOR);
   token = l.CheckNextToken(LEX_E_STRINGTOKEN);
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::program()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_PROGRAM);
   token = l.CheckNextToken(LEX_E_STRINGTOKEN);
   token = l.NextToken();
   a28();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::dataOrigin()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_DATAORIGIN);
   token = l.CheckNextToken(LEX_E_STRINGTOKEN);
   token = l.NextToken();
   a28();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::version()
{
   if(token!=LEX_E_LPA) return; //version -> e
   token = l.CheckNextToken(LEX_E_VERSION);
   token = l.CheckNextToken(LEX_E_STRINGTOKEN);
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::library()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_LIBRARY);
   token = l.NextToken();
   std::string libName = nameDef();
   client_->haveLibrary (libName);		// ------------ have library -------
   edifLevel();
   technology();
   a6();
   client_->endLibrary();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::external()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken (LEX_E_EXTERNAL);
   token = l.NextToken();
   std::string libName = nameDef();
   client_->haveExternal (libName);		// ------------ have ext library ---
   edifLevel();
   technology();
   a6();
   client_->endExternal();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::technology()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_TECHNOLOGY);
   token = l.NextToken();
   numberDefinition();
   if(token==LEX_E_LPA)
     simulationInfo();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::numberDefinition()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_NUMBERDEFINITION);
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::simulationInfo()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_SIMULATIONINFO);
   token = l.NextToken();
   a26();
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::logicValue()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_LOGICVALUE);
   token = l.NextToken();
   nameDef();
   a27();
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::booleanMap()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_BOOLEANMAP);
   token = l.NextToken();
   booleanValue();
   token = l.NextToken();
}
//---------------------------------------------------------------------------
int EdifParser::booleanValue()
{
    l.CheckToken (token, LEX_E_LPA);
    int ret = l.CheckNextToken(LEX_E_TRUE, LEX_E_FALSE);
    token = l.CheckNextToken(LEX_E_RPA);
    token = l.NextToken();
    return ret;
}
//---------------------------------------------------------------------------
void EdifParser::cell()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_CELL);
   token = l.NextToken();
   std::string cellName = nameDef();
   cellType();
   client_->haveCell (cellName);
   a8 ();
   client_->endCell ();
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::cellType()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_CELLTYPE);
   token = l.NextToken();
   a7();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::view()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_VIEW);
   token = l.NextToken();
   std::string viewName = nameDef();
   viewType();
   client_->haveView (viewName);
   _interface();
   
   a13();
   client_->endView();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::viewType()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_VIEWTYPE);
   token = l.NextToken();
   a9();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::_interface()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_INTERFACE);
   token = l.NextToken();
   a10();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::port()
{
    std::string portName;
    EdifIndices portDims;      // array dimensions

    l.CheckToken (token, LEX_E_LPA);
    token = l.CheckNextToken(LEX_E_PORT);
    token = l.NextToken();
    
    aNameDef(portName, portDims);
    client_->havePort (portName, portDims);
    a12();
    client_->endPort ();
    
    l.CheckToken (token, LEX_E_RPA);
    token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::aNameDef (std::string &nm, EdifIndices &dims)
{
    if(l.LookAhead()==LEX_E_ARRAY) {
       array (nm, dims);
    } else {
       nm = nameDef();
       dims.clear();
    }
}
//---------------------------------------------------------------------------
void EdifParser::array(std::string &arrName, EdifIndices &arrDims)
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_ARRAY);
   token = l.NextToken();
   arrName = nameDef();
   
   arrDims.clear();
   l.CheckToken (token, LEX_E_INTEGERTOKEN);
   arrDims.push_back(l.Lex_AInt);
   token = l.NextToken();

   while (token == LEX_E_INTEGERTOKEN) {
        arrDims.push_back(l.Lex_AInt);
        token = l.NextToken();
   }

   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::member(std::string &membName, EdifIndices &membIndices)
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_MEMBER);
   token = l.NextToken();
   membName = nameDef();
   
   membIndices.clear();
   l.CheckToken (token, LEX_E_INTEGERTOKEN);
   membIndices.push_back(l.Lex_AInt);
   token = l.NextToken();

   while (token == LEX_E_INTEGERTOKEN) {
        membIndices.push_back(l.Lex_AInt);
        token = l.NextToken();
   }

   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::contents()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_CONTENTS);
   token = l.NextToken();
   a14();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::instance()
{
    std::string       instName, viewName, cellName, libName;
    EdifIndices  instDims;

    l.CheckToken (token, LEX_E_LPA);
    token = l.CheckNextToken(LEX_E_INSTANCE);
    token = l.NextToken();

    // ----------- parse values from instance phrase -----------------------
    aNameDef(instName, instDims);		// parse instance name & dimensions
    a15 (viewName, cellName, libName);          // of what it is
    client_->haveInstance (instName, instDims, viewName, cellName, libName);
    a16 ();                                     // parse properties
    client_->endInstance();
    
    l.CheckToken (token, LEX_E_RPA);
    token = l.NextToken();
}

//---------------------------------------------------------------------------
void EdifParser::viewRef(std::string& viewName, 
			 std::string& cellName,
			 std::string& libName)
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_VIEWREF);
   token = l.NextToken();
   viewName = nameRef();
   cellRef (cellName, libName);
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::viewRef (void)
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_VIEWREF);
   token = l.NextToken();
   nameRef();
   std::string cellName, libName;
   cellRef (cellName, libName);
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
std::string EdifParser::nameRef()
{
    switch(token) {
	case LEX_E_LPA: 
	    return name();
	default:
	    std::string nm=l.Lex_AStr;
	    token = l.NextToken();
	    return nm;
    }
}
//---------------------------------------------------------------------------
void EdifParser::cellRef(std::string& cellName, std::string& libName)
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_CELLREF);
   token = l.NextToken();
   cellName = nameRef();
   a17 (libName);
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::libraryRef(std::string& nm)
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_LIBRARYREF);
   token = l.NextToken();
   nm = nameRef();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::net()
{
   std::string      netName;
   EdifIndices netDims;

   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_NET);
   token = l.NextToken();

   aNameDef (netName, netDims);
   client_->haveNet (netName, netDims);
   joined();        	// list of joined ports
   a20();           	// optional part
   client_->endNet();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}

//---------------------------------------------------------------------------
void EdifParser::joined()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken (LEX_E_JOINED);
   token = l.NextToken();
   a18();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::portRef()
{
    std::string portName, instName;
    EdifIndices portIndices, instIndices;

    l.CheckToken (token, LEX_E_LPA);
    token = l.CheckNextToken (LEX_E_PORTREF);
    token = l.NextToken();

    aNameRef (portName, portIndices);
    a19 (instName, instIndices);		// sets instname or leaves empty
    client_->haveJoined (portName, portIndices, instName, instIndices);
    l.CheckToken (token, LEX_E_RPA);
    token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::aNameRef(std::string &nm, EdifIndices& indices) {
    if (l.LookAhead()==LEX_E_MEMBER) {
        member (nm, indices);
    } else {
        nm = nameRef();
        indices.clear();
    }
}
//---------------------------------------------------------------------------
void EdifParser::design() {
    l.CheckToken (token, LEX_E_LPA);
    token = l.CheckNextToken(LEX_E_DESIGN);
    token = l.NextToken();
    std::string designName, cellName, libName;
    designName = nameDef();
    cellRef (cellName, libName);
    client_->haveDesign (designName, cellName, libName);
    a21();
    client_->endDesign ();
    l.CheckToken (token, LEX_E_RPA);
    token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::property (EdifParserClient :: propCtx ctx)
{
    l.CheckToken (token, LEX_E_LPA);
    token = l.CheckNextToken(LEX_E_PROPERTY);
    token = l.NextToken();
    bool want;
    std::string propName = nameDef();
    want = client_->wantProperty (ctx, propName);
    if (want) {   
	Val propValue;
	typedValue (propValue);
	switch (propValue.lexToken) {
	    case LEX_E_STRINGTOKEN:
		client_->haveStrProperty (ctx, propName, propValue.strVal); 
		break;
	    case LEX_E_INTEGERTOKEN:
		client_->haveIntProperty (ctx, propName, propValue.intVal); 
		break;
	    case LEX_E_BOOLTOKEN:
		client_->haveBoolProperty (ctx, propName, propValue.boolVal); 
		break;
	}
	a22();
	l.CheckToken (token, LEX_E_RPA);
    } else {
       skip ();
    }	
    token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::typedValue(Val& val)		// possibly other values
{
    switch(l.LookAhead()) {
	case LEX_E_STRING:
	    val.lexToken = LEX_E_STRINGTOKEN;
	    string_ (val.strVal);
	    break;
	case LEX_E_INTEGER:
	    val.lexToken = LEX_E_INTEGERTOKEN;
	    val.intVal = integer();
	    break;
	case LEX_E_BOOLEAN:
	    val.lexToken = LEX_E_BOOLTOKEN;
	    val.boolVal = boolean();
	    break;
    }
}
//---------------------------------------------------------------------------
void EdifParser::skip (void) {
    while (token != LEX_E_RPA) {
	token = l.NextToken();    
	if (token == LEX_E_LPA) skip ();    
    }
    token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::string_(std::string &s)
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_STRING);
   token = l.CheckNextToken(LEX_E_STRINGTOKEN);
   s=l.Lex_AStr;
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
int  EdifParser::integer () {
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_INTEGER);
   token = l.CheckNextToken(LEX_E_INTEGERTOKEN);
   int s=l.Lex_AInt;
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
   return s;
}
//---------------------------------------------------------------------------
bool  EdifParser::boolean () {
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_BOOLEAN);
   int s = booleanValue();
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
   return s == LEX_E_TRUE;
}
    
//---------------------------------------------------------------------------
void EdifParser::owner()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_OWNER);
   token = l.CheckNextToken(LEX_E_STRINGTOKEN);
   token = l.CheckNextToken(LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::direction()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_DIRECTION);
   token = l.NextToken();
   client_->haveDir (a23());
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::instanceRef(std::string &nm, EdifIndices& indices)
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken (LEX_E_INSTANCEREF);
   token = l.NextToken();
   aNameRef(nm, indices);
   a25();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
void EdifParser::viewList()
{
   l.CheckToken (token, LEX_E_LPA);
   token = l.CheckNextToken(LEX_E_VIEWLIST);
   token = l.NextToken();
   throw NotYetException (NotYetReason("viewlist"), LexPosition(l));
   a24();
   l.CheckToken (token, LEX_E_RPA);
   token = l.NextToken();
}
//---------------------------------------------------------------------------
EdifParser::  ~EdifParser() {
}
//---------------------------------------------------------------------------
void EdifParserClient:: haveLibrary     (std::string libname) {}
void EdifParserClient:: haveExternal    (std::string libname) {}
void EdifParserClient:: haveDesign      (std::string designName, std::string cellName, std::string libName) {}
void EdifParserClient:: haveCell        (std::string cellName) {}
void EdifParserClient:: haveView        (std::string viewName) {}
void EdifParserClient:: havePort        (std::string portName, EdifIndices& portDims) {}
void EdifParserClient:: haveDir	        (std::string portDir) {}
void EdifParserClient:: haveInstance    (std::string instName, EdifIndices& instDims, std::string viewName, std::string cellName, std::string libName) {}
bool EdifParserClient:: wantProperty      (propCtx, std::string propName) { return false; }
void EdifParserClient:: haveStrProperty   (propCtx, std::string propName, std::string propValue) {}
void EdifParserClient:: haveBoolProperty  (propCtx, std::string propName, bool propValue) {}
void EdifParserClient:: haveIntProperty   (propCtx, std::string propName, int propValue) {}
void EdifParserClient:: haveNet         (std::string netName, EdifIndices& netDims) {}
void EdifParserClient:: haveJoined      (std::string portName, EdifIndices& portIndices, std::string instName, EdifIndices& instIndices) {}
void EdifParserClient:: endLibrary      (void) {}    
void EdifParserClient:: endExternal     (void) {}    
void EdifParserClient:: endDesign       (void) {}    
void EdifParserClient:: endCell         (void) {}    
void EdifParserClient:: endPort         (void) {}    
void EdifParserClient:: endView         (void) {}    
void EdifParserClient:: endInstance     (void) {}    
void EdifParserClient:: endNet          (void) {}    
EdifParserClient :: ~EdifParserClient () { }
