#include "prodsys.h" int production_system(char *context) { int hit_number = 0, hits[L], i = 0, interpreting_context = 1, lowest = L, no_hits = 1, reading_rules = 1, result = 1, rule_number = 1; char rule[L]; while(interpreting_context){ for(i=0; i<L; i++) hits[i] = LIMIT; hit_number = 0; no_hits = 1; rule_number = 1; reading_rules = 1; while(reading_rules){ reading_rules = read_a_rule(rule_number, rule); rule_number++; if(is_a_hit(context, rule)){ no_hits = 0; hits[hit_number++] = rule_number-1; } } /* ends while reading_rules */ if(!no_hits){ /* deactivate any hit whose action adds a duplicate to the context */ for(i=0; i<L; i++){ if(hits[i] != LIMIT){ read_a_rule(hits[i], rule); if(is_a_duplicate(context, rule)) hits[i] = LIMIT; } /* ends if hits */ } /* ends loop through hits */ lowest = lowest_number(hits); if(lowest == LIMIT){ no_hits = 1; } /* ends if lowest == LIMIT */ else{ fire_rule(context, lowest); } /* ends else lowest != LIMIT */ } /* ends if not no_hits */ if(no_hits) interpreting_context = 0; } /* ends while */ return(result); } /* ends production_system */ /*********************************/ /*********************************/ int read_a_rule(int rule_number, char *answer) { char *there, rule[L]; FILE *rule_file; int i = 1, result = 1; rule_file = fopen(RULES_FILE, "rt"); if(rule_file == NULL) printf("\nERROR Could not open file %s", RULES_FILE); while(i <= rule_number){ if(fgets(rule, L, rule_file) == NULL){ i = rule_number * 100; result = 0; } /* did we read a rule or a comment or a blank line? No COMMENT and IF means we hit a rule */ there = strstr(rule, "COMMENT"); if(there != NULL){ } else{ /* no COMMENT */ there = strstr(rule, "IF"); if(there != NULL){ i++; } /* ends if there */ } /* ends else no COMMENT */ } /* ends while */ fclose(rule_file); strcpy(answer, rule); return(result); } /* ends read_a_rule */ /*********************************/ /*********************************/ int is_a_hit(char *context, char *rule) { int a = 0, b = 0, hit = 0, logical_case = 6; char *and_there, *and_not_there, *not_there, *or_there, *or_not_there, *there, *there1, *there2, *there3, word[L], word1[L], word2[L], word3[L]; and_there = strstr(rule, " AND "); and_not_there = strstr(rule, "AND_NOT"); not_there = strstr(rule, " NOT "); or_there = strstr(rule, " OR "); or_not_there = strstr(rule, "OR_NOT"); if( (and_there != NULL) && (and_not_there == NULL)) logical_case = 1; if( (and_there == NULL) && (and_not_there != NULL)) logical_case = 2; if( (and_there != NULL) && (and_not_there != NULL)) logical_case = 7; if(not_there != NULL) logical_case = 3; if( (or_there != NULL) && (or_not_there == NULL)) logical_case = 4; if( (or_there == NULL) && (or_not_there != NULL)) logical_case = 5; if( (or_there != NULL) && (or_not_there != NULL)) logical_case = 8; switch(logical_case){ case 1: /* AND */ /* 1a IF a AND b THEN z */ /* 1b IF a AND b AND c THEN z */ b = get_next_word(rule, word, &a); b = get_next_word(rule, word1, &a); b = get_next_word(rule, word, &a); b = get_next_word(rule, word2, &a); b = get_next_word(rule, word, &a); /* case 1a */ if(strcmp(word, "AND") != 0){ there1 = strstr(context, word1); there2 = strstr(context, word2); if((there1 != NULL) && (there2 != NULL)) hit = 1; } /* ends if case 1a */ /* case 1b */ else{ b = get_next_word(rule, word3, &a); there1 = strstr(context, word1); there2 = strstr(context, word2); there3 = strstr(context, word3); if((there1 != NULL) && (there2 != NULL) && (there3 != NULL)) hit = 1; } /* ends else case 1b */ break; case 2: /* AND_NOT IF a AND_NOT b THEN z */ b = get_next_word(rule, word, &a); b = get_next_word(rule, word1, &a); b = get_next_word(rule, word, &a); b = get_next_word(rule, word2, &a); there1 = strstr(context, word1); there2 = strstr(context, word2); if((there1 != NULL) && (there2 == NULL)) hit = 1; break; case 3: /* NOT IF NOT a THEN b */ b = get_next_word(rule, word, &a); b = get_next_word(rule, word, &a); there = strstr(context, word); if(there == NULL) hit = 1; break; case 4: /* OR IF a OR b THEN z */ /* 4a IF a OR b THEN z */ /* 4b IF a OR b OR c THEN z */ b = get_next_word(rule, word, &a); b = get_next_word(rule, word1, &a); b = get_next_word(rule, word, &a); b = get_next_word(rule, word2, &a); b = get_next_word(rule, word, &a); /* case 4a */ if(strcmp(word, "AND") != 0){ there1 = strstr(context, word1); there2 = strstr(context, word2); if((there1 != NULL) || (there2 != NULL)) hit = 1; } /* ends if case 4a */ /* case 4b */ else{ b = get_next_word(rule, word3, &a); there1 = strstr(context, word1); there2 = strstr(context, word2); there3 = strstr(context, word3); if((there1 != NULL) || (there2 != NULL) || (there3 != NULL)) hit = 1; } /* ends else case 4b */ break; case 5: /* OR_NOT IF a OR_NOT b THEN z */ b = get_next_word(rule, word, &a); b = get_next_word(rule, word1, &a); b = get_next_word(rule, word, &a); b = get_next_word(rule, word2, &a); there1 = strstr(context, word1); there2 = strstr(context, word2); if((there1 != NULL) || (there2 == NULL)) hit = 1; break; case 6: /* simplest, IF x THEN y */ b = get_next_word(rule, word, &a); b = get_next_word(rule, word, &a); there = strstr(context, word); if(there != NULL) hit = 1; break; case 7: /* complex AND_NOT */ /* IF a AND b AND_NOT c THEN z */ b = get_next_word(rule, word, &a); b = get_next_word(rule, word1, &a); b = get_next_word(rule, word, &a); b = get_next_word(rule, word2, &a); b = get_next_word(rule, word, &a); b = get_next_word(rule, word3, &a); there1 = strstr(context, word1); there2 = strstr(context, word2); there3 = strstr(context, word3); if((there1 != NULL) && (there2 != NULL) && (there3 == NULL)) hit = 1; break; case 8: /* complex OR_NOT */ /* IF a OR b OR_NOT c THEN z */ b = get_next_word(rule, word, &a); b = get_next_word(rule, word1, &a); b = get_next_word(rule, word, &a); b = get_next_word(rule, word2, &a); b = get_next_word(rule, word, &a); b = get_next_word(rule, word3, &a); there1 = strstr(context, word1); there2 = strstr(context, word2); there3 = strstr(context, word3); if((there1 != NULL) || (there2 != NULL) || (there3 == NULL)) hit = 1; break; default: printf("\ndefault fall through"); break; } /* ends switch logical_case */ return(hit); } /* ends is_a_hit */ /*********************************/ /*********************************/ /* this returns 1 if hits end of line 0 if not */ int get_next_word(char *line, char *next_word, int *place) { int i = 0, j = 0, not_done = 1, result = 0; next_word[0] = '\0'; i = *place; while(not_done){ if(line[i] == ' '){ if(j == 0) i++; else not_done = 0; } if(line[i] == '\n'){ not_done = 0; result = 1; } if(not_done) next_word[j++] = line[i++]; } /* ends while not_done */ next_word[j] = '\0'; *place = i; return(result); } /* ends get_next_word */ /*********************************/ /*********************************/ int is_a_duplicate(char *context, char *rule) /* if the result of the action in the rule is already in the context, return a 1 else return a 0 */ { char *there, word[L]; int a = 0, b = 0, not_done = 1, result = 0; while(not_done){ b = get_next_word(rule, word, &a); if(strcmp(word, "THEN") == 0){ b = get_next_word(rule, word, &a); not_done = 0; } /* ends if */ } /* ends while not_done */ there = strstr(context, word); if(there != NULL) result = 1; return(result); } /* ends is_a_duplicate */ /*********************************/ /*********************************/ int fire_rule(char *context, int number) { char rule[L], temp[L], word[L]; int a = 0, b = 0, not_done = 1; a = read_a_rule(number, rule); while(not_done){ b = get_next_word(rule, word, &a); if(strcmp(word, "THEN") == 0){ b = get_next_word(rule, word, &a); not_done = 0; } /* ends if */ } /* ends while not_done */ strcpy(temp, " "); strcpy(temp, word); strcat(temp, " "); strcat(temp, context); strcpy(context, temp); return(a); } /* ends fire_rule */ /*********************************/ /*********************************/ int lowest_number(int *list) { int i = 0, lowest = LIMIT; for(i=0; i<L; i++){ if(list[i] < lowest) lowest = list[i]; } return(lowest); } /* ends lowest_number */ /* End of File */