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