246 lines
8 KiB
C++
246 lines
8 KiB
C++
/*
|
|
* 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 <stdio.h>
|
|
#include <iostream.h>
|
|
#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
|
|
|