1/**
2 * \file
3 * \brief Use this file for quick parser tests on your machine.
4 */
5
6/*
7 * Copyright (c) 2011, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#ifdef TEST_PARSER
16
17#include <stdio.h>
18#include <assert.h>
19#include <stdarg.h>
20#include <string.h>
21
22
23#ifdef TEST_PARSER
24#include "../../../include/octopus/parser/ast.h"
25#else
26#include <octopus/parser/ast.h>
27#endif
28
29#include "y.tab.h"
30
31
32#define INITIAL_LENGTH 255
33
34struct writer {
35    char* output;
36    size_t pos;
37    size_t length;
38};
39
40struct skb_record {
41	struct writer name;
42	struct writer attributes;
43	struct writer constraints;
44};
45
46void emit(struct writer*, const char*, ...);
47
48
49// State used by tranlate()
50static struct skb_record* sr;
51static struct writer* w;
52struct ast_object* attribute_name;
53
54
55#ifdef PARSER_DEBUG
56static void print_writer(struct writer* w) {
57    printf("\tpos: %lu\n", w->pos);
58    printf("\tlength: %lu\n", w->length);
59    printf("\toutput: %s\n", w->output);
60}
61#endif
62
63
64void emit(struct writer* w, const char* format, ...)
65{
66	assert(w != NULL);
67	assert(format != NULL);
68	va_list  args;
69
70    if(w->output == NULL) {
71        w->output = malloc(INITIAL_LENGTH);
72        assert(w->output != NULL);
73        w->pos = 0;
74        w->length = INITIAL_LENGTH;
75    }
76
77	va_start(args, format);
78	int append_len = vsnprintf(NULL, 0, format, args);
79    va_end(args);
80
81    size_t occupied = w->pos + append_len;
82    if(w->length < occupied) {
83        w->output = realloc(w->output, occupied+1);
84        w->length = occupied;
85    }
86
87    va_start(args, format);
88	int bytes_written = vsnprintf(w->output+w->pos, append_len+1, format, args);
89    va_end(args);
90    assert(bytes_written == append_len);
91
92    w->pos = occupied;
93}
94
95static void translate(struct ast_object* p) {
96	assert(sr != NULL);
97    assert(p != NULL);
98
99    switch(p->type) {
100        case nodeType_Object:
101            assert(p->u.on.name != NULL);
102            w = &sr->name;
103
104            translate(p->u.on.name);
105
106            w = &sr->attributes;
107            emit(w, "[ ");
108
109			emit(&sr->constraints, "[ ");
110            if(p->u.on.attrs) {
111
112                translate(p->u.on.attrs);
113            }
114			emit(w, " ]");
115
116            size_t len = strlen(sr->constraints.output);
117            if(sr->constraints.output[len-2] == ',') {
118				sr->constraints.output[len-2] = ' ';
119				sr->constraints.output[len-1] = ']';
120            }
121            else {
122            	emit(&sr->constraints, " ]");
123            }
124
125        break;
126
127        case nodeType_Attribute:
128            assert(p->u.an.attr != NULL);
129
130            translate(p->u.an.attr);
131            if(p->u.an.next != NULL) {
132                emit(w, ", ");
133                translate(p->u.an.next);
134            }
135        break;
136
137        case nodeType_Pair:
138            assert(p->u.pn.left != NULL);
139            assert(p->u.pn.right != NULL);
140
141            attribute_name = p->u.pn.left;
142
143            translate(p->u.pn.left);
144            emit(w, "::");
145            translate(p->u.pn.right);
146        break;
147
148        case nodeType_Constraint:
149            assert(p->u.cnsn.value != NULL);
150            // prolog variable, dont care about result, just make sure it's set
151            emit(w, "_");
152
153            w = &sr->constraints;
154            char* operator;
155            switch(p->u.cnsn.op) {
156                case constraint_GT:
157                    operator = ">";
158                break;
159                case constraint_GE:
160                    operator = ">=";
161                break;
162                case constraint_LT:
163                    operator = "<";
164                break;
165                case constraint_LE:
166                    operator = "=<";
167                break;
168                case constraint_EQ:
169                    operator = "==";
170                break;
171                case constraint_NE:
172                    operator = "=/=";
173                break;
174                case constraint_REGEX:
175                	operator = "match";
176				break;
177                default:
178                    assert(!"OP code not supported");
179                break;
180            }
181            emit(w, "constraint(");
182            translate(attribute_name);
183            emit(w, ", ");
184            emit(w, "'%s'", operator);
185            emit(w, ", ");
186            translate(p->u.cnsn.value);
187            emit(w, "), ");
188            w = &sr->attributes;
189        break;
190
191        case nodeType_Float:
192            emit(w, "%f", p->u.fn.value);
193        break;
194
195        case nodeType_Boolean:
196            if(p->u.bn.value) {
197            	emit(w, "true");
198            }
199            else {
200            	emit(w, "false");
201            }
202        break;
203
204        case nodeType_Constant:
205            emit(w, "%d", p->u.cn.value);
206        break;
207
208        case nodeType_String:
209            emit(w, "\'");
210            emit(w, p->u.sn.str);
211            emit(w, "\'");
212        break;
213
214        case nodeType_Ident:
215            emit(w, p->u.in.str);
216        break;
217
218        case nodeType_Unset:
219        	assert(!"nodeType_Unset");
220		break;
221   }
222
223}
224
225
226static void walk_attributes(struct ast_object* ast) {
227	struct ast_object* attr = ast->u.on.attrs;
228
229	while(attr != NULL) {
230		assert(attr->type == nodeType_Attribute);
231
232		struct ast_object* pair = attr->u.an.attr;
233		assert(pair != NULL);
234		assert(pair->type == nodeType_Pair);
235
236		struct ast_object* left = pair->u.pn.left;
237		struct ast_object* right = pair->u.pn.right;;
238		assert(left != NULL);
239		assert(right != NULL);
240
241
242		attr = attr->u.an.next;
243	}
244}
245
246void transform_query(char* obj)
247{
248
249	struct ast_object* ast = NULL;
250	errval_t err = generate_ast(obj, &ast);
251	if(err == 0) {
252	    printf("AST seems ok, translate...\n");
253        sr = malloc(sizeof(struct skb_record));
254        memset(sr, 0, sizeof(struct skb_record));
255        translate(ast);
256	}
257	else {
258	    assert(!"ast generation failed");
259	}
260	//free_ast(ast);
261}
262
263
264int main(int argc, char** argv)
265{
266	transform_query("spawn.1.ready");
267	printf("result: %s:\n\t%s\n\t%s\n", sr->name.output, sr->attributes.output, sr->constraints.output);
268
269	/*transform_query("obj2 {}");
270	printf("result: %s:\n\t%s\n\t%s\n", sr->name.output, sr->attributes.output, sr->constraints.output);
271
272	transform_query("obj3 { int: -11, fl: 12.0}");
273	printf("result: %s:\n\t%s\n\t%s\n", sr->name.output, sr->attributes.output, sr->constraints.output);
274
275	transform_query("obj4 { int: 12, fl: .0012321, fl2: .22123100 }");
276	printf("result: %s:\n\t%s\n\t%s\n", sr->name.output, sr->attributes.output, sr->constraints.output);
277
278	transform_query("obj5 { reference: bla, integer: 12, str: '[]String!@#%^&*$&^*(_)(-=\\'', float: 12.0, bool: true }");
279	printf("result: %s:\n\t%s\n\t%s\n", sr->name.output, sr->attributes.output, sr->constraints.output);
280
281	transform_query("obj5 { str1: 'String1', str2: 'String2' }");
282	printf("result: %s:\n\t%s\n\t%s\n", sr->name.output, sr->attributes.output, sr->constraints.output);
283
284	//transform_query("obj7 { c1: < 10, c1: > 11.0, c3: == 0, c4: >= 0, c5: <= .123 }");
285	//printf("result: %s:\n\t%s\n\t%s\n", sr->name.output, sr->attributes.output, sr->constraints.output);
286
287	transform_query("obj7 { c1: r'^12.*ab$', c2: r'^ \\\\ ab*ab$  asd \\naasdf' }");
288	printf("result: %s:\n\t%s\n\t%s\n", sr->name.output, sr->attributes.output, sr->constraints.output);
289*/
290    return 0;
291}
292#endif
293