globle BOOLEAN ProcessConnectedConstraints( struct lhsParseNode *theNode, struct lhsParseNode *multifieldHeader, struct lhsParseNode *patternHead) { struct constraintRecord *orConstraints = NULL, *andConstraints; struct constraintRecord *tmpConstraints, *rvConstraints; struct lhsParseNode *orNode, *andNode; struct expr *tmpExpr; /*============================================*/ /* Loop through all of the or (|) constraints */ /* found in the connected constraint. */ /*============================================*/ for (orNode = theNode->bottom; orNode != NULL; orNode = orNode->bottom) { /*=================================================*/ /* Intersect all of the &'ed constraints together. */ /*=================================================*/ andConstraints = NULL; for (andNode = orNode; andNode != NULL; andNode = andNode->right) { if (! andNode->negated) { if (andNode->type == RETURN_VALUE_CONSTRAINT) { if (andNode->expression->type == FCALL) { rvConstraints = FunctionCallToConstraintRecord(andNode->expression->value); tmpConstraints = andConstraints; andConstraints = IntersectConstraints(andConstraints,rvConstraints); RemoveConstraint(tmpConstraints); RemoveConstraint(rvConstraints); } } else if (ConstantType(andNode->type)) { tmpExpr = GenConstant(andNode->type,andNode->value); rvConstraints = ExpressionToConstraintRecord(tmpExpr); tmpConstraints = andConstraints; andConstraints = IntersectConstraints(andConstraints,rvConstraints); RemoveConstraint(tmpConstraints); RemoveConstraint(rvConstraints); ReturnExpression(tmpExpr); } else if (andNode->constraints != NULL) { tmpConstraints = andConstraints; andConstraints = IntersectConstraints(andConstraints,andNode->constraints); RemoveConstraint(tmpConstraints); } } } /*===========================================================*/ /* Intersect the &'ed constraints with the slot constraints. */ /*===========================================================*/ tmpConstraints = andConstraints; andConstraints = IntersectConstraints(andConstraints,theNode->constraints); RemoveConstraint(tmpConstraints); /*===============================================================*/ /* Remove any negated constants from the list of allowed values. */ /*===============================================================*/ for (andNode = orNode; andNode != NULL; andNode = andNode->right) { if ((andNode->negated) && ConstantType(andNode->type)) { RemoveConstantFromConstraint(andNode->type,andNode->value,andConstraints); } } /*=======================================================*/ /* Union the &'ed constraints with the |'ed constraints. */ /*=======================================================*/ tmpConstraints = orConstraints; orConstraints = UnionConstraints(orConstraints,andConstraints); RemoveConstraint(tmpConstraints); RemoveConstraint(andConstraints); } /*===============================================*/ /* Replace the constraints for the slot with the */ /* constraints derived from the connected */ /* constraints (which should be a subset. */ /*===============================================*/ if (orConstraints != NULL) { if (theNode->derivedConstraints) RemoveConstraint(theNode->constraints); theNode->constraints = orConstraints; theNode->derivedConstraints = TRUE; } /*==================================*/ /* Check for constraint violations. */ /*==================================*/ if (CheckForUnmatchableConstraints(theNode,(int) patternHead->whichCE)) { return(TRUE); } /*=========================================*/ /* If the constraints are for a multifield */ /* slot, check for cardinality violations. */ /*=========================================*/ if ((multifieldHeader != NULL) && (theNode->right == NULL)) { if (MultifieldCardinalityViolation(multifieldHeader)) { ConstraintViolationErrorMessage("The group of restrictions", NULL,FALSE, (int) patternHead->whichCE, multifieldHeader->slot, multifieldHeader->index, CARDINALITY_VIOLATION, multifieldHeader->constraints,TRUE); return(TRUE); } } /*=======================================*/ /* Return FALSE indicating no constraint */ /* violations were detected. */ /*=======================================*/ return(FALSE); }
static struct expr *BindParse( void *theEnv, struct expr *top, char *infile) { struct token theToken; SYMBOL_HN *variableName; struct expr *texp; CONSTRAINT_RECORD *theConstraint = NULL; #if DEFGLOBAL_CONSTRUCT struct defglobal *theGlobal; int count; #endif SavePPBuffer(theEnv," "); /*=============================================*/ /* Next token must be the name of the variable */ /* to be bound. */ /*=============================================*/ GetToken(theEnv,infile,&theToken); if ((theToken.type != SF_VARIABLE) && (theToken.type != GBL_VARIABLE)) { if ((theToken.type != MF_VARIABLE) || ExpressionData(theEnv)->SequenceOpMode) { SyntaxErrorMessage(theEnv,"bind function"); ReturnExpression(theEnv,top); return(NULL); } } /*==============================*/ /* Process the bind expression. */ /*==============================*/ top->argList = GenConstant(theEnv,SYMBOL,theToken.value); variableName = (SYMBOL_HN *) theToken.value; #if DEFGLOBAL_CONSTRUCT if ((theToken.type == GBL_VARIABLE) ? ((theGlobal = (struct defglobal *) FindImportedConstruct(theEnv,"defglobal",NULL,ValueToString(variableName), &count,TRUE,FALSE)) != NULL) : FALSE) { top->argList->type = DEFGLOBAL_PTR; top->argList->value = (void *) theGlobal; } else if (theToken.type == GBL_VARIABLE) { GlobalReferenceErrorMessage(theEnv,ValueToString(variableName)); ReturnExpression(theEnv,top); return(NULL); } #endif texp = get_struct(theEnv,expr); texp->argList = texp->nextArg = NULL; if (CollectArguments(theEnv,texp,infile) == NULL) { ReturnExpression(theEnv,top); return(NULL); } top->argList->nextArg = texp->argList; rtn_struct(theEnv,expr,texp); #if DEFGLOBAL_CONSTRUCT if (top->argList->type == DEFGLOBAL_PTR) return(top); #endif if (top->argList->nextArg != NULL) { theConstraint = ExpressionToConstraintRecord(theEnv,top->argList->nextArg); } AddBindName(theEnv,variableName,theConstraint); return(top); }
globle struct expr *ParseDefault( void *theEnv, char *readSource, int multifield, int dynamic, int evalStatic, int *noneSpecified, int *deriveSpecified, int *error) { struct expr *defaultList = NULL, *lastDefault = NULL; struct expr *newItem, *tmpItem; struct token theToken; DATA_OBJECT theValue; CONSTRAINT_RECORD *rv; int specialVarCode; *noneSpecified = FALSE; *deriveSpecified = FALSE; SavePPBuffer(theEnv,(char*)" "); GetToken(theEnv,readSource,&theToken); /*===================================================*/ /* Read the items contained in the default attribute */ /* until a closing right parenthesis is encountered. */ /*===================================================*/ while (theToken.type != RPAREN) { /*========================================*/ /* Get the next item in the default list. */ /*========================================*/ newItem = ParseAtomOrExpression(theEnv,readSource,&theToken); if (newItem == NULL) { ReturnExpression(theEnv,defaultList); *error = TRUE; return(NULL); } /*===========================================================*/ /* Check for invalid variable usage. With the expection of */ /* ?NONE for the default attribute, local variables may not */ /* be used within the default or default-dynamic attributes. */ /*===========================================================*/ if ((newItem->type == SF_VARIABLE) || (newItem->type == MF_VARIABLE)) { if (strcmp(ValueToString(newItem->value),"NONE") == 0) { specialVarCode = 0; } else if (strcmp(ValueToString(newItem->value),"DERIVE") == 0) { specialVarCode = 1; } else { specialVarCode = -1; } if ((dynamic) || (newItem->type == MF_VARIABLE) || (specialVarCode == -1) || ((specialVarCode != -1) && (defaultList != NULL))) { if (dynamic) SyntaxErrorMessage(theEnv,(char*)"default-dynamic attribute"); else SyntaxErrorMessage(theEnv,(char*)"default attribute"); ReturnExpression(theEnv,newItem); ReturnExpression(theEnv,defaultList); *error = TRUE; return(NULL); } ReturnExpression(theEnv,newItem); /*============================================*/ /* Check for the closing right parenthesis of */ /* the default or default dynamic attribute. */ /*============================================*/ GetToken(theEnv,readSource,&theToken); if (theToken.type != RPAREN) { if (dynamic) SyntaxErrorMessage(theEnv,(char*)"default-dynamic attribute"); else SyntaxErrorMessage(theEnv,(char*)"default attribute"); PPBackup(theEnv); SavePPBuffer(theEnv,(char*)" "); SavePPBuffer(theEnv,theToken.printForm); *error = TRUE; } if (specialVarCode == 0) *noneSpecified = TRUE; else *deriveSpecified = TRUE; return(NULL); } /*====================================================*/ /* Look to see if any variables have been used within */ /* expressions contained within the default list. */ /*====================================================*/ if (ExpressionContainsVariables(newItem,FALSE) == TRUE) { ReturnExpression(theEnv,defaultList); ReturnExpression(theEnv,newItem); *error = TRUE; if (dynamic) SyntaxErrorMessage(theEnv,(char*)"default-dynamic attribute"); else SyntaxErrorMessage(theEnv,(char*)"default attribute"); return(NULL); } /*============================================*/ /* Add the default value to the default list. */ /*============================================*/ if (lastDefault == NULL) { defaultList = newItem; } else { lastDefault->nextArg = newItem; } lastDefault = newItem; /*=======================================*/ /* Begin parsing the next default value. */ /*=======================================*/ SavePPBuffer(theEnv,(char*)" "); GetToken(theEnv,readSource,&theToken); } /*=====================================*/ /* Fix up pretty print representation. */ /*=====================================*/ PPBackup(theEnv); PPBackup(theEnv); SavePPBuffer(theEnv,(char*)")"); /*=========================================*/ /* A single field slot's default attribute */ /* must contain a single value. */ /*=========================================*/ if (multifield == FALSE) { if (defaultList == NULL) { *error = TRUE; } else if (defaultList->nextArg != NULL) { *error = TRUE; } else { rv = ExpressionToConstraintRecord(theEnv,defaultList); rv->multifieldsAllowed = FALSE; if (UnmatchableConstraint(rv)) *error = TRUE; RemoveConstraint(theEnv,rv); } if (*error) { PrintErrorID(theEnv,(char*)"DEFAULT",1,TRUE); EnvPrintRouter(theEnv,WERROR,(char*)"The default value for a single field slot must be a single field value\n"); ReturnExpression(theEnv,defaultList); return(NULL); } } /*=======================================================*/ /* If the dynamic-default attribute is not being parsed, */ /* evaluate the expressions to make the default value. */ /*=======================================================*/ if (dynamic || (! evalStatic) || (defaultList == NULL)) return(defaultList); tmpItem = defaultList; newItem = defaultList; defaultList = NULL; while (newItem != NULL) { SetEvaluationError(theEnv,FALSE); if (EvaluateExpression(theEnv,newItem,&theValue)) *error = TRUE; if ((theValue.type == MULTIFIELD) && (multifield == FALSE) && (*error == FALSE)) { PrintErrorID(theEnv,(char*)"DEFAULT",1,TRUE); EnvPrintRouter(theEnv,WERROR,(char*)"The default value for a single field slot must be a single field value\n"); *error = TRUE; } if (*error) { ReturnExpression(theEnv,tmpItem); ReturnExpression(theEnv,defaultList); *error = TRUE; return(NULL); } lastDefault = ConvertValueToExpression(theEnv,&theValue); defaultList = AppendExpressions(defaultList,lastDefault); newItem = newItem->nextArg; } ReturnExpression(theEnv,tmpItem); /*==========================*/ /* Return the default list. */ /*==========================*/ return(defaultList); }