#define _GNU_SOURCE #include #include #include #include #include #include #include "tdl.h" #include "dag.h" #include "hash.h" #include "conf.h" #include "unicode.h" struct type_hierarchy *semi_th, *semi_p_th; enum { semi_variables = 1, semi_properties = 2, semi_roles = 3, semi_predicates = 4 }; int semi_mode = 0; int isoperator(char c) { if(c==':')return 1; if(c=='<')return 1; if(c==',')return 1; if(c=='[')return 1; if(c==']')return 1; if(c=='{')return 1; if(c=='}')return 1; if(c=='&')return 1; if(c=='.')return 1; else return 0; } struct type *semi_super;//, *semi_top; void semi_set_super(char *what) { if(!strcmp(what, "semi-predicate"))set_default_type_hierarchy(semi_th); else set_default_type_hierarchy(semi_p_th); if(!lookup_type(what)) { //printf("adding %s as a subtype of %p\n", what, semi_top); struct type *semi_top = lookup_type(semi_top_type); add_type_only(what, 1, &semi_top, 0); } semi_super = lookup_type(what); //semi_super = semi_top; } int process_semi_command(char *parent, int lnum, char *cmd) { if(0) {} else if(!strcasecmp(cmd, "variables:")) { semi_mode = semi_variables; semi_set_super("semi-variable"); } else if(!strcasecmp(cmd, "properties:")) { semi_mode = semi_properties; semi_set_super("semi-property"); } else if(!strcasecmp(cmd, "roles:")) { semi_mode = semi_roles; semi_super = NULL; } else if(!strcasecmp(cmd, "predicates:")) { semi_mode = semi_predicates; semi_set_super("semi-predicate"); } else { fprintf(stderr, "%s:%d: unknown SEMI command: `%s'\n", parent, lnum, cmd); exit(-1); } return 0; } char semi_peek(char **P) { char *p = *P; while(isspace(*p)) p++; return *p; } char *semi_tokenize(char **P, int *L) { char *p = *P; // skip to end of whitespace while(isspace(*p)) { if(*p=='\n')(*L)++; p++; } *P = p; // anything left? if(!*p)return NULL; // skip comments if(*p == ';') { while(*p && *p!='\n')p++; *P=p; return semi_tokenize(P,L); } // punctuation tokens are single letter tokens if(isoperator(*p)) { char *tok = malloc(2); tok[0]=*p++; tok[1]=0; *P=p; return tok; } // all other tokens extend until whitespace or a punctuation mark else { char *ts = p; // special case 1: ':' can appear inside an identifier (but cannot start one). // special case 2: '.' can appear inside an identifier (but cannot start or end one). while(*p && !isspace(*p) && (*p==':' || (*p=='.' && !isspace(p[1])) || !isoperator(*p)))p++; char *tok = malloc(p-ts+1); memcpy(tok,ts,p-ts); tok[p-ts]=0; *P=p; return tok; } } int ndefs, adefs; struct semi_def { char *name; int npar; char **par; int active; } *defs; void semi_define_immediately(char *name) { if(lookup_type(name))return; add_type_only(name, 1, &semi_super, 0); } semi_define(char *name, int npar, char **par) { if(ndefs+1 > adefs) { adefs = (adefs+1)*1.5; defs = realloc(defs, sizeof(struct semi_def)*adefs); } defs[ndefs].name = strdup(name); defs[ndefs].npar = npar; defs[ndefs].par = malloc(sizeof(char*)*npar); defs[ndefs].active = 0; memcpy(defs[ndefs].par, par, sizeof(char*)*npar); ndefs++; } struct type *semi_process_1_def(struct semi_def *d) { if(d->active) { if(d->active==2)return lookup_type(d->name); // already did this. fprintf(stderr, "ERROR: SEM-I: %s is part of a circular hierarchy\n", d->name); exit(-1); } d->active = 1; //printf("process definition of %s\n", d->name); assert(d->npar > 0); int j; struct type *par[d->npar]; for(j=0;jnpar;j++) { par[j] = lookup_type(d->par[j]); if(!par[j]) { int k; for(k=0;kpar[j]))break; if(k >= ndefs) { //fprintf(stderr, "ERROR: SEM-I: %s (parent of %s) undefined\n", d->par[j], d->name); //exit(-1); //printf("SEM-I: %s (parent of %s) undefined, adding implicitly at top of predicate hierarchy\n", d->par[j], d->name); add_type_only(d->par[j], 1, &semi_super, 0); par[j] = lookup_type(d->par[j]); } else par[j] = semi_process_1_def(&defs[k]); } assert(par[j] != NULL); } add_type_only(d->name, d->npar, par, 1); d->active = 2; return lookup_type(d->name); } void semi_process_definitions() { int i; // visit defs in an order s.t. parents are defined before subtypes for(i=0;i