#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 */