1 /*
2 * This file is part of the Yices SMT Solver.
3 * Copyright (C) 2017 SRI International.
4 *
5 * Yices is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Yices is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Yices. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /*
20 * Build tables for parsing and relatives
21 * - the input is a set of triples <state, token, value>
22 * or <state, default, value>, and a global default value d
23 * - the set must be deterministic: no triples have the same
24 * state and token.
25 *
26 * This defines a function f that maps states and tokens to values:
27 * - f(s, t) = v if <s, t, v> is a triple
28 * - f(s, t) = v0 if <s, default, v0> is a triple and there's no
29 * triple of the form <s, t, _>
30 * - f(s, t) = global default otherwise.
31 *
32 * The code builds four tables default, table, val, and check
33 * that encode the function in a compact way.
34 * - for every state c,
35 * default[c] = a default value for state c (or error)
36 * base[c] = an index in array val and check
37 * - for an index i,
38 * val[i] = a value
39 * check[i] = a state
40 *
41 * The goal is to build the table so that f(s, t) is computed
42 * as follows:
43 * let i = base[s] + t;
44 * if check[i] = s then return val[i] else return default[s]
45 */
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <stdbool.h>
50 #include <string.h>
51
52
53 /*
54 * The specification file must define
55 * NSTATES, NTOKENS, DEFAULT_TOKEN, DEFAULT_VALUE, and triple
56 */
57 // #include "smt2_input_tables.h"
58 #include "yices_input_tables.h"
59
60 /*
61 * Descriptor for each state
62 */
63 typedef struct edge_s {
64 int token;
65 char * val;
66 } edge_t;
67
68 typedef struct {
69 char * def; // default value for that state
70 int nedges; // number of edges known
71 int size; // size of array edge
72 edge_t *edge;
73 } state_desc_t;
74
75 static state_desc_t state[NSTATES];
76
77 /*
78 * Initialization
79 */
init_state_descriptors(void)80 static void init_state_descriptors(void) {
81 int i;
82 edge_t *tmp;
83
84 for (i=0; i<NSTATES; i++) {
85 state[i].def = DEFAULT_VALUE;
86 state[i].nedges = 0;
87 state[i].size = 2;
88 tmp = (edge_t *) malloc(20 * sizeof(edge_t));
89 if (tmp == NULL) {
90 fprintf(stderr, "Malloc failed; could not allocate descriptors\n");
91 abort();
92 }
93 state[i].edge = tmp;
94 }
95 }
96
97 /*
98 * Add edge x, val to state i
99 */
add_edge(int i,int x,char * v)100 static void add_edge(int i, int x, char * v) {
101 state_desc_t *desc;
102 edge_t *e;
103 int j, n;
104
105 desc = state + i;
106
107 if (x == DEFAULT_TOKEN) {
108 if (strcmp(desc->def, DEFAULT_VALUE) == 0) {
109 desc->def = v;
110 } else {
111 fprintf(stderr, "Error: two default values for state %d\n", i);
112 abort();
113 }
114 } else {
115 e = desc->edge;
116 for (j=0; j<desc->nedges; j++) {
117 if (e[j].token == x) {
118 fprintf(stderr, "Error: two values for (state %d, token %d)\n", i, x);
119 abort();
120 }
121 }
122
123 if (j >= desc->size) {
124 n = desc->size * 2;
125 e = (edge_t *) realloc(e, n * sizeof(edge_t));
126 if (e == NULL) {
127 fprintf(stderr, "Realloc failed; could not allocate descriptors\n");
128 abort();
129 }
130 desc->edge = e;
131 desc->size = n;
132 }
133
134 e[j].token = x;
135 e[j].val = v;
136 desc->nedges ++;
137 }
138 }
139
140
141 /*
142 * Read all the triples
143 */
set_descriptors(triple_t * l)144 static void set_descriptors(triple_t *l) {
145 while (((int) l->source) >= 0) {
146 // printf("Adding triple %d %d %s\n", l->source, l->token, l->value);
147 if (l->source >= NSTATES) {
148 fprintf(stderr, "Error: triple state = %d, number of states = %d\n", l->source, NSTATES);
149 abort();
150 }
151 add_edge(l->source, l->token, l->value);
152 l ++;
153 }
154 }
155
156 /*
157 * Print the descriptors
158 */
print_descriptors(void)159 static void print_descriptors(void) {
160 int i, j, n;
161 edge_t *e;
162
163 for (i=0; i<NSTATES; i++) {
164 printf("state %d\n", i);
165 n = state[i].nedges;
166 e = state[i].edge;
167 for (j=0; j<n; j++) {
168 printf(" token %d: %s\n", e[j].token, e[j].val);
169 }
170 printf(" default: %s\n", state[i].def);
171 }
172 }
173
174
175 /*
176 * Tables to construct
177 */
178 static char * defval[NSTATES];
179 static int base[NSTATES];
180 static int val_size;
181 static int *check;
182 static char * *val;
183
184
185 /*
186 * Allocate tables check and val, with initial size = 2*NTOKENS
187 * Set all defaults in deval
188 */
init_tables(void)189 static void init_tables(void) {
190 int i, n;
191
192 for (i=0; i<NSTATES; i++) {
193 defval[i] = state[i].def;
194 }
195
196 n = 2*NTOKENS;
197 val_size = n;
198 check = (int *) malloc(n * sizeof(int));
199 val = (char * *) malloc(n * sizeof(char *));
200 if (check == NULL || val == NULL) {
201 fprintf(stderr, "Malloc failed: could not allocate check or val table\n");
202 abort();
203 }
204
205 for (i=0; i<n; i++) {
206 check[i] = NSTATES;
207 val[i] = DEFAULT_VALUE;
208 }
209 }
210
211 /*
212 * Extend the tables: make then twice as large
213 */
extend_tables(void)214 static void extend_tables(void) {
215 int i, n;
216
217 n = 2 * val_size;
218 check = (int *) realloc(check, n * sizeof(int));
219 val = (char * *) realloc(val, n * sizeof(char *));
220 if (check == NULL || val == NULL) {
221 fprintf(stderr, "Realloc failed: could not extend check or val table\n");
222 abort();
223 }
224
225 for (i=val_size; i<n; i++) {
226 check[i] = NSTATES;
227 val[i] = DEFAULT_VALUE;
228 }
229
230 val_size = n;
231 }
232
233 /*
234 * Check whether setting base[i] = b causes a conflict
235 */
base_possible(state_t i,int b)236 static bool base_possible(state_t i, int b) {
237 state_desc_t *desc;
238 edge_t *e;
239 int j, n, k;
240
241 desc = state + i;
242 e = desc->edge;
243 n = desc->nedges;
244
245 for (j=0; j<n; j++) {
246 k = b + e[j].token;
247 if (check[k] != NSTATES) {
248 return false;
249 }
250 }
251 return true;
252 }
253
254 /*
255 * Store data for state i at base b
256 */
build_state_base(state_t i,int b)257 static void build_state_base(state_t i, int b) {
258 state_desc_t *desc;
259 edge_t *e;
260 int j, n, k;
261
262 desc = state + i;
263 e = desc->edge;
264 n = desc->nedges;
265
266 base[i] = b;
267
268 for (j=0; j<n; j++) {
269 k = b + e[j].token;
270 check[k] = i;
271 val[k] = e[j].val;
272 }
273 }
274
275
276 /*
277 * Store data for state i
278 */
find_base(state_t i)279 static void find_base(state_t i) {
280 int b;
281
282 b=0;
283 while (! base_possible(i, b)) {
284 b ++;
285 if (b + NTOKENS > val_size) {
286 extend_tables();
287 }
288 }
289 build_state_base(i, b);
290 }
291
292
293 /*
294 * Build the full tables
295 */
build_tables(void)296 static void build_tables(void) {
297 state_t i;
298
299 init_tables();
300 for (i=0; i<NSTATES; i++) {
301 find_base(i);
302 }
303 }
304
305
306 /*
307 * Print the tables
308 */
print_tables(void)309 static void print_tables(void) {
310 int i, maxbase, size;
311
312 maxbase = base[0];
313 for (i=1; i<NSTATES; i++) {
314 if (base[i] > maxbase) {
315 maxbase = base[i];
316 }
317 }
318 size = maxbase + NTOKENS;
319
320 printf("/*\n"
321 " * Tables generated by table_builder\n"
322 " * see utils/table_builder.c\n"
323 " */\n\n");
324
325 printf("// Table sizes\n");
326 printf("#define NSTATES %d\n", NSTATES);
327 printf("#define BSIZE %d\n\n", size);
328
329 printf("// Default values for each state\n");
330 printf("static value_t default_value[NSTATES] = {\n");
331 for (i=0; i<NSTATES; i++) {
332 printf(" %s,\n", defval[i]);
333 }
334 printf("};\n\n");
335
336 printf("// Base values for each state\n");
337 printf("static int base[NSTATES] = {");
338 for (i=0; i<NSTATES; i++) {
339 if (i % 10 == 0) printf("\n ");
340 printf("%4d,", base[i]);
341 }
342 printf("\n};\n\n");
343
344 printf("// Check table\n");
345 printf("static int check[BSIZE] = {");
346 for (i=0; i<size; i++) {
347 if (i % 10 == 0) printf("\n ");
348 printf("%4d,", check[i]);
349 }
350 printf("\n};\n\n");
351
352 printf("// Value table\n");
353 printf("static value_t value[BSIZE] = {\n");
354 for (i=0; i<size; i++) {
355 printf(" %s,\n", val[i]);
356 }
357 printf("};\n\n");
358 }
359
360
361 /*
362 * Check the tables
363 */
get_val(state_t i,token_t t)364 static char *get_val(state_t i, token_t t) {
365 int k;
366
367 k = base[i] + t;
368 if (check[k] == i) {
369 return val[k];
370 } else {
371 return defval[i];
372 }
373 }
374
get_desc_val(state_t i,token_t t)375 static char *get_desc_val(state_t i, token_t t) {
376 state_desc_t *desc;
377 edge_t *e;
378 int j, n;
379
380 desc = state + i;
381 e = desc->edge;
382 n = desc->nedges;
383
384 for (j=0; j<n; j++) {
385 if (e[j].token == t) return e[j].val;
386 }
387
388 return desc->def;
389 }
390
check_tables(void)391 static void check_tables(void) {
392 int i, j, n;
393 char *v1, *v2;
394
395 n = 0;
396 for (i=0; i<NSTATES; i++) {
397 for (j=0; j<NTOKENS; j++) {
398 v1 = get_val(i, j);
399 v2 = get_desc_val(i, j);
400 if (v1 != v2) {
401 n ++;
402 fprintf(stderr, "Error in tables\n");
403 fprintf(stderr, " get_val(%d, %d) = %s\n", i, j, v1);
404 fprintf(stderr, " get_desc_val(%d, %d) = %s\n", i, j, v2);
405 }
406 }
407 }
408 if (n == 0) {
409 fprintf(stderr, "Tables appear correct\n");
410 }
411 }
412
main(void)413 int main(void) {
414 init_state_descriptors();
415 set_descriptors(triples);
416 print_descriptors();
417
418 build_tables();
419 print_tables();
420 check_tables();
421 return 0;
422 }
423