/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



#ifndef _SYMTBL_HXX
#define _SYMTBL_HXX

#include <svl/svarray.hxx>
#include <tools/string.hxx>
#include <basic/sbxdef.hxx>
#include <basic/sbdef.hxx>

class SbiSymDef;   					// Basisklasse
class SbiProcDef;					// Prozedur
class SbiConstDef;					// Konstante
class SbiSymPool;					// Symbol-Pool
class SbiStringPool;				// gepoolte Strings

class SvStream;
class SbiParser;

enum SbiSymScope { SbLOCAL, SbPARAM, SbPUBLIC, SbGLOBAL, SbRTL };

///////////////////////////////////////////////////////////////////////////

// Der String-Pool nimmt String-Eintraege auf und sorgt dafuer,
// dass sie nicht doppelt vorkommen.

SV_DECL_PTRARR_DEL(SbiStrings,String*,5,5)

class SbiStringPool {				// String-Pool
	SbiStrings aData;				// Daten
	String 	   aEmpty;				// for convenience
	SbiParser* pParser;				// der Parser
public:
	SbiStringPool( SbiParser* );
   ~SbiStringPool();
	sal_uInt16 GetSize() const { return aData.Count(); }
	// AB 8.4.1999, Default wegen #64236 auf sal_True geaendert
	// Wenn der Bug sauber behoben ist, wieder auf sal_False aendern.
	short Add( const String&, sal_Bool=sal_True );
	short Add( double, SbxDataType );
	const String& Find( sal_uInt16 ) const;
	SbiParser* GetParser() { return pParser; }
};

///////////////////////////////////////////////////////////////////////////

SV_DECL_PTRARR_DEL(SbiSymbols,SbiSymDef*,5,5)

class SbiSymPool {					// Symbol-Pool
	friend class SbiSymDef;
	friend class SbiProcDef;
protected:
	SbiStringPool& rStrings;   		// verwendeter Stringpool
	SbiSymbols  aData;				// Daten
	SbiSymPool* pParent;  			// uebergeordneter Symbol-Pool
	SbiParser*  pParser; 			// der Parser
	SbiSymScope eScope;				// Scope des Pools
	sal_uInt16	   nProcId;				// aktuelles ProcId fuer STATIC-Variable
	sal_uInt16	   nCur;				// Iterator
public:
	SbiSymPool( SbiStringPool&, SbiSymScope );
   ~SbiSymPool();

	void Clear();

	void   SetParent( SbiSymPool* p )	{ pParent = p;		}
	void   SetProcId( short n )			{ nProcId = n;		}
	sal_uInt16 GetSize() const				{ return aData.Count(); }
	SbiSymScope GetScope() const   		{ return eScope;	}
	void   SetScope( SbiSymScope s ) 	{ eScope = s;		}
	SbiParser* GetParser()				{ return pParser;	}

	SbiSymDef* AddSym( const String& );	// Symbol hinzufuegen
	SbiProcDef* AddProc( const String& );// Prozedur hinzufuegen
	void Add( SbiSymDef* ); 			// Symbol uebernehmen
	SbiSymDef* Find( const String& ) const;// Variablenname
	SbiSymDef* FindId( sal_uInt16 ) const;	// Variable per ID suchen
	SbiSymDef* Get( sal_uInt16 ) const;		// Variable per Position suchen
	SbiSymDef* First(), *Next();  		// Iteratoren

	sal_uInt32 Define( const String& );		// Label definieren
	sal_uInt32 Reference( const String& );  // Label referenzieren
	void   CheckRefs();					// offene Referenzen suchen
};

///////////////////////////////////////////////////////////////////////////

class SbiSymDef {  					// Allgemeiner Symboleintrag
	friend class SbiSymPool;
protected:
	String 	   aName;				// Name des Eintrags
	SbxDataType eType;				// Typ des Eintrags
	SbiSymPool* pIn;			  	// Parent-Pool
	SbiSymPool* pPool;				// Pool fuer Unterelemente
	short	   nLen;				// Stringlaenge bei STRING*n
	short	   nDims;				// Array-Dimensionen
	sal_uInt16	   nId;					// Symbol-Nummer
	sal_uInt16	   nTypeId;				// String-ID des Datentyps (Dim X AS Dytentyp)
	sal_uInt16	   nProcId;				// aktuelles ProcId fuer STATIC-Variable
	sal_uInt16	   nPos;				// Positions-Nummer
	sal_uInt32	   nChain;				// Backchain-Kette
	sal_Bool	   bNew		: 1;		// sal_True: Dim As New...
	sal_Bool	   bChained : 1;		// sal_True: Symbol ist in Code definiert
	sal_Bool	   bByVal   : 1;		// sal_True: ByVal-Parameter
	sal_Bool	   bOpt		: 1;		// sal_True: optionaler Parameter
	sal_Bool	   bStatic  : 1;		// sal_True: STATIC-Variable
	sal_Bool	   bAs		: 1;		// sal_True: Datentyp per AS XXX definiert
	sal_Bool	   bGlobal	: 1;		// sal_True: Global-Variable
	sal_Bool	   bParamArray : 1;		// sal_True: ParamArray parameter
	sal_Bool	   bWithEvents : 1;		// sal_True: Declared WithEvents
	sal_Bool	   bWithBrackets : 1;	// sal_True: Followed by ()
	sal_uInt16	   nDefaultId;			// Symbol number of default value
	short      nFixedStringLength;  // String length in: Dim foo As String*Length
public:
	SbiSymDef( const String& );
	virtual ~SbiSymDef();
	virtual SbiProcDef* GetProcDef();
	virtual SbiConstDef* GetConstDef();

	SbxDataType GetType() const	{ return eType;		}
	virtual void SetType( SbxDataType );
	const String& GetName();
	SbiSymScope GetScope() const;
	sal_uInt16	   GetProcId() const{ return nProcId;	}
	sal_uInt32	   GetAddr() const	{ return nChain;	}
	sal_uInt16	   GetId() const 	{ return nId;		}
	sal_uInt16	   GetTypeId() const{ return nTypeId;	}
	void 	   SetTypeId( sal_uInt16 n ) { nTypeId = n; eType = SbxOBJECT; }
	sal_uInt16	   GetPos() const	{ return nPos;		}
	void	   SetLen( short n ){ nLen = n;			}
	short	   GetLen() const	{ return nLen;		}
	void	   SetDims( short n ) { nDims = n;		}
	short	   GetDims() const  { return nDims;		}
	sal_Bool	   IsDefined() const{ return bChained;	}
	void	   SetOptional()   	{ bOpt = sal_True;		}
	void	   SetParamArray() 	{ bParamArray = sal_True;		}
	void	   SetWithEvents() 	{ bWithEvents = sal_True;		}
	void	   SetWithBrackets(){ bWithBrackets = sal_True;		}
	void	   SetByVal( sal_Bool bByVal_ = sal_True )
				{ bByVal = bByVal_; }
	void	   SetStatic( sal_Bool bAsStatic = sal_True )		{ bStatic = bAsStatic;	}
	void	   SetNew()			{ bNew = sal_True;		}
	void	   SetDefinedAs()	{ bAs = sal_True;		}
	void	   SetGlobal(sal_Bool b){ bGlobal = b;	}
	void 	   SetDefaultId( sal_uInt16 n ) { nDefaultId = n; }
	sal_uInt16 	   GetDefaultId( void ) { return nDefaultId; }
	sal_Bool	   IsOptional() const{ return bOpt;		}
	sal_Bool	   IsParamArray() const{ return bParamArray; }
	sal_Bool	   IsWithEvents() const{ return bWithEvents; }
	sal_Bool	   IsWithBrackets() const{ return bWithBrackets; }
	sal_Bool	   IsByVal() const	{ return bByVal;	}
	sal_Bool	   IsStatic() const { return bStatic;	}
	sal_Bool	   IsNew() const	{ return bNew;		}
	sal_Bool	   IsDefinedAs() const { return bAs;	}
	sal_Bool	   IsGlobal() const { return bGlobal;	}
	short      GetFixedStringLength( void ) const { return nFixedStringLength; }
	void 	   SetFixedStringLength( short n ) { nFixedStringLength = n; }

	SbiSymPool& GetPool();
	sal_uInt32	   Define();		// Symbol in Code definieren
	sal_uInt32	   Reference();		// Symbol in Code referenzieren

private:
	SbiSymDef( const SbiSymDef& );

};

class SbiProcDef : public SbiSymDef {	// Prozedur-Definition (aus Basic):
	SbiSymPool aParams;				// Parameter
	SbiSymPool aLabels;				// lokale Sprungziele
	String aLibName;				// LIB "name"
	String aAlias;					// ALIAS "name"
	sal_uInt16 nLine1, nLine2;			// Zeilenbereich
	PropertyMode mePropMode;		// Marks if this is a property procedure and which
	String maPropName;				// Property name if property procedure (!= proc name)
	sal_Bool   bCdecl  : 1;				// sal_True: CDECL angegeben
	sal_Bool   bPublic : 1;				// sal_True: proc ist PUBLIC
	sal_Bool   mbProcDecl : 1;			// sal_True: instanciated by SbiParser::ProcDecl
public:
	SbiProcDef( SbiParser*, const String&, sal_Bool bProcDecl=false );
	virtual ~SbiProcDef();
	virtual SbiProcDef* GetProcDef();
	virtual void SetType( SbxDataType );
	SbiSymPool& GetParams() 	  	{ return aParams;  }
	SbiSymPool& GetLabels() 	  	{ return aLabels;  }
	SbiSymPool& GetLocals() 	  	{ return GetPool();}
	String& GetLib() 	    		{ return aLibName; }
	String& GetAlias() 		  		{ return aAlias;   }
	void SetPublic( sal_Bool b )		{ bPublic = b;	   }
	sal_Bool IsPublic() const			{ return bPublic;  }
	void SetCdecl( sal_Bool b = sal_True) 	{ bCdecl = b;      }
	sal_Bool IsCdecl() const			{ return bCdecl;   }
	sal_Bool IsUsedForProcDecl() const	{ return mbProcDecl; }
	void SetLine1( sal_uInt16 n )		{ nLine1 = n;	   }
	sal_uInt16 GetLine1() const			{ return nLine1;   }
	void SetLine2( sal_uInt16 n )		{ nLine2 = n;	   }
	sal_uInt16 GetLine2() const			{ return nLine2;   }
	PropertyMode getPropertyMode()	{ return mePropMode; }
	void setPropertyMode( PropertyMode ePropMode );
	const String& GetPropName()		{ return maPropName; }

	// Match mit einer Forward-Deklaration. Die Parameternamen
	// werden abgeglichen und die Forward-Deklaration wird
	// durch this ersetzt
	void Match( SbiProcDef* pForward );

private:
	SbiProcDef( const SbiProcDef& );

};

class SbiConstDef : public SbiSymDef
{
	double nVal;
	String aVal;
public:
	SbiConstDef( const String& );
	virtual ~SbiConstDef();
	virtual SbiConstDef* GetConstDef();
	void Set( double, SbxDataType );
	void Set( const String& );
	double GetValue()			{ return nVal; }
	const String& GetString() 	{ return aVal; }
};


#endif

