1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
#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__ */
|