#define _GNU_SOURCE #include #include #include #include "lkb-tree.h" #include "lkb-protocol.h" static void adjoin_subtree(lkb_tree *tr, lkb_tree *sub); static void r_copy_lkb_tree(lkb_tree *t, lkb_tree *to); static void r_free_lkb_tree(lkb_tree *t) { int i; for(i=0;indaughters;i++) r_free_lkb_tree(t->daughters+i); free(t->daughters); free(t->root_name); } void free_lkb_tree(lkb_tree *t) { (*t->refcnt)--; if((*t->refcnt)<=0) { free(t->refcnt); free(t); } } static void r_copy_lkb_tree(lkb_tree *t, lkb_tree *to) { int i; *to = *t; to->root_name = strdup(to->root_name); if(to->sublabel_id)to->sublabel_id = strdup(to->sublabel_id); if(to->rule_id)to->rule_id = strdup(to->rule_id); to->daughters = malloc(sizeof(*t)*to->ndaughters); for(i=0;indaughters;i++) r_copy_lkb_tree(t->daughters+i, to->daughters+i); } lkb_tree *copy_lkb_tree(lkb_tree *t) { lkb_tree *to = malloc(sizeof(*t)); r_copy_lkb_tree(t, to); to->refcnt = t->refcnt; (*t->refcnt)++; return to; } #ifndef _GNU_SOURCE static int strnlen(char *str, int len) { int i; for(i=0;iid = tree_id_d; tr->edge_id = edge_id_d; tr->rule_id = rule_id_d; tr->root_name = tree_type_d; tr->sublabel_id = sublabel_id_d; tr->ndaughters = 0; tr->refcnt = malloc(sizeof(int)); *(tr->refcnt) = 1; //debug("tree id %d, type %s\n", tr->id, tr->root_name); do { c = tokenize(&p); if(c==' ')continue; if(c==']')break; p--; parse_protocol(&p, &subtree_type, (void**)&subtree); if(subtree_type != type_tree) { fprintf(stderr, "Subtree was not a tree (type %d)\n", subtree_type); goto done_tree; } adjoin_subtree(tr, subtree); } while(*p); //debug("tree finished\n"); done_tree: *TYPE = type_tree; *INPUT=p; if(!tr) { tr = (lkb_tree*)calloc(sizeof(lkb_tree), 1); tr->id = -1; tr->edge_id = -1; tr->rule_id = strdup("error-rule"); tr->root_name = strdup("*ERROR*"); tr->sublabel_id = 0; tr->ndaughters = 0; tr->refcnt = malloc(sizeof(int)); *(tr->refcnt) = 1; } *(lkb_tree**)DATA = tr; return 0; } static void adjoin_subtree(lkb_tree *tr, lkb_tree *sub) { tr->ndaughters++; tr->daughters = realloc(tr->daughters, sizeof(lkb_tree)*tr->ndaughters); tr->daughters[tr->ndaughters-1] = *sub; free(sub); } int parse_hierarchy(char **INPUT, int *TYPE, void **DATA) { char c, *p = *INPUT; struct lui_hierarchy *h = NULL; *DATA = NULL; c = tokenize(&p); if(c!='[') { fprintf(stderr, "Expected '[' opening hierarchy structure\n"); goto done; } #define EXPECT(cfieldtype, field, fieldtype, fieldname) \ cfieldtype field; \ int field##_type; \ parse_protocol(&p, &field##_type, (void**)&field); \ if(field##_type != fieldtype) { \ fprintf(stderr, fieldname " had wrong type (%d)\n", field##_type); goto done; } EXPECT(char*, name, type_string, "name of #H"); EXPECT(lui_list*, parlist, type_list, "supertype-list of #H"); EXPECT(lui_list*, sublist, type_list, "subtype-list of #H"); do { c = tokenize(&p); } while(c==' '); if(c!=']') { fprintf(stderr, "Expected ']' ending hierarchy structure ; got '%c' = %d\n", c, c); goto done; } if(parlist->type==-1)parlist->type=type_int; if(sublist->type==-1)sublist->type=type_int; if(parlist->type != type_int || sublist->type != type_int) { fprintf(stderr, "supertype and subtype lists for #H must be ints\n"); goto done; } h = calloc(sizeof(*h),1); h->name = name; h->npar = parlist->length; h->par = malloc(sizeof(int)*h->npar); int k; for(k=0;knpar;k++)h->par[k] = *(int*)&parlist->data[k]; h->nsub = sublist->length; h->sub = malloc(sizeof(int)*h->nsub); for(k=0;knsub;k++)h->sub[k] = *(int*)&sublist->data[k]; done:; *TYPE = type_hierarchy; *INPUT=p; if(!h) { h = calloc(sizeof(*h), 1); h->name = strdup("*ERROR*"); } *(struct lui_hierarchy**)DATA = h; return 0; } void free_hierarchy(struct lui_hierarchy *h) { if(h->par)free(h->par); if(h->sub)free(h->sub); free(h->name); free(h); }