#include <stdio.h> #include "term.h" #include "error.h" #define MAXSTRING 100 termlist parseargs(FILE *infile, int *length); int skipspaces(FILE *infile); void printtermlist(termlist tl); void freeterm(term t); void freelist(termlist tl); term parseterm(FILE *infile); char *stringCat(char *s1, char*s2); char *renamevar(char *var, int suffix); term renametermvars(term t,int suffix); termlist renametlistvars(termlist tl,int suffix); term parselist(FILE *infile); void printlist(term t); int skiptoendofcomment(FILE *infile); termlist parseargs(FILE *infile, int *length) { char next; termlist returnlist; next=skipspaces(infile); if (next == ')') { *length = 0; return NULL; } ungetc(next,infile); returnlist = (termlist) malloc(sizeof(struct _termlist)); returnlist->first = parseterm(infile); next = skipspaces(infile); if (next == ',') { returnlist->rest = parseargs(infile,length); *length += 1; } else if (next == ')' || next == '.') { returnlist->rest = NULL; *length = 1; ungetc(next,infile); } else { error("Parse Error \n"); } return returnlist; } int skiptoendofcomment(FILE *infile) { int next; next = getc(infile); for(;;) { if (next == EOF) return EOF; if (next == '*') { next = getc(infile); if (next == EOF) return EOF; if (next == '/') return getc(infile); } else { next = getc(infile); } } } int skipspaces(FILE *infile) { int next, next2; do { next = getc(infile); if (next==EOF) return EOF; if (next == '/') { if ((next2 = getc(infile)) == '*') { next = skiptoendofcomment(infile); if (next == EOF) return EOF; } else { ungetc(next2,infile); return next; } } } while (next == '\n' || next == ' ' || next == '\t'); return next; } term parseterm(FILE *infile) { char buffer[MAXSTRING]; char next; term returnterm; int i = 0; term tlistelem; next = skipspaces(infile); if (next == '[') { return parselist(infile); } do { buffer[i++] = next; next = getc(infile); } while (next != '\n' && next != ' ' && next != '\t' && next != ')' && next != '(' && next != '.' && next != ',' && next != ']' && next != '|'); buffer[i++] = '\0'; returnterm = (term) malloc(sizeof(struct _term)); returnterm->name = (char *) malloc(sizeof(char)*i); strcpy(returnterm->name,buffer); if ((returnterm->name[0] >= 'A' && returnterm->name[0] <= 'Z') || returnterm->name[0] == '_') { returnterm->variable = 1; returnterm->arity = 0; ungetc(next,infile); return returnterm; } else { returnterm->variable = 0; } if (next == '(') { returnterm->args = parseargs(infile, &(returnterm->arity)); if (skipspaces(infile) != ')') error("Parse Error: ) expected\n"); } else { returnterm->args = NULL; returnterm->arity = 0; ungetc(next,infile); } return returnterm; } void printtermlist(termlist tl) { if (tl != NULL) { printterm(tl->first); if (tl->rest != NULL) { printf(","); printtermlist(tl->rest); } } } void printterm(term t) { if (t == NULL) { printf("Empty Term"); } else { if (strcmp(t->name,".") == 0) { printf("["); printlist(t); printf("]"); } else { printf("%s",t->name); if (t->arity != 0) { printf("("); printtermlist(t->args); printf(")"); } } } } void freelist(termlist tl) { if (tl != NULL) { freeterm(tl->first); freelist(tl->rest); free(tl); } } void freeterm(term t) { if (t!= NULL) { free(t->name); freelist(t->args); free(t); } } termlist gettermlist(FILE *infile) { termlist tl; int dummy; dummy = skipspaces(infile); if (dummy == EOF) return NULL; ungetc(dummy,infile); tl = parseargs(infile,&dummy); if (skipspaces(infile) != '.') { error("Parse error: . expected\n"); } return tl; } term getterm(FILE *infile) { term t; t = parseterm(infile); if (skipspaces(infile) != '.') { error("Parse error: . expected\n"); } return t; } void printrule(rule t) { if (t == NULL) { printf("Empty Rule\n"); } else { printterm(t->consequent); if (t->antecedent == NULL) printf("."); else { printf(":-"); printtermlist(t->antecedent); printf("."); } } } void freerule(rule t) { if (t != NULL) { freeterm(t->consequent); freelist(t->antecedent); free(t); } } rule getrule(FILE *infile) { rule returnrule; termlist l; char next; int first; first = skipspaces(infile); if (first == EOF) return NULL; ungetc(first, infile); returnrule = (rule) malloc(sizeof(struct _rule)); returnrule->consequent = parseterm(infile); next = skipspaces(infile); if (next == '.') { returnrule->antecedent = NULL; return returnrule; } if (next != ':' || (char) getc(infile) != '-') { error("Error in parsing rule: :- expected\n"); return NULL; } returnrule->antecedent = parseargs(infile,&(returnrule->numantecedent)); if (skipspaces(infile) != '.') error("Error in parsing rule: . expected\n"); if (returnrule->consequent->variable) { error("Consequent needs to be a term, not a variable \n"); } for (l=returnrule->antecedent; l; l=l->rest) { if (l->first->variable) error("Antecedent cannot be a variable\n"); } return returnrule; } rule renamevars(rule r) { static int currentnum = -1; rule returnrule; currentnum++; returnrule = (rule) malloc(sizeof(struct _rule)); returnrule->consequent = renametermvars(r->consequent,currentnum); returnrule->antecedent = renametlistvars(r->antecedent,currentnum); return returnrule; } char *renamevar(char *var, int suffix) { char buffer[100]; sprintf(buffer,"_%d",suffix); return stringCat(var,buffer); } char *stringCat(char *s1, char*s2){ char *retval; retval = (char *) malloc(sizeof(char)*(strlen(s1)+strlen(s2)+1)); strcpy(retval,s1); strcat(retval,s2); return retval; } term renametermvars(term t,int suffix) { term returnterm; if (t == NULL) return NULL; returnterm = (term) malloc(sizeof(struct _term)); if (t->variable) { returnterm->variable = 1; returnterm->name = renamevar(t->name,suffix); returnterm->arity = 0; returnterm->args = NULL; } else { returnterm->variable = 0; returnterm->name = t->name; returnterm->arity = t->arity; returnterm->args = renametlistvars(t->args,suffix); } return returnterm; } termlist renametlistvars(termlist tl,int suffix){ termlist returnlist; if (tl == NULL) return NULL; returnlist = (termlist) malloc(sizeof(struct _termlist)); returnlist->first = renametermvars(tl->first,suffix); returnlist->rest = renametlistvars(tl->rest,suffix); return returnlist; } term parselist(FILE *infile) { term listelem; term listhead; char next; listhead =(term) malloc(sizeof(struct _term)); next = skipspaces(infile); if (next == ']') { listhead->name = (char *) malloc(3 * sizeof(char)); strcpy(listhead->name,"[]"); listhead->variable = 0; listhead->arity = 0; listhead->args = NULL; } else { ungetc(next,infile); listelem = parseterm(infile); listhead->name = (char *) malloc(2 * sizeof(char)); strcpy(listhead->name,"."); listhead->variable = 0; listhead->arity = 2; listhead->args = (termlist) malloc(sizeof(struct _termlist)); listhead->args->rest = (termlist) malloc(sizeof(struct _termlist)); listhead->args->rest->rest = NULL; listhead->args->first = listelem; next = skipspaces(infile); if (next == ',') { listhead->args->rest->first = parselist(infile); } else if (next == '|') { listhead->args->rest->first = parseterm(infile); if (skipspaces(infile) != ']') error("Parse error: ] expected\n"); } else if (next == ']') { ungetc(next,infile); listhead->args->rest->first = parselist(infile); } } return listhead; } void printlist(term t) { if (strcmp(t->name,".") != 0) { printf("|"); printterm(t); return; } printterm(t->args->first); if (strcmp(t->args->rest->first->name,"[]") != 0) printf(","); printlist(t->args->rest->first); }