Example #1
0
globle struct lhsParseNode *DeftemplateLHSParse(
  void *theEnv,
  char *readSource,
  struct deftemplate *theDeftemplate)
  {
   struct lhsParseNode *head, *firstSlot;
   struct token theToken;
   int error;
   
   /*===============================================================*/
   /* Make sure the deftemplate name is not connected to subfields. */
   /*===============================================================*/

   GetToken(theEnv,readSource,&theToken);
   if ((theToken.type == OR_CONSTRAINT) || (theToken.type == AND_CONSTRAINT))
     {
      SyntaxErrorMessage(theEnv,(char*)"deftemplate patterns");
      return(NULL);
     }

   /*===================================================*/
   /* Create the pattern node for the deftemplate name. */
   /*===================================================*/

   head = GetLHSParseNode(theEnv);
   head->type = SF_WILDCARD;
   head->negated = FALSE;
   head->exists = FALSE;
   head->index = 0;
   head->slotNumber = 1;
   head->bottom = GetLHSParseNode(theEnv);
   head->bottom->type = SYMBOL;
   head->bottom->negated = FALSE;
   head->bottom->exists = FALSE;
   head->bottom->value = (void *) theDeftemplate->header.name;

   /*==========================================*/
   /* Get the other fields in the deftemplate. */
   /*==========================================*/

   error = FALSE;
   firstSlot = GetLHSSlots(theEnv,readSource,&theToken,theDeftemplate,&error);
   if (error)
     {
      ReturnLHSParseNodes(theEnv,firstSlot);
      ReturnLHSParseNodes(theEnv,head);
      return(NULL);
     }

   /*=========================*/
   /* Return the LHS pattern. */
   /*=========================*/

   head->right = firstSlot;
   return(head);
  }
Example #2
0
globle struct lhsParseNode *GetExpressionVarConstraints(
  struct lhsParseNode *theExpression)
  {
   struct lhsParseNode *list1 = NULL, *list2;

   for (; theExpression != NULL; theExpression = theExpression->bottom)
     {
      if (theExpression->right != NULL)
        {
         list2 = GetExpressionVarConstraints(theExpression->right);
         list1 = AddToVariableConstraints(list2,list1);
        }

      if (theExpression->type == SF_VARIABLE)
        {
         list2 = GetLHSParseNode();
         if (theExpression->referringNode != NULL)
           { list2->type = theExpression->referringNode->type; }
         else
           { list2->type = SF_VARIABLE; }
         list2->value = theExpression->value;
         list2->derivedConstraints = TRUE;
         list2->constraints = CopyConstraintRecord(theExpression->constraints);
         list1 = AddToVariableConstraints(list2,list1);
        }
     }

   return(list1);
  }
Example #3
0
static struct lhsParseNode *UnionVariableConstraints(
  struct lhsParseNode *list1,
  struct lhsParseNode *list2)
  {
   struct lhsParseNode *list3 = NULL, *trace, *temp;

   /*===================================*/
   /* Loop through all of the variables */
   /* in the first list.                */
   /*===================================*/

   while (list1 != NULL)
     {
      /*=============================================*/
      /* Search for the variable in the second list. */
      /*=============================================*/

      for (trace = list2; trace != NULL; trace = trace->right)
        {
         /*============================================*/
         /* If the variable is found in both lists,    */
         /* union the constraints and add the variable */
         /* to the new list being constructed.         */
         /*============================================*/

         if (list1->value == trace->value)
           {
            temp = GetLHSParseNode();
            temp->derivedConstraints = TRUE;
            temp->value = list1->value;
            temp->constraints = UnionConstraints(list1->constraints,trace->constraints);
            temp->right = list3;
            list3 = temp;
            break;
           }
        }

      /*==============================*/
      /* Move on to the next variable */
      /* in the first list.           */
      /*==============================*/

      temp = list1->right;
      list1->right = NULL;
      ReturnLHSParseNodes(list1);
      list1 = temp;
     }

   /*====================================*/
   /* Free the items in the second list. */
   /*====================================*/

   ReturnLHSParseNodes(list2);

   /*======================*/
   /* Return the new list. */
   /*======================*/

   return(list3);
  }
Example #4
0
globle struct lhsParseNode *CreateInitialFactPattern(
  void *theEnv)
  {
   struct lhsParseNode *topNode;
   struct deftemplate *theDeftemplate;
   int count;
   
   /*==================================*/
   /* If the initial-fact deftemplate  */
   /* doesn't exist, then create it.   */
   /*==================================*/

   theDeftemplate = (struct deftemplate *)
                    FindImportedConstruct(theEnv,"deftemplate",NULL,"initial-fact",
                                          &count,TRUE,NULL);
   if (theDeftemplate == NULL)
     {
      PrintWarningID(theEnv,"FACTLHS",1,FALSE);
      EnvPrintRouter(theEnv,WWARNING,"Creating implied initial-fact deftemplate in module ");
      EnvPrintRouter(theEnv,WWARNING,EnvGetDefmoduleName(theEnv,EnvGetCurrentModule(theEnv)));
      EnvPrintRouter(theEnv,WWARNING,".\n");
      EnvPrintRouter(theEnv,WWARNING,"  You probably want to import this deftemplate from the MAIN module.\n");
      CreateImpliedDeftemplate(theEnv,(SYMBOL_HN *) EnvAddSymbol(theEnv,"initial-fact"),FALSE);
     }

   /*====================================*/
   /* Create the (initial-fact) pattern. */
   /*====================================*/

   topNode = GetLHSParseNode(theEnv);
   topNode->type = SF_WILDCARD;
   topNode->index = 0;
   topNode->slotNumber = 1;

   topNode->bottom = GetLHSParseNode(theEnv);
   topNode->bottom->type = SYMBOL;
   topNode->bottom->value = (void *) EnvAddSymbol(theEnv,"initial-fact");

   /*=====================*/
   /* Return the pattern. */
   /*=====================*/

   return(topNode);
  }
Example #5
0
static struct lhsParseNode *TestPattern(
  void *theEnv,
  EXEC_STATUS,
  char *readSource,
  int *error)
  {
   struct lhsParseNode *theNode;
   struct token theToken;
   struct expr *theExpression;

   /*================================================*/
   /* Create the data specification for the test CE. */
   /*================================================*/

   SavePPBuffer(theEnv,execStatus," ");
   theNode = GetLHSParseNode(theEnv,execStatus);
   theNode->type = TEST_CE;
   theExpression = Function0Parse(theEnv,execStatus,readSource);
   theNode->expression = ExpressionToLHSParseNodes(theEnv,execStatus,theExpression);
   ReturnExpression(theEnv,execStatus,theExpression);

   if (theNode->expression == NULL)
     {
      *error = TRUE;
      ReturnLHSParseNodes(theEnv,execStatus,theNode);
      return(NULL);
     }

   /*=========================================================*/
   /* Check for the closing right parenthesis of the test CE. */
   /*=========================================================*/

   GetToken(theEnv,execStatus,readSource,&theToken);
   if (theToken.type != RPAREN)
     {
      SyntaxErrorMessage(theEnv,execStatus,"test conditional element");
      *error = TRUE;
      ReturnLHSParseNodes(theEnv,execStatus,theNode);
      return(NULL);
     }

   /*=====================*/
   /* Return the test CE. */
   /*=====================*/

   return(theNode);
  }
Example #6
0
static struct lhsParseNode *LiteralRestrictionParse(
  char *readSource,
  struct token *theToken,
  int *error)
  {
   struct lhsParseNode *topNode;
   struct expr *theExpression;

   /*============================================*/
   /* Create a node to represent the constraint. */
   /*============================================*/

   topNode = GetLHSParseNode();

   /*=================================================*/
   /* Determine if the constraint has a '~' preceding */
   /* it. If it  does, then the field is negated      */
   /* (e.g. ~red means "not the constant red."        */
   /*=================================================*/

   if (theToken->type == NOT_CONSTRAINT)
     {
      GetToken(readSource,theToken);
      topNode->negated = TRUE;
     }
   else
     { topNode->negated = FALSE; }

   /*===========================================*/
   /* Determine if the constraint is one of the */
   /* recognized types. These are ?variables,   */
   /* symbols, strings, numbers, :(expression), */
   /* and =(expression).                        */
   /*===========================================*/

   topNode->type = theToken->type;

   /*============================================*/
   /* Any symbol is valid, but an = signifies a  */
   /* return value constraint and an : signifies */
   /* a predicate constraint.                    */
   /*============================================*/

   if (theToken->type == SYMBOL)
     {
      /*==============================*/
      /* If the symbol is an =, parse */
      /* a return value constraint.   */
      /*==============================*/

      if (strcmp(ValueToString(theToken->value),"=") == 0)
        {
         theExpression = Function0Parse(readSource);
         if (theExpression == NULL)
           {
            *error = TRUE;
            ReturnLHSParseNodes(topNode);
            return(NULL);
           }
         topNode->type = RETURN_VALUE_CONSTRAINT;
         topNode->expression = ExpressionToLHSParseNodes(theExpression);
         ReturnExpression(theExpression);
        }

      /*=============================*/
      /* If the symbol is a :, parse */
      /* a predicate constraint.     */
      /*=============================*/

      else if (strcmp(ValueToString(theToken->value),":") == 0)
        {
         theExpression = Function0Parse(readSource);
         if (theExpression == NULL)
           {
            *error = TRUE;
            ReturnLHSParseNodes(topNode);
            return(NULL);
           }
         topNode->type = PREDICATE_CONSTRAINT;
         topNode->expression = ExpressionToLHSParseNodes(theExpression);
         ReturnExpression(theExpression);
        }

      /*==============================================*/
      /* Otherwise, treat the constraint as a symbol. */
      /*==============================================*/

      else
        { topNode->value = theToken->value; }
     }

   /*=====================================================*/
   /* Single and multifield variables and float, integer, */
   /* string, and instance name constants are also valid. */
   /*=====================================================*/

   else if ((theToken->type == SF_VARIABLE)  ||
            (theToken->type == MF_VARIABLE)  ||
            (theToken->type == FLOAT) ||
            (theToken->type == INTEGER) ||
            (theToken->type == STRING) ||
            (theToken->type == INSTANCE_NAME))
     { topNode->value = theToken->value; }

   /*===========================*/
   /* Anything else is invalid. */
   /*===========================*/

   else
     {
      SyntaxErrorMessage("defrule");
      *error = TRUE;
      ReturnLHSParseNodes(topNode);
      return(NULL);
     }

   /*===============================*/
   /* Return the parsed constraint. */
   /*===============================*/

   return(topNode);
  }
Example #7
0
static struct lhsParseNode *ConjuctiveRestrictionParse(
  char *readSource,
  struct token *theToken,
  int *error)
  {
   struct lhsParseNode *bindNode;
   struct lhsParseNode *theNode, *nextOr, *nextAnd;
   int connectorType;

   /*=====================================*/
   /* Get the first node and determine if */
   /* it is a binding variable.           */
   /*=====================================*/

   theNode = LiteralRestrictionParse(readSource,theToken,error);

   if (*error == TRUE)
     { return(NULL); }

   GetToken(readSource,theToken);

   if (((theNode->type == SF_VARIABLE) || (theNode->type == MF_VARIABLE)) &&
       (theNode->negated == FALSE) &&
       (theToken->type != OR_CONSTRAINT))
     {
      theNode->bindingVariable = TRUE;
      bindNode = theNode;
      nextOr = NULL;
      nextAnd = NULL;
     }
   else
     {
      bindNode = GetLHSParseNode();
      if (theNode->type == MF_VARIABLE) bindNode->type = MF_WILDCARD;
      else bindNode->type = SF_WILDCARD;
      bindNode->negated = FALSE;
      bindNode->bottom = theNode;
      nextOr = theNode;
      nextAnd = theNode;
     }

   /*===================================*/
   /* Process the connected constraints */
   /* within the constraint             */
   /*===================================*/

   while ((theToken->type == OR_CONSTRAINT) || (theToken->type == AND_CONSTRAINT))
     {
      /*==========================*/
      /* Get the next constraint. */
      /*==========================*/

      connectorType = theToken->type;

      GetToken(readSource,theToken);
      theNode = LiteralRestrictionParse(readSource,theToken,error);

      if (*error == TRUE)
        {
         ReturnLHSParseNodes(bindNode);
         return(NULL);
        }

      /*=======================================*/
      /* Attach the new constraint to the list */
      /* of constraints for this field.        */
      /*=======================================*/

      if (connectorType == OR_CONSTRAINT)
        {
         if (nextOr == NULL)
           { bindNode->bottom = theNode; }
         else
           { nextOr->bottom = theNode; }
         nextOr = theNode;
         nextAnd = theNode;
        }
      else if (connectorType == AND_CONSTRAINT)
        {
         if (nextAnd == NULL)
           {
            bindNode->bottom = theNode;
            nextOr = theNode;
           }
         else
           { nextAnd->right = theNode; }
         nextAnd = theNode;
        }
      else
        {
         SystemError("RULEPSR",1);
         ExitRouter(EXIT_FAILURE);
        }

      /*==================================================*/
      /* Determine if any more restrictions are connected */
      /* to the current list of restrictions.             */
      /*==================================================*/

      GetToken(readSource,theToken);
     }

   /*==========================================*/
   /* Check for illegal mixing of single and   */
   /* multifield values within the constraint. */
   /*==========================================*/

   if (CheckForVariableMixing(bindNode))
     {
      *error = TRUE;
      ReturnLHSParseNodes(bindNode);
      return(NULL);
     }

   /*========================*/
   /* Return the constraint. */
   /*========================*/

   return(bindNode);
  }
Example #8
0
struct lhsParseNode *RestrictionParse(
  char *readSource,
  struct token *theToken,
  int multifieldSlot,
  struct symbolHashNode *theSlot,
  int slotNumber,
  CONSTRAINT_RECORD *theConstraints,
  int position)
  {
   struct lhsParseNode *topNode = NULL, *lastNode = NULL, *nextNode;
   int numberOfSingleFields = 0;
   int numberOfMultifields = 0;
   int startPosition = position;
   int error = FALSE;
   CONSTRAINT_RECORD *tempConstraints;

   /*==================================================*/
   /* Keep parsing fields until a right parenthesis is */
   /* encountered. This will either indicate the end   */
   /* of an instance or deftemplate slot or the end of */
   /* an ordered fact.                                 */
   /*==================================================*/

   while (theToken->type != RPAREN)
     {
      /*========================================*/
      /* Look for either a single or multifield */
      /* wildcard or a conjuctive restriction.  */
      /*========================================*/

      if ((theToken->type == SF_WILDCARD) ||
          (theToken->type == MF_WILDCARD))
        {
         nextNode = GetLHSParseNode();
         nextNode->type = theToken->type;
         nextNode->negated = FALSE;
         GetToken(readSource,theToken);
        }
      else
        {
         nextNode = ConjuctiveRestrictionParse(readSource,theToken,&error);
         if (nextNode == NULL)
           {
            ReturnLHSParseNodes(topNode);
            return(NULL);
           }
        }

      /*========================================================*/
      /* Fix up the pretty print representation of a multifield */
      /* slot so that the fields don't run together.            */
      /*========================================================*/

      if ((theToken->type != RPAREN) && (multifieldSlot == TRUE))
        {
         PPBackup();
         SavePPBuffer(" ");
         SavePPBuffer(theToken->printForm);
        }

      /*========================================*/
      /* Keep track of the number of single and */
      /* multifield restrictions encountered.   */
      /*========================================*/

      if ((nextNode->type == SF_WILDCARD) || (nextNode->type == SF_VARIABLE))
        { numberOfSingleFields++; }
      else
        { numberOfMultifields++; }

      /*===================================*/
      /* Assign the slot name and indices. */
      /*===================================*/

      nextNode->slot = theSlot;
      nextNode->slotNumber = slotNumber;
      nextNode->index = position++;

      /*==============================================*/
      /* If we're not dealing with a multifield slot, */
      /* attach the constraints directly to the node  */
      /* and return.                                  */
      /*==============================================*/

      if (! multifieldSlot)
        {
         if (theConstraints == NULL)
           {
            if (nextNode->type == SF_VARIABLE)
              { nextNode->constraints = GetConstraintRecord(); }
            else nextNode->constraints = NULL;
           }
         else nextNode->constraints = theConstraints;
         return(nextNode);
        }

      /*====================================================*/
      /* Attach the restriction to the list of restrictions */
      /* already parsed for this slot or ordered fact.      */
      /*====================================================*/

      if (lastNode == NULL) topNode = nextNode;
      else lastNode->right = nextNode;

      lastNode = nextNode;
     }

   /*=====================================================*/
   /* Once we're through parsing, check to make sure that */
   /* a single field slot was given a restriction. If the */
   /* following test fails, then we know we're dealing    */
   /* with a multifield slot.                             */
   /*=====================================================*/

   if ((topNode == NULL) && (! multifieldSlot))
     {
      SyntaxErrorMessage("defrule");
      return(NULL);
     }

   /*===============================================*/
   /* Loop through each of the restrictions in the  */
   /* list of restrictions for the multifield slot. */
   /*===============================================*/

   for (nextNode = topNode; nextNode != NULL; nextNode = nextNode->right)
     {
      /*===================================================*/
      /* Assign a constraint record to each constraint. If */
      /* the slot has an explicit constraint, then copy    */
      /* this and store it with the constraint. Otherwise, */
      /* create a constraint record for a single field     */
      /* constraint and skip the constraint modifications  */
      /* for a multifield constraint.                      */
      /*===================================================*/

      if (theConstraints == NULL)
        {
         if (nextNode->type == SF_VARIABLE)
           { nextNode->constraints = GetConstraintRecord(); }
         else
           { continue; }
        }
      else
        { nextNode->constraints = CopyConstraintRecord(theConstraints); }

      /*==========================================*/
      /* Remove the min and max field constraints */
      /* for the entire slot from the constraint  */
      /* record for this single constraint.       */
      /*==========================================*/

      ReturnExpression(nextNode->constraints->minFields);
      ReturnExpression(nextNode->constraints->maxFields);
      nextNode->constraints->minFields = GenConstant(SYMBOL,NegativeInfinity);
      nextNode->constraints->maxFields = GenConstant(SYMBOL,PositiveInfinity);
      nextNode->derivedConstraints = TRUE;

      /*====================================================*/
      /* If we're not dealing with a multifield constraint, */
      /* then no further modifications are needed to the    */
      /* min and max constraints for this constraint.       */
      /*====================================================*/

      if ((nextNode->type != MF_WILDCARD) && (nextNode->type != MF_VARIABLE))
        { continue; }

      /*==========================================================*/
      /* Create a separate constraint record to keep track of the */
      /* cardinality information for this multifield constraint.  */
      /*==========================================================*/

      tempConstraints = GetConstraintRecord();
      SetConstraintType(MULTIFIELD,tempConstraints);
      tempConstraints->singlefieldsAllowed = FALSE;
      tempConstraints->multifield = nextNode->constraints;
      nextNode->constraints = tempConstraints;

      /*=====================================================*/
      /* Adjust the min and max field values for this single */
      /* multifield constraint based on the min and max      */
      /* fields for the entire slot and the number of single */
      /* field values contained in the slot.                 */
      /*=====================================================*/

      if (theConstraints->maxFields->value != PositiveInfinity)
        {
         ReturnExpression(tempConstraints->maxFields);
         tempConstraints->maxFields = GenConstant(INTEGER,AddLong(ValueToLong(theConstraints->maxFields->value) - numberOfSingleFields));
        }

      if ((numberOfMultifields == 1) && (theConstraints->minFields->value != NegativeInfinity))
        {
         ReturnExpression(tempConstraints->minFields);
         tempConstraints->minFields = GenConstant(INTEGER,AddLong(ValueToLong(theConstraints->minFields->value) - numberOfSingleFields));
        }
     }

   /*================================================*/
   /* If a multifield slot is being parsed, place a  */
   /* node on top of the list of constraints parsed. */
   /*================================================*/

   if (multifieldSlot)
     {
      nextNode = GetLHSParseNode();
      nextNode->type = MF_WILDCARD;
      nextNode->multifieldSlot = TRUE;
      nextNode->bottom = topNode;
      nextNode->slot = theSlot;
      nextNode->slotNumber = slotNumber;
      nextNode->index = startPosition;
      nextNode->constraints = theConstraints;
      topNode = nextNode;
      TallyFieldTypes(topNode->bottom);
     }

   /*=================================*/
   /* Return the list of constraints. */
   /*=================================*/

   return(topNode);
  }
Example #9
0
globle struct lhsParseNode *SequenceRestrictionParse(
  void *theEnv,
  char *readSource,
  struct token *theToken)
  {
   struct lhsParseNode *topNode;
   struct lhsParseNode *nextField;

   /*================================================*/
   /* Create the pattern node for the relation name. */
   /*================================================*/

   topNode = GetLHSParseNode(theEnv);
   topNode->type = SF_WILDCARD;
   topNode->negated = FALSE;
   topNode->exists = FALSE;
   topNode->index = -1;
   topNode->slotNumber = 1;
   topNode->bottom = GetLHSParseNode(theEnv);
   topNode->bottom->type = SYMBOL;
   topNode->bottom->negated = FALSE;
   topNode->bottom->exists = FALSE;
   topNode->bottom->value = (void *) theToken->value;

   /*======================================================*/
   /* Connective constraints cannot be used in conjunction */
   /* with the first field of a pattern.                   */
   /*======================================================*/

   SavePPBuffer(theEnv," ");
   GetToken(theEnv,readSource,theToken);
   if ((theToken->type == OR_CONSTRAINT) || (theToken->type == AND_CONSTRAINT))
     {
      ReturnLHSParseNodes(theEnv,topNode);
      SyntaxErrorMessage(theEnv,"the first field of a pattern");
      return(NULL);
     }

   /*============================================================*/
   /* Treat the remaining constraints of an ordered fact pattern */
   /* as if they were contained in a multifield slot.            */
   /*============================================================*/

   nextField = RestrictionParse(theEnv,readSource,theToken,TRUE,NULL,1,NULL,1);
   if (nextField == NULL)
     {
      ReturnLHSParseNodes(theEnv,topNode);
      return(NULL);
     }
   topNode->right = nextField;

   /*================================================*/
   /* The pattern must end with a right parenthesis. */
   /*================================================*/

   if (theToken->type != RPAREN)
     {
      PPBackup(theEnv);
      SavePPBuffer(theEnv," ");
      SavePPBuffer(theEnv,theToken->printForm);
      SyntaxErrorMessage(theEnv,"fact patterns");
      ReturnLHSParseNodes(theEnv,topNode);
      return(NULL);
     }

   /*====================================*/
   /* Fix the pretty print output if the */
   /* slot contained no restrictions.    */
   /*====================================*/

   if (nextField->bottom == NULL)
     {
      PPBackup(theEnv);
      PPBackup(theEnv);
      SavePPBuffer(theEnv,")");
     }

   /*===================================*/
   /* If no errors, return the pattern. */
   /*===================================*/

   return(topNode);
  }
Example #10
0
static struct lhsParseNode *ConnectedPatternParse(
  void *theEnv,
  char *readSource,
  struct token *theToken,
  int *error)
  {
   unsigned short connectorValue = 0;
   struct lhsParseNode *theNode, *tempNode, *theGroup;
   char *errorCE = NULL;
   int logical = FALSE;
   int tempValue;

   /*==========================================================*/
   /* Use appropriate spacing for pretty printing of the rule. */
   /*==========================================================*/

   IncrementIndentDepth(theEnv,5);
   if (strcmp(ValueToString(theToken->value),"or") == 0)
     {
      connectorValue = OR_CE;
      errorCE = "the or conditional element";
      SavePPBuffer(theEnv,"  ");
     }
   else if (strcmp(ValueToString(theToken->value),"and") == 0)
     {
      connectorValue = AND_CE;
      errorCE = "the and conditional element";
      SavePPBuffer(theEnv," ");
     }
   else if (strcmp(ValueToString(theToken->value),"not") == 0)
     {
      connectorValue = NOT_CE;
      errorCE = "the not conditional element";
      SavePPBuffer(theEnv," ");
     }
   else if (strcmp(ValueToString(theToken->value),"exists") == 0)
     {
      connectorValue = EXISTS_CE;
      errorCE = "the exists conditional element";
      PPCRAndIndent(theEnv);
     }
   else if (strcmp(ValueToString(theToken->value),"forall") == 0)
     {
      connectorValue = FORALL_CE;
      errorCE = "the forall conditional element";
      PPCRAndIndent(theEnv);
     }
   else if (strcmp(ValueToString(theToken->value),"logical") == 0)
     {
      connectorValue = AND_CE;
      errorCE = "the logical conditional element";
      logical = TRUE;
      PPCRAndIndent(theEnv);
     }

   /*=====================================================*/
   /* The logical CE cannot be contained within a not CE. */
   /*=====================================================*/

   if (PatternData(theEnv)->WithinNotCE && logical)
     {
      PrintErrorID(theEnv,"RULELHS",1,TRUE);
      EnvPrintRouter(theEnv,WERROR,"The logical CE cannot be used within a not/exists/forall CE.\n");
      *error = TRUE;
      return(NULL);
     }

   /*=====================================================*/
   /* Remember if we're currently within a *not* CE and   */
   /* then check to see if we're entering a new *not* CE. */
   /*=====================================================*/

      tempValue = PatternData(theEnv)->WithinNotCE;
   if ((connectorValue == NOT_CE) ||
       (connectorValue == EXISTS_CE) ||
       (connectorValue == FORALL_CE))
     { PatternData(theEnv)->WithinNotCE = TRUE; }

   /*===========================================*/
   /* Parse all of the CEs contained with the   */
   /* CE. A ) will terminate the end of the CE. */
   /*===========================================*/

   theGroup = GroupPatterns(theEnv,readSource,RPAREN,")",error);

   /*====================================*/
   /* Restore the "with a *not* CE" flag */
   /* and reset the indentation depth.   */
   /*====================================*/

   PatternData(theEnv)->WithinNotCE = tempValue;
   DecrementIndentDepth(theEnv,5);

   /*============================================*/
   /* If an error occured while parsing, return. */
   /*============================================*/

   if (*error == TRUE)
     {
      ReturnLHSParseNodes(theEnv,theGroup);
      return(NULL);
     }

   /*=========================================================*/
   /* If we parsed a *logical* CE, then mark the logical flag */
   /* for all of the CEs contained within the logical CE.     */
   /*=========================================================*/

   if (logical) TagLHSLogicalNodes(theGroup);

   /*=====================================================*/
   /* All the connected CEs must contain at least one CE. */
   /*=====================================================*/

   if (theGroup == NULL)
     {
      SyntaxErrorMessage(theEnv,errorCE);
      *error = TRUE;
      return(NULL);
     }

   /*============================================*/
   /* A not CE may not contain more than one CE. */
   /*============================================*/

   if ((connectorValue == NOT_CE) && (theGroup->bottom != NULL))
     {
      SyntaxErrorMessage(theEnv,errorCE);
      ReturnLHSParseNodes(theEnv,theGroup);
      *error = TRUE;
      return(NULL);
     }

   /*============================================*/
   /* A forall CE must contain at least two CEs. */
   /*============================================*/

   if ((connectorValue == FORALL_CE) && (theGroup->bottom == NULL))
     {
      SyntaxErrorMessage(theEnv,errorCE);
      ReturnLHSParseNodes(theEnv,theGroup);
      *error = TRUE;
      return(NULL);
     }

   /*========================================================*/
   /* Remove an "and" and "or" CE that only contains one CE. */
   /*========================================================*/

   if (((connectorValue == AND_CE) || (connectorValue == OR_CE)) &&
       (theGroup->bottom == NULL))
     {
      theGroup->logical = logical;
      return(theGroup);
     }

   /*===========================================================*/
   /* Create the top most node which connects the CEs together. */
   /*===========================================================*/

   theNode = GetLHSParseNode(theEnv);
   theNode->logical = logical;

   /*======================================================*/
   /* Attach and/or/not CEs directly to the top most node. */
   /*======================================================*/

   if ((connectorValue == AND_CE) ||
       (connectorValue == OR_CE) ||
       (connectorValue == NOT_CE))
     {
      theNode->type = connectorValue;
      theNode->right = theGroup;
     }

   /*=================================================================*/
   /* Wrap two not CEs around the patterns contained in an exists CE. */
   /*=================================================================*/

   else if (connectorValue == EXISTS_CE)
     {
      theNode->type = NOT_CE;

      theNode->right = GetLHSParseNode(theEnv);
      theNode->right->type = NOT_CE;
      theNode->right->logical = logical;

      if (theGroup->bottom != NULL)
        {
         theNode->right->right = GetLHSParseNode(theEnv);
         theNode->right->right->type = AND_CE;
         theNode->right->right->logical = logical;
         theNode->right->right->right = theGroup;
        }
      else
        { theNode->right->right = theGroup; }
     }

   /*==================================================*/
   /* For a forall CE, wrap a not CE around all of the */
   /* CEs and a not CE around the 2nd through nth CEs. */
   /*==================================================*/

   else if (connectorValue == FORALL_CE)
     {
      theNode->type = NOT_CE;

      tempNode = theGroup->bottom;
      theGroup->bottom = NULL;

      theNode->right = GetLHSParseNode(theEnv);
      theNode->right->type = AND_CE;
      theNode->right->logical = logical;
      theNode->right->right = theGroup;

      theGroup = tempNode;

      theNode->right->right->bottom = GetLHSParseNode(theEnv);
      theNode->right->right->bottom->type = NOT_CE;
      theNode->right->right->bottom->logical = logical;

      tempNode = theNode->right->right->bottom;

      if (theGroup->bottom == NULL)
        { tempNode->right = theGroup; }
      else
        {
         tempNode->right = GetLHSParseNode(theEnv);
         tempNode->right->type = AND_CE;
         tempNode->right->logical = logical;
         tempNode->right->right = theGroup;
        }
     }

   /*================*/
   /* Return the CE. */
   /*================*/

   return(theNode);
  }
Example #11
0
static struct lhsParseNode *SimplePatternParse(
  void *theEnv,
  char *readSource,
  struct token *theToken,
  int *error)
  {
   struct lhsParseNode *theNode;
   struct patternParser *tempParser;

   /*=================================================*/
   /* The first field of a pattern must be a symbol.  */
   /* In addition, the symbols ":" and "=" can not    */
   /* be used because they have special significance. */
   /*=================================================*/

   if (theToken->type != SYMBOL)
     {
      SyntaxErrorMessage(theEnv,"the first field of a pattern");
      *error = TRUE;
      return(NULL);
     }
   else if ((strcmp(ValueToString(theToken->value),"=") == 0) ||
            (strcmp(ValueToString(theToken->value),":") == 0))
     {
      SyntaxErrorMessage(theEnv,"the field field of a pattern");
      *error = TRUE;
      return(NULL);
     }

   /*===============================================*/
   /* Construct the topmost node of the pattern CE. */
   /*===============================================*/

   theNode = GetLHSParseNode(theEnv);
   theNode->type = PATTERN_CE;
   theNode->negated = FALSE;

   /*======================================================*/
   /* Search for a pattern parser that claims the pattern. */
   /*======================================================*/

   for (tempParser = PatternData(theEnv)->ListOfPatternParsers;
        tempParser != NULL;
        tempParser = tempParser->next)
     {
      if ((*tempParser->recognizeFunction)((SYMBOL_HN *) theToken->value))
        {
         theNode->patternType = tempParser;
         theNode->right = (*tempParser->parseFunction)(theEnv,readSource,theToken);
         if (theNode->right == NULL)
           {
            *error = TRUE;
            ReturnLHSParseNodes(theEnv,theNode);
            return(NULL);
           }

         PropagatePatternType(theNode,tempParser);
         return(theNode);
        }
     }

   /*=================================*/
   /* If a pattern parser couldn't be */
   /* found, then signal an error.    */
   /*=================================*/

   *error = TRUE;
   SyntaxErrorMessage(theEnv,"the field field of a pattern");
   ReturnLHSParseNodes(theEnv,theNode);
   return(NULL);
  }