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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }