#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__ */