summaryrefslogblamecommitdiffstats
path: root/src/pbg.h
blob: 98a33705f5924fc8bc17738b9743400751233226 (plain) (tree)














































































































































































































































                                                                                  
#ifndef __PBG_H__
#define __PBG_H__

/*********************************************************
 *                                                       *
 * Prefix Boolean Grammar (PBG), a lightweight C library *
 * By Tyler J. Daddio, November 2018                     *
 *                                                       *
 *********************************************************/

/* Used to suppress compiler warnings for intentionally unused arguments. This
 * isn't as foolproof as GCC's unused attribute, but it is not compiler-
 * dependent, which is just dandy. */
#define PBG_UNUSED(x) (void)(x)

/* Used to represent the result of an expression evaluation. */
#define PBG_FALSE  0
#define PBG_TRUE   1
#define PBG_ERROR -1

/*****************************
 *                           *
 * EXPRESSION REPRESENTATION *
 *                           *
 *****************************/

/**
 * Types of PBG fields.
 */
typedef enum {
	PBG_NULL,  /* NULL: Unknown field type */
	
	/* Type literals. */
	PBG_MIN_LT_TP,
	PBG_LT_TP_DATE,    /* DATE TYPE literal */
	PBG_LT_TP_BOOL,    /* TRUE/FALSE TYPE literal */
	PBG_LT_TP_NUMBER,  /* NUMBER TYPE literal */
	PBG_LT_TP_STRING,  /* STRING TYPE literal */
	/* Add more TYPE literals here. */
	PBG_MAX_LT_TP,
	
	/* Literals. */
	PBG_MIN_LT,
	PBG_LT_TRUE,    /* TRUE literal */
	PBG_LT_FALSE,   /* FALSE literal */
	PBG_LT_NUMBER,  /* NUMBER literal */
	PBG_LT_STRING,  /* STRING literal */
	PBG_LT_DATE,    /* DATE literal */
	PBG_LT_VAR,     /* VARiable literal */
	/* Add more literals here. */
	PBG_MAX_LT,
	
	/* Operators. */
	PBG_MIN_OP,
	PBG_OP_NOT,   /* !   NOT */
	PBG_OP_AND,   /* &   AND */
	PBG_OP_OR,    /* |   OR */
	PBG_OP_EQ,    /* =   EQUAL */
	PBG_OP_LT,    /* <   LESS THAN */
	PBG_OP_GT,    /* >   GREATER THAN */
	PBG_OP_EXST,  /* ?   EXISTS */
	PBG_OP_NEQ,   /* !=  NOT EQUAL */
	PBG_OP_LTE,   /* <=  LESS THAN OR EQUAL TO */
	PBG_OP_GTE,   /* >=  GREATER THAN OR EQUAL TO */
	PBG_OP_TYPE,  /* @   TYPE OF */
	/* Add more operators here. */
	PBG_MAX_OP
} pbg_field_type;

/**
 * This struct represents a PBG field. A field can be either a literal or an 
 * operator. This is determined by its type. For operators, the data pointer
 * describes a list of pointers to other fields in the abstract syntax tree.
 * For constants, it describes data relevant to the field type.
 */
typedef struct {
	pbg_field_type  _type;  /* Node type, determines the type/size of data. */
	int             _int;   /* Type determines what this is used for! */
	void*           _data;  /* Arbitrary data! */
} pbg_field;

/**
 * This struct represents a PBG expression. There are two arrays in this 
 * representation: one for constants, and one for variables. Both types are
 * represented by fields. 
 */
typedef struct {
	pbg_field*  _constants;  /* Constants. */
	pbg_field*  _variables;  /* Variables. */
	int         _numconst;   /* Number of constants. */
	int         _numvars;    /* Number of variables. */
} pbg_expr;


/************************
 *                      *
 * ERROR REPRESENTATION *
 *                      *
 ************************/

/**
 * Type specifiers for all possible PBG errors.
 */
typedef enum {
	PBG_ERR_NONE,
	PBG_ERR_ALLOC,
	PBG_ERR_STATE,
	PBG_ERR_SYNTAX,
	PBG_ERR_UNKNOWN_TYPE,
	PBG_ERR_OP_ARITY,
	PBG_ERR_OP_ARG_TYPE
} pbg_error_type;

/**
 * Represents a PBG error. Errors may be generated during parsing and 
 * evaluation and should be checked by the caller.
 */
typedef struct {
	pbg_error_type  _type;  /* Error type. */
	int             _line;  /* Line of file where error occurred. */
	char*           _file;  /* File in which error occurred. */
	int             _int;   /* Type determines what this is used for! */
	void*           _data;  /* Data to be included with error report. */
} pbg_error;


/***************
 *             *
 * EXPRESSIONS *
 *             *
 ***************/

/**
 * Parses the string as a boolean expression in Prefix Boolean Grammar.
 * @param e    PBG expression instance to initialize.
 * @param err  Container to store error, if any occurs.
 * @param str  String to parse. This must be terminated with '\0'.
 */
void pbg_parse(pbg_expr* e, pbg_error* err, char* str);

/**
 * Parses the string as a boolean expression in Prefix Boolean Grammar.
 * @param e    PBG expression instance to initialize.
 * @param err  Container to store error, if any occurs.
 * @param str  String to parse.
 * @param n    Length of the string.
 */
void pbg_parse_n(pbg_expr* e, pbg_error* err, char* str, int n);

/**
 * Evaluates the PBG expression with the provided assignments.
 * @param e     PBG expression to evaluate.
 * @param err   Container to store error, if any occurs.
 * @param dict  Dictionary used to resolve VAR names.
 * @return 1 if the PBG expression evaluates to true with the given dictionary. 
 *         0 otherwise.
 */
int pbg_evaluate(pbg_expr* e, pbg_error* err, pbg_field (*dict)(char*, int));

/**
 * Destroys the PBG expression instance and frees all associated resources.
 * This function does not free the provided pointer.
 * @param e PBG expression to destroy.
 */
void pbg_free(pbg_expr* e);


/**************
 *            *
 *   FIELDS   *
 *            *
 **************/

/**
 * Makes a field representing a DATE.
 * @param year   Year of the date.
 * @param month  Month of the date.
 * @param day    Day of the date.
 * @return a new DATE field.
 */
pbg_field pbg_make_date(int year, int month, int day);

/**
 * Makes a field representing a BOOL.
 * @param truth   Truth value of the new BOOL.
 * @return a new BOOL field.
 */
pbg_field pbg_make_bool(int truth);

/**
 * Makes a field representing a NUMBER.
 * @param value   Numeric value of the NUMBER.
 * @return a new NUMBER field.
 */
pbg_field pbg_make_number(double value);

/**
 * Makes a field representing a STRING.
 * @param value   Value of the STRING.
 * @return a new STRING field.
 */
pbg_field pbg_make_string(char* str);

/**
 * Makes a field representing NULL.
 * @return a new NULL field.
 */
pbg_field pbg_make_null(void);


/***************
 *             *
 *   ERRORS    *
 *             *
 ***************/

/**
 * Checks if the given error has been initialized with error data.
 * @param err  Error to check.
 * @return 1 if the given error has been initialized, 0 otherwise.
 */
int pbg_iserror(pbg_error* err);

/**
 * Prints a human-readable representation of the given pbg_error to the
 * standard output.
 * @param err  Error to print.
 */
void pbg_error_print(pbg_error* err);

/**
 * Frees resources being used by the given error, if any. This function does
 * not free the provided pointer.
 * @param e  PBG error to clean up.
 */
void pbg_error_free(pbg_error* e);


#endif  /* __PBG_H__ */