#include #include #include "lkb-avm.h" #include "lkb-protocol.h" #include lkb_avm *convert_symbol_to_dag(char *sym) { lkb_avm *dag; dag = (lkb_avm*)calloc(sizeof(lkb_avm), 1); dag->type = sym; return dag; } lkb_avm_tag *lkb_tagdup(lkb_avm_tag *told) { lkb_avm_tag *tag; tag = malloc(sizeof(lkb_avm_tag)); *tag = *told; tag->name = strdup(told->name); return tag; } lkb_avm *find_attribute(lkb_avm *fs, char *attr, int *tt, lkb_avm_tag **tag) { int i; for(i=0;inattr;i++) if(!strcmp(fs->attr_name[i], attr)) { *tt = fs->attr_what[i]; *tag = fs->attr_tag[i]; return fs->attr_value[i]; } *tt = -1; *tag = 0; return 0; } void print_attribs(lkb_avm *fs) { int i; for(i=0;inattr;i++) printf("%s %p [tag %p] [type %d]\n", fs->attr_name[i], fs->attr_value[i], fs->attr_tag[i], fs->attr_what[i]); } extern char *first_feature, *rest_feature; extern char *current_path; void free_avm(lkb_avm *fs) { int i; free(fs->attr_what); for(i=0;inattr;i++) { free(fs->attr_name[i]); if(fs->attr_tag[i]) { free(fs->attr_tag[i]->name); free(fs->attr_tag[i]); } } free(fs->attr_name); free(fs->attr_tag); free(fs->attr_value); free(fs->attr_x); free(fs->attr_y); free(fs->attr_dx); free(fs->attr_dy); free(fs->attr_cycle); free(fs); } // unification failures parse_failure(char **INPUT, int *TYPE, void **DATA) { int what_type, id_type, path_type; char *what; lui_list *path; int id, ctx; char *p = *INPUT; char c; lkb_failure *f=0; *DATA = 0; //printf("parsing failure at %s\n", *INPUT); c = tokenize(&p); if(c!='[') { fprintf(stderr, "Expected '[' opening failure structure\n"); goto done_fail; } parse_protocol(&p, &what_type, (void**)&what); if(what_type != type_symbol && what_type != type_string) { fprintf(stderr, "`what' of failure was not a symbol (type %d)\n", what_type); goto done_fail; } parse_protocol(&p, &id_type, (void**)&id); if(id_type != type_int) { fprintf(stderr, "ID of failure was not a number (type %d)\n", id_type); goto done_fail; } parse_protocol(&p, &path_type, (void**)&path); if(path_type != type_list || (path->length && path->type != type_symbol && path->type != type_string)) { fprintf(stderr, "Path of failure was not a list of symbols (type %d)\n", path_type); goto done_fail; } // switch on which type of failure if(!strcasecmp(what, "type")) { if(parse_type_failure(&f, id, path, &p))goto done_fail; } else if(!strcasecmp(what, "cycle")) { if(parse_cycle_failure(&f, id, path, &p))goto done_fail; } else if(!strcasecmp(what, "constraint")) { if(parse_constraint_failure(&f, id, path, &p))goto done_fail; } else { fprintf(stderr, "Unknown unification failure `%s'\n", what); goto done_fail; } //printf("success parsing a `%s'-failure = %p\n", what, f); done_fail: *TYPE = type_failure; *INPUT=p; if(!f) { f = (lkb_failure*)calloc(sizeof(lkb_failure), 1); f->what = -1; } *(lkb_failure**)DATA = f; return 0; } int parse_type_failure(lkb_failure **F, int id, lui_list *path, char **INPUT) { char *type1, *type2; char c, *p = *INPUT; int ctx, type1_type, type2_type, ctx_type; lkb_failure *f; parse_protocol(&p, &type1_type, (void**)&type1); if(type1_type != type_symbol && type1_type != type_string) { fprintf(stderr, "Type1 of failure was not a symbol (type %d)\n", type1_type); return -1; } parse_protocol(&p, &type2_type, (void**)&type2); if(type2_type != type_symbol && type2_type != type_string) { fprintf(stderr, "Type2 of failure was not a symbol (type %d)\n", type2_type); return -1; } parse_protocol(&p, &ctx_type, (void**)&ctx); if(ctx_type != type_int) { fprintf(stderr, "Ctx of failure was not an int (type %d)\n", ctx_type); return -1; } f = (lkb_failure*)calloc(sizeof(lkb_failure), 1); f->what = ufail_no_glb; f->id = id; f->ctx = ctx; f->path = path; f->type1 = type1; f->type2 = type2; do { c = tokenize(&p); if(c==' ')continue; if(c==']')break; fprintf(stderr, "Extra garbage `%c' in failure record\n", c); return -1; } while(*p); *F = f; *INPUT=p; return 0; } int parse_cycle_failure(lkb_failure **F, int id, lui_list *path, char **INPUT) { lui_list *cycle; char c, *p = *INPUT; int ctx, cycle_type, ctx_type; lkb_failure *f; //printf("cycle parser at %s\n", *INPUT); parse_protocol(&p, &cycle_type, (void**)&cycle); if(cycle_type != type_list || (cycle->length && cycle->type != type_symbol && cycle->type != type_string)) { fprintf(stderr, "Cycle-path of failure was not a list of symbol (type %d)\n", cycle_type); return -1; } parse_protocol(&p, &ctx_type, (void**)&ctx); if(ctx_type != type_int) { fprintf(stderr, "Ctx of failure was not an int (type %d)\n", ctx_type); return -1; } //printf("cycle parser good\n"); f = (lkb_failure*)calloc(sizeof(lkb_failure), 1); f->what = ufail_cycle; f->id = id; f->ctx = ctx; f->path = path; f->cycle = cycle; do { c = tokenize(&p); if(c==' ')continue; if(c==']')break; fprintf(stderr, "Extra garbage `%c' in failure record\n", c); return -1; } while(*p); *F = f; *INPUT=p; return 0; } int parse_constraint_failure(lkb_failure **F, int id, lui_list *path, char **INPUT) { char *type1, *type2, *constraint; char c, *p = *INPUT; int ctx, type1_type, type2_type, constraint_type, ctx_type; lkb_failure *f; parse_protocol(&p, &type1_type, (void**)&type1); if(type1_type != type_symbol && type1_type != type_string) { fprintf(stderr, "Type1 of failure was not a symbol (type %d)\n", type1_type); return -1; } parse_protocol(&p, &type2_type, (void**)&type2); if(type2_type != type_symbol && type2_type != type_string) { fprintf(stderr, "Type2 of failure was not a symbol (type %d)\n", type2_type); return -1; } parse_protocol(&p, &constraint_type, (void**)&constraint); if(constraint_type != type_symbol && constraint_type != type_string) { fprintf(stderr, "Constraint of failure was not a symbol (type %d)\n", constraint_type); return -1; } parse_protocol(&p, &ctx_type, (void**)&ctx); if(ctx_type != type_int) { fprintf(stderr, "Ctx of failure was not an int (type %d)\n", ctx_type); return -1; } f = (lkb_failure*)calloc(sizeof(lkb_failure), 1); f->what = ufail_constraint; f->id = id; f->ctx = ctx; f->path = path; f->type1 = type1; f->type2 = type2; f->constraint = constraint; do { c = tokenize(&p); if(c==' ')continue; if(c==']')break; fprintf(stderr, "Extra garbage `%c' in failure record\n", c); return -1; } while(*p); *F = f; *INPUT=p; return 0; } /* AVM setup utilities */ extern char *list_type, *empty_list_type, *non_empty_list_type; extern char *first_feature, *rest_feature; extern lui_list hidden_features, hidden_types; extern lui_list collapsed_features, collapsed_types; int is_default_collapse_feature(char *attr) { int i; for(i=0;itype = dag_type_d; dag->nattr = 0; dag->path = 0; if(default_collapse)dag->expand = 0; else dag->expand = 1; //debug("dag type %p %s\n", dag->type, dag->type); save_path = current_path; do { c = tokenize(&p); if(c==' ')continue; if(c==0 || c==']')break; p--; parse_protocol(&p, &attr_name_type, (void**)&attr_name); if(attr_name_type != type_symbol) { fprintf(stderr, "Attribute name was not a symbol (type %d)\n", attr_name_type); goto error_dag; } if(attr_name[0])attr_name[strlen(attr_name)-1] = 0; p--; c = tokenize(&p); if(c==' ')c = tokenize(&p); if(c==0 || c==']')break; if(c=='<') { parse_protocol(&p, &tag_type, (void**)&tag); if(tag_type == type_int) sprintf(tagstr, "%d", (int)tag); else if(tag_type == type_symbol || tag_type == type_string) { if(strlen((char*)tag) > 63) ((char*)tag)[63] = 0; sprintf(tagstr, "%s", (char*)tag); } else //if(tag_type != type_int) { fprintf(stderr, "Tag was of unexpected type %d\n", tag_type); goto error_dag; } c = tokenize(&p); if(c!='>') { fprintf(stderr, "Tag was not closed by a '>')\n"); goto error_dag; } c = tokenize(&p); if(c==' ' || c==']') { p--; adjoin_dag_attribute(dag, attr_name, tagstr, 0, avm_tag, 0); continue; } if(c!='=') { fprintf(stderr, "Expected tag definition by '='\n"); goto error_dag; } } else *tagstr = 0; //tag = -1; p--; old_dc = default_collapse; // if this feature is marked as default-collapse, then collapse it! if(is_default_collapse_feature(attr_name))default_collapse = 1; else { // otherwise we'd like to by default expand, // but if this is a list inside a collapsed feature, keep it collapsed. if(strcmp(attr_name, first_feature) && strcmp(attr_name, rest_feature)) default_collapse = 0; } // if this is a default collapse type, say so if(is_default_collapse_type(dag->type)) { dag->expand = 0; default_collapse = 1; } current_path = strappend(current_path, attr_name); parse_protocol(&p, &subdag_type, (void**)&subdag); /*if(subdag_type == type_symbol && strcasecmp((char*)subdag, empty_list_type) && strcasecmp((char*)subdag, non_empty_list_type))*/ if(subdag_type == type_symbol || subdag_type == type_string) { subdag_type = type_dag; subdag = convert_symbol_to_dag((char*)subdag); } if(subdag_type == type_dag)subdag->path = current_path; else free(current_path); current_path = save_path; default_collapse = old_dc; if(is_default_hidden_feature(attr_name)) do_hide = 2; else do_hide = 0; if(subdag_type == type_symbol || subdag_type == type_string) { //debug("attribute %s terminal %s tag %s\n", attr_name, subdag, tagstr); if(is_default_hidden_type((char*)subdag))do_hide = 2; adjoin_dag_attribute(dag, attr_name, tagstr, subdag, avm_terminal, do_hide); } else if(subdag_type == type_dag) { //debug("attribute %s subdag %p tag %s\n", attr_name, subdag, tagstr); if(is_default_hidden_type(subdag->type))do_hide = 2; adjoin_dag_attribute(dag, attr_name, tagstr, subdag, avm_structure, do_hide); } else if(subdag_type == type_daglist) { //debug("attribute %s list %p tag %s\n", attr_name, subdag, tagstr); if(is_default_hidden_type(((lkb_avm_list*)subdag)->type[0]))do_hide = 2; adjoin_dag_attribute(dag, attr_name, tagstr, subdag, avm_list, do_hide); } else { fprintf(stderr, "Value dag for '%s' was not a dag (type %d)\n", attr_name, subdag_type); goto error_dag; } } while(*p); //debug("dag finished\n"); dag->attr_x = calloc(sizeof(int),dag->nattr); dag->attr_y = calloc(sizeof(int),dag->nattr); dag->attr_dx = calloc(sizeof(int),dag->nattr); dag->attr_dy = calloc(sizeof(int),dag->nattr); dag->attr_ldx = calloc(sizeof(int),dag->nattr); dag->attr_cycle = calloc(sizeof(lkb_failure*), dag->nattr); if(is_non_empty_list(dag))//!strcmp(dag->type, non_empty_list_type)) { ldag = convert_to_list(dag); if(!ldag)fprintf(stderr, "Unable to convert list dag to list format\n"); else { free_avm(dag); // XXX would be better to record this for togglable display *TYPE = type_daglist; *INPUT=p; *(lkb_avm_list**)DATA = ldag; return 0; } } else if(!strcmp(dag->type, empty_list_type)) { ldag = empty_avm_list(&subdag_type, 0); //ldag->list_type = 0; ldag->open_ended = 0; free_avm(dag); *TYPE = type_daglist; *INPUT=p; *(lkb_avm_list**)DATA = ldag; return 0; } else if(!strcmp(dag->type, list_type)) { ldag = empty_avm_list(&subdag_type, dag->type); //ldag->list_type = 1; ldag->open_ended = 1; free_avm(dag); *TYPE = type_daglist; *INPUT=p; *(lkb_avm_list**)DATA = ldag; return 0; } done_dag: *TYPE = type_dag; *INPUT=p; *(lkb_avm**)DATA = dag; return 0; error_dag: *TYPE = -1; *INPUT=p; *(lkb_avm**)DATA = 0; return -1; } lkb_avm_tag *make_str_tag(char *str, int def) { lkb_avm_tag *t = calloc(sizeof(*t), 1); t->name = malloc(16); sprintf(t->name, "%s", str); t->is_def = def; return t; } adjoin_dag_attribute(lkb_avm *dag, char *attr, char *tag, lkb_avm *subdag, int type, int hide) { dag->nattr++; dag->attr_what = realloc(dag->attr_what, dag->nattr*sizeof(dag->attr_what[0])); dag->attr_name = realloc(dag->attr_name, dag->nattr*sizeof(dag->attr_name[0])); dag->attr_tag = realloc(dag->attr_tag, dag->nattr*sizeof(dag->attr_tag[0])); dag->attr_value = realloc(dag->attr_value, dag->nattr*sizeof(dag->attr_value[0])); dag->attr_hide = realloc(dag->attr_hide, dag->nattr*sizeof(dag->attr_hide[0])); dag->attr_name[dag->nattr-1] = attr; dag->attr_tag[dag->nattr-1] = (*tag==0)?0:make_str_tag(tag, subdag?1:0); dag->attr_hide[dag->nattr-1] = hide; if(type == avm_terminal && !strcmp((char*)subdag, empty_list_type)) { free(subdag); dag->attr_what[dag->nattr-1] = avm_list; dag->attr_value[dag->nattr-1] = empty_avm_list(&type, 0); //((lkb_avm_list*)dag->attr_value[dag->nattr-1])->list_type = 0; ((lkb_avm_list*)dag->attr_value[dag->nattr-1])->open_ended = 0; } else if(type == avm_terminal && !strcmp((char*)subdag, list_type)) { free(subdag); dag->attr_what[dag->nattr-1] = avm_list; dag->attr_value[dag->nattr-1] = empty_avm_list(&type, non_empty_list_type); //((lkb_avm_list*)dag->attr_value[dag->nattr-1])->list_type = 1; ((lkb_avm_list*)dag->attr_value[dag->nattr-1])->open_ended = 1; } else { dag->attr_what[dag->nattr-1] = type; dag->attr_value[dag->nattr-1] = subdag; } }