Listing 3: Production system functions

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