/* * File: cexpr.h * Purpose: Prolog-like file I/O * Author: Julian Smart * Created: 1997 * Updated: * Copyright: (c) 1997, Julian Smart */ /* sccsid[] = "%W% %G%" */ #ifndef __CEXPRH__ #define __CEXPRH__ #include #include #include "wx_list.h" #include "wx_hash.h" #include "expr.h" // Error types #define CEXPR_ERROR_GENERAL 1 #define CEXPR_ERROR_SYNTAX 2 // Error handler function definition. If app returns TRUE, // carry on processing. typedef BOOL (*CExprErrorHandler) (int errorType, char *msg); extern CExprErrorHandler currentCExprErrorHandler; extern "C" FILE *yyin; //#ifndef __WATCOMC__ extern "C" //#endif int yyparse(void); typedef enum { CExprNull, CExprInteger, CExprReal, CExprWord, CExprString, CExprList } CExprType; class CExprDatabase; class ClipsTemplate; class ClipsTemplateSlot; class CExpr { public: CObject *client_data; CExprType type; union { long integer; char *word; char *string; float real; CExpr *first; // If is a list expr, points to the first node } value; CExpr *next; // If this is a node in a list, points to the next node CExpr *last; // If is a list expr, points to the last node CExpr(CExprType the_type, char *word_or_string, BOOL allocate); CExpr(const CString& functor); // Assume this is a new clause - pass functor CExpr(CExprType the_type, const CString& word_or_string = ""); CExpr(long the_integer); CExpr(float the_real); CExpr(wxList *the_list); ~CExpr(void); inline CExprType Type(void) { return type; } inline long IntegerValue(void) { if (type == CExprInteger) return value.integer; else if (type == CExprReal) return (long)value.real; else return 0; } inline float RealValue(void) { if (type == CExprReal) return value.real; else if (type == CExprInteger) return (float)value.integer; else return (float)0.0; } inline CString WordValue(void) { if (type == CExprWord) return value.word; else if (type == CExprString) return CString(value.string); else return CString(""); } inline CString StringValue(void) { if (type == CExprString) return CString(value.string); else if (type == CExprWord) return CString(value.word); else return CString(""); } // Get nth arg of clause (starting from 1) CExpr *Arg(CExprType type, int arg); // Return nth argument of a list expression (starting from zero) CExpr *Nth(int arg); // Returns the number of elements in a list expression int Number(void); CExpr *Copy(void); CExpr *GetAttributeValueNode(const CString& word); // Use only for a clause or list CExpr *AttributeValue(const CString& word); // Use only for a clause CString Functor(void); // Only for a clause BOOL IsFunctor(const CString& s); // Only for a clause void WriteClause(ostream& stream); // Write this expression as a top-level clause void WriteExpr(ostream& stream); // Write as any other subexpression void WriteLispExpr(ostream& stream); void WriteClipsClause(ostream& stream, BOOL filtering = FALSE, CExprDatabase *database = NULL); void WriteClipsSlot(ostream& stream, ClipsTemplate *temp); void WriteClipsList(ostream& stream); // Append an expression to a list void Append(CExpr *expr); // Insert at beginning of list void Insert(CExpr *expr); // Get first expr in list inline CExpr *GetFirst(void) { return ((type == CExprList) ? value.first : NULL); } // Get next expr if this is a node in a list inline CExpr *GetNext(void) { return next; } // Get last expr in list inline CExpr *GetLast(void) { return ((type == CExprList) ? last : NULL); } // This should really be called SetAttributeValue since any existing // attribute-value is deleted first. void AddAttributeValue(const CString& attribute, long value); void AddAttributeValue(const CString& attribute, float value); void AddAttributeValueWord(const CString& attribute, const CString& value); void AddAttributeValueString(const CString& attribute, const CString& value); void AddAttributeValue(const CString& attribute, wxList *value); void AddAttributeValue(const CString& attribute, CExpr *value); void AddAttributeValueStringList(const CString& attribute, wxList *string_list); void DeleteAttributeValue(const CString& attribute); BOOL GetAttributeValue(const CString& att, int& var); BOOL GetAttributeValue(const CString& att, long& var); BOOL GetAttributeValue(const CString& att, float& var); BOOL GetAttributeValue(const CString& att, CString& var); // Word OR string -> string BOOL GetAttributeValue(const CString& att, CExpr **var); // Add string items to list if the list attribute exists BOOL GetAttributeValueStringList(const CString& att, wxList *var); // Associate other data with this expression, e.g. when reading in a // number of linked items - store C++ object pointer with the expression // so we can index into the CExpr database and fish out the pointer. inline void SetClientData(CObject *data) { client_data = data; } inline CObject *GetClientData(void) { return client_data; } }; class CExprDatabase: public wxList { DECLARE_DYNAMIC(CExprDatabase) private: wxNode *position; // Where we are in a search wxHashTable *hash_table; CString attribute_to_hash; public: int noErrors; CExprDatabase(CExprErrorHandler handler = 0); // Use hashing on both the functor, and the attribute of // specified type (CExprString or CExprInteger) and name. // So to find node 45 // (i.e. match the clause node(id=45, ...)) // it usually requires 1 look-up: the keys for functor and attribute // are added together. // Obviously if the attribute was missing in a clause, it would // fail to be found by this method, but could be retrieved by a // linear search using BeginFind and FindClauseByFunctor, // or just searching through the list as per usual. CExprDatabase(CExprType type, const CString& attribute, int size = 500, CExprErrorHandler handler = 0); ~CExprDatabase(void); int GetItemCount(void); // get count of possible items void BeginFind(void); // Initialise a search CExpr *FindClause(long id); // Find a term based on an integer id attribute // e.g. node(id=23, type=rectangle, ....). // Find on basis of attribute/value pairs, e.g. type=rectangle // This doesn't use hashing; it's a linear search. CExpr *FindClause(const CString& word, const CString& value); CExpr *FindClause(const CString& word, long value); CExpr *FindClause(const CString& word, float value); CExpr *FindClauseByFunctor(const CString& functor); CExpr *HashFind(const CString& functor, const CString& value); CExpr *HashFind(const CString& functor, long value); void Append(CExpr *expr); // Does cleverer things if hashing is on void ClearDatabase(void); inline int GetErrorCount() { return noErrors; } BOOL Read(const CString& filename); BOOL ReadFromString(const CString& buffer); BOOL Write(const CString& fileName); BOOL Write(ostream& stream); void WriteLisp(ostream& stream); }; // Function call-style interface - some more convenience wrappers/unwrappers // Make a call CExpr *CExprMakeCall(const CString& functor ...); #define CExprMakeInteger(x) (new CExpr((long)x)) #define CExprMakeReal(x) (new CExpr((float)x)) #define CExprMakeString(x) (new CExpr(CExprString, x)) #define CExprMakeWord(x) (new CExpr(CExprWord, x)) #define CExprMake(x) (new CExpr(x)) // Checks functor BOOL CExprIsFunctor(CExpr *expr, const CString& functor); // Temporary variable for communicating between read.cc and YACC/LEX extern CExprDatabase *theCExprDatabase; // YACC/LEX can leave memory lying around... extern "C" CExprCleanUp(); #endif