00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #define _PATTERN_SOURCE_
00030
00031 #include "setup.h"
00032
00033 #include <stdio.h>
00034 #define _STDIO_INCLUDED_
00035 #include <stdlib.h>
00036
00037 #if DEFRULE_CONSTRUCT
00038
00039 #include "constant.h"
00040 #include "constrnt.h"
00041 #include "cstrnchk.h"
00042 #include "cstrnutl.h"
00043 #include "envrnmnt.h"
00044 #include "exprnpsr.h"
00045 #include "match.h"
00046 #include "memalloc.h"
00047 #include "reteutil.h"
00048 #include "router.h"
00049 #include "rulecmp.h"
00050
00051 #include "pattern.h"
00052
00053
00054
00055
00056
00057 #if (! RUN_TIME) && (! BLOAD_ONLY)
00058 static struct lhsParseNode *ConjuctiveRestrictionParse(void *,char *,struct token *,int *);
00059 static struct lhsParseNode *LiteralRestrictionParse(void *,char *,struct token *,int *);
00060 static int CheckForVariableMixing(void *,struct lhsParseNode *);
00061 static void TallyFieldTypes(struct lhsParseNode *);
00062 #endif
00063 static void DeallocatePatternData(void *);
00064 static struct patternNodeHashEntry **CreatePatternHashTable(void *,unsigned long);
00065
00066
00067
00068
00069 globle void InitializePatterns(
00070 void *theEnv)
00071 {
00072 AllocateEnvironmentData(theEnv,PATTERN_DATA,sizeof(struct patternData),DeallocatePatternData);
00073 PatternData(theEnv)->NextPosition = 1;
00074 PatternData(theEnv)->PatternHashTable = CreatePatternHashTable(theEnv,SIZE_PATTERN_HASH);
00075 PatternData(theEnv)->PatternHashTableSize = SIZE_PATTERN_HASH;
00076 }
00077
00078
00079
00080
00081 static struct patternNodeHashEntry **CreatePatternHashTable(
00082 void *theEnv,
00083 unsigned long tableSize)
00084 {
00085 unsigned long i;
00086 struct patternNodeHashEntry **theTable;
00087
00088 theTable = (struct patternNodeHashEntry **)
00089 gm3(theEnv,sizeof (struct patternNodeHashEntry *) * tableSize);
00090
00091 if (theTable == NULL) EnvExitRouter(theEnv,EXIT_FAILURE);
00092
00093 for (i = 0; i < tableSize; i++) theTable[i] = NULL;
00094
00095 return(theTable);
00096 }
00097
00098
00099
00100
00101
00102 static void DeallocatePatternData(
00103 void *theEnv)
00104 {
00105 struct reservedSymbol *tmpRSPtr, *nextRSPtr;
00106 struct patternParser *tmpPPPtr, *nextPPPtr;
00107 struct patternNodeHashEntry *tmpPNEPtr, *nextPNEPtr;
00108 unsigned long i;
00109
00110 tmpRSPtr = PatternData(theEnv)->ListOfReservedPatternSymbols;
00111 while (tmpRSPtr != NULL)
00112 {
00113 nextRSPtr = tmpRSPtr->next;
00114 rtn_struct(theEnv,reservedSymbol,tmpRSPtr);
00115 tmpRSPtr = nextRSPtr;
00116 }
00117
00118 tmpPPPtr = PatternData(theEnv)->ListOfPatternParsers;
00119 while (tmpPPPtr != NULL)
00120 {
00121 nextPPPtr = tmpPPPtr->next;
00122 rtn_struct(theEnv,patternParser,tmpPPPtr);
00123 tmpPPPtr = nextPPPtr;
00124 }
00125
00126 for (i = 0; i < PatternData(theEnv)->PatternHashTableSize; i++)
00127 {
00128 tmpPNEPtr = PatternData(theEnv)->PatternHashTable[i];
00129
00130 while (tmpPNEPtr != NULL)
00131 {
00132 nextPNEPtr = tmpPNEPtr->next;
00133 rtn_struct(theEnv,patternNodeHashEntry,tmpPNEPtr);
00134 tmpPNEPtr = nextPNEPtr;
00135 }
00136 }
00137
00138 rm3(theEnv,PatternData(theEnv)->PatternHashTable,
00139 sizeof(struct patternNodeHashEntry *) * PatternData(theEnv)->PatternHashTableSize);
00140 }
00141
00142
00143
00144
00145 globle void AddHashedPatternNode(
00146 void *theEnv,
00147 void *parent,
00148 void *child,
00149 unsigned short keyType,
00150 void *keyValue)
00151 {
00152 unsigned long hashValue;
00153 struct patternNodeHashEntry *newhash, *temp;
00154
00155 hashValue = GetAtomicHashValue(keyType,keyValue,1) + HashExternalAddress(parent,0);
00156
00157 newhash = get_struct(theEnv,patternNodeHashEntry);
00158 newhash->parent = parent;
00159 newhash->child = child;
00160 newhash->type = keyType;
00161 newhash->value = keyValue;
00162
00163 hashValue = (hashValue % PatternData(theEnv)->PatternHashTableSize);
00164
00165 temp = PatternData(theEnv)->PatternHashTable[hashValue];
00166 PatternData(theEnv)->PatternHashTable[hashValue] = newhash;
00167 newhash->next = temp;
00168 }
00169
00170
00171
00172
00173
00174 globle intBool RemoveHashedPatternNode(
00175 void *theEnv,
00176 void *parent,
00177 void *child,
00178 unsigned short keyType,
00179 void *keyValue)
00180 {
00181 unsigned long hashValue;
00182 struct patternNodeHashEntry *hptr, *prev;
00183
00184 hashValue = GetAtomicHashValue(keyType,keyValue,1) + HashExternalAddress(parent,0);
00185 hashValue = (hashValue % PatternData(theEnv)->PatternHashTableSize);
00186
00187 for (hptr = PatternData(theEnv)->PatternHashTable[hashValue], prev = NULL;
00188 hptr != NULL;
00189 hptr = hptr->next)
00190 {
00191 if (hptr->child == child)
00192 {
00193 if (prev == NULL)
00194 {
00195 PatternData(theEnv)->PatternHashTable[hashValue] = hptr->next;
00196 rtn_struct(theEnv,patternNodeHashEntry,hptr);
00197 return(1);
00198 }
00199 else
00200 {
00201 prev->next = hptr->next;
00202 rtn_struct(theEnv,patternNodeHashEntry,hptr);
00203 return(1);
00204 }
00205 }
00206 prev = hptr;
00207 }
00208
00209 return(0);
00210 }
00211
00212
00213
00214
00215
00216 globle void *FindHashedPatternNode(
00217 void *theEnv,
00218 void *parent,
00219 unsigned short keyType,
00220 void *keyValue)
00221 {
00222 unsigned long hashValue;
00223 struct patternNodeHashEntry *hptr;
00224
00225 hashValue = GetAtomicHashValue(keyType,keyValue,1) + HashExternalAddress(parent,0);
00226 hashValue = (hashValue % PatternData(theEnv)->PatternHashTableSize);
00227
00228 for (hptr = PatternData(theEnv)->PatternHashTable[hashValue];
00229 hptr != NULL;
00230 hptr = hptr->next)
00231 {
00232 if ((hptr->parent == parent) &&
00233 (keyType == hptr->type) &&
00234 (keyValue == hptr->value))
00235 { return(hptr->child); }
00236 }
00237
00238 return(NULL);
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 void AddReservedPatternSymbol(
00250 void *theEnv,
00251 char *theSymbol,
00252 char *reservedBy)
00253 {
00254 struct reservedSymbol *newSymbol;
00255
00256 newSymbol = get_struct(theEnv,reservedSymbol);
00257 newSymbol->theSymbol = theSymbol;
00258 newSymbol->reservedBy = reservedBy;
00259 newSymbol->next = PatternData(theEnv)->ListOfReservedPatternSymbols;
00260 PatternData(theEnv)->ListOfReservedPatternSymbols = newSymbol;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269 intBool ReservedPatternSymbol(
00270 void *theEnv,
00271 char *theSymbol,
00272 char *checkedBy)
00273 {
00274 struct reservedSymbol *currentSymbol;
00275
00276 for (currentSymbol = PatternData(theEnv)->ListOfReservedPatternSymbols;
00277 currentSymbol != NULL;
00278 currentSymbol = currentSymbol->next)
00279 {
00280 if (strcmp(theSymbol,currentSymbol->theSymbol) == 0)
00281 {
00282 if ((currentSymbol->reservedBy == NULL) || (checkedBy == NULL))
00283 { return(TRUE); }
00284
00285 if (strcmp(checkedBy,currentSymbol->reservedBy) == 0) return(FALSE);
00286
00287 return(TRUE);
00288 }
00289 }
00290
00291 return(FALSE);
00292 }
00293
00294
00295
00296
00297
00298 void ReservedPatternSymbolErrorMsg(
00299 void *theEnv,
00300 char *theSymbol,
00301 char *usedFor)
00302 {
00303 PrintErrorID(theEnv,"PATTERN",1,TRUE);
00304 EnvPrintRouter(theEnv,WERROR,"The symbol ");
00305 EnvPrintRouter(theEnv,WERROR,theSymbol);
00306 EnvPrintRouter(theEnv,WERROR," has special meaning\n");
00307 EnvPrintRouter(theEnv,WERROR,"and may not be used as ");
00308 EnvPrintRouter(theEnv,WERROR,usedFor);
00309 EnvPrintRouter(theEnv,WERROR,".\n");
00310 }
00311
00312
00313
00314
00315
00316
00317 globle void GetNextPatternEntity(
00318 void *theEnv,
00319 struct patternParser **theParser,
00320 struct patternEntity **theEntity)
00321 {
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 if (*theParser == NULL)
00333 {
00334 *theParser = PatternData(theEnv)->ListOfPatternParsers;
00335 *theEntity = NULL;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345 else if (theEntity != NULL)
00346 {
00347 *theEntity = (struct patternEntity *)
00348 (*(*theParser)->entityType->base.getNextFunction)(theEnv,*theEntity);
00349
00350 if ((*theEntity) != NULL) return;
00351
00352 *theParser = (*theParser)->next;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361 else
00362 {
00363 SystemError(theEnv,"PATTERN",1);
00364 EnvExitRouter(theEnv,EXIT_FAILURE);
00365 }
00366
00367
00368
00369
00370
00371
00372 while ((*theEntity == NULL) && (*theParser != NULL))
00373 {
00374 *theEntity = (struct patternEntity *)
00375 (*(*theParser)->entityType->base.getNextFunction)(theEnv,*theEntity);
00376
00377 if (*theEntity != NULL) return;
00378
00379 *theParser = (*theParser)->next;
00380 }
00381
00382 return;
00383 }
00384
00385
00386
00387
00388
00389
00390 void DetachPattern(
00391 void *theEnv,
00392 int rhsType,
00393 struct patternNodeHeader *theHeader)
00394 {
00395 if (rhsType == 0) return;
00396
00397 if (PatternData(theEnv)->PatternParserArray[rhsType-1] != NULL)
00398 {
00399 FlushAlphaMemory(theEnv,theHeader);
00400 (*PatternData(theEnv)->PatternParserArray[rhsType-1]->removePatternFunction)(theEnv,theHeader);
00401 }
00402 }
00403
00404
00405
00406
00407
00408
00409 globle intBool AddPatternParser(
00410 void *theEnv,
00411 struct patternParser *newPtr)
00412 {
00413 struct patternParser *currentPtr, *lastPtr = NULL;
00414
00415
00416
00417
00418
00419
00420 if (PatternData(theEnv)->NextPosition >= MAX_POSITIONS) return(FALSE);
00421
00422
00423
00424
00425
00426 newPtr->positionInArray = PatternData(theEnv)->NextPosition;
00427 PatternData(theEnv)->PatternParserArray[PatternData(theEnv)->NextPosition-1] = newPtr;
00428 PatternData(theEnv)->NextPosition++;
00429
00430
00431
00432
00433
00434
00435 if (PatternData(theEnv)->ListOfPatternParsers == NULL)
00436 {
00437 newPtr->next = NULL;
00438 PatternData(theEnv)->ListOfPatternParsers = newPtr;
00439 return(TRUE);
00440 }
00441
00442 currentPtr = PatternData(theEnv)->ListOfPatternParsers;
00443 while ((currentPtr != NULL) ? (newPtr->priority < currentPtr->priority) : FALSE)
00444 {
00445 lastPtr = currentPtr;
00446 currentPtr = currentPtr->next;
00447 }
00448
00449 if (lastPtr == NULL)
00450 {
00451 newPtr->next = PatternData(theEnv)->ListOfPatternParsers;
00452 PatternData(theEnv)->ListOfPatternParsers = newPtr;
00453 }
00454 else
00455 {
00456 newPtr->next = currentPtr;
00457 lastPtr->next = newPtr;
00458 }
00459
00460 return(TRUE);
00461 }
00462
00463
00464
00465
00466
00467
00468 globle struct patternParser *FindPatternParser(
00469 void *theEnv,
00470 char *name)
00471 {
00472 struct patternParser *tempParser;
00473
00474 for (tempParser = PatternData(theEnv)->ListOfPatternParsers;
00475 tempParser != NULL;
00476 tempParser = tempParser->next)
00477 { if (strcmp(tempParser->name,name) == 0) return(tempParser); }
00478
00479 return(NULL);
00480 }
00481
00482
00483
00484
00485
00486 struct patternParser *GetPatternParser(
00487 void *theEnv,
00488 int rhsType)
00489 {
00490 if (rhsType == 0) return(NULL);
00491
00492 return(PatternData(theEnv)->PatternParserArray[rhsType-1]);
00493 }
00494
00495 #if CONSTRUCT_COMPILER && (! RUN_TIME)
00496
00497
00498
00499
00500
00501 globle void PatternNodeHeaderToCode(
00502 void *theEnv,
00503 FILE *fp,
00504 struct patternNodeHeader *theHeader,
00505 int imageID,
00506 int maxIndices)
00507 {
00508 fprintf(fp,"{NULL,NULL,");
00509
00510 if (theHeader->entryJoin == NULL)
00511 { fprintf(fp,"NULL,"); }
00512 else
00513 {
00514 fprintf(fp,"&%s%d_%d[%d],",
00515 JoinPrefix(),imageID,
00516 (((int) theHeader->entryJoin->bsaveID) / maxIndices) + 1,
00517 ((int) theHeader->entryJoin->bsaveID) % maxIndices);
00518 }
00519
00520 PrintHashedExpressionReference(theEnv,fp,theHeader->rightHash,imageID,maxIndices);
00521
00522 fprintf(fp,",%d,%d,%d,0,0,%d,%d,%d}",theHeader->singlefieldNode,
00523 theHeader->multifieldNode,
00524 theHeader->stopNode,
00525 theHeader->beginSlot,
00526 theHeader->endSlot,
00527 theHeader->selector);
00528 }
00529
00530 #endif
00531
00532 #if (! RUN_TIME) && (! BLOAD_ONLY)
00533
00534
00535
00536
00537
00538
00539
00540 globle intBool PostPatternAnalysis(
00541 void *theEnv,
00542 struct lhsParseNode *theLHS)
00543 {
00544 struct lhsParseNode *patternPtr;
00545 struct patternParser *tempParser;
00546
00547 for (patternPtr = theLHS; patternPtr != NULL; patternPtr = patternPtr->bottom)
00548 {
00549 if ((patternPtr->type == PATTERN_CE) && (patternPtr->patternType != NULL))
00550 {
00551 tempParser = patternPtr->patternType;
00552 if (tempParser->postAnalysisFunction != NULL)
00553 { if ((*tempParser->postAnalysisFunction)(theEnv,patternPtr)) return(TRUE); }
00554 }
00555 }
00556
00557 return(FALSE);
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 struct lhsParseNode *RestrictionParse(
00571 void *theEnv,
00572 char *readSource,
00573 struct token *theToken,
00574 int multifieldSlot,
00575 struct symbolHashNode *theSlot,
00576 short slotNumber,
00577 CONSTRAINT_RECORD *theConstraints,
00578 short position)
00579 {
00580 struct lhsParseNode *topNode = NULL, *lastNode = NULL, *nextNode;
00581 int numberOfSingleFields = 0;
00582 int numberOfMultifields = 0;
00583 short startPosition = position;
00584 int error = FALSE;
00585 CONSTRAINT_RECORD *tempConstraints;
00586
00587
00588
00589
00590
00591
00592
00593
00594 while (theToken->type != RPAREN)
00595 {
00596
00597
00598
00599
00600
00601 if ((theToken->type == SF_WILDCARD) ||
00602 (theToken->type == MF_WILDCARD))
00603 {
00604 nextNode = GetLHSParseNode(theEnv);
00605 nextNode->type = theToken->type;
00606 nextNode->negated = FALSE;
00607 nextNode->exists = FALSE;
00608 GetToken(theEnv,readSource,theToken);
00609 }
00610 else
00611 {
00612 nextNode = ConjuctiveRestrictionParse(theEnv,readSource,theToken,&error);
00613 if (nextNode == NULL)
00614 {
00615 ReturnLHSParseNodes(theEnv,topNode);
00616 return(NULL);
00617 }
00618 }
00619
00620
00621
00622
00623
00624
00625 if ((theToken->type != RPAREN) && (multifieldSlot == TRUE))
00626 {
00627 PPBackup(theEnv);
00628 SavePPBuffer(theEnv," ");
00629 SavePPBuffer(theEnv,theToken->printForm);
00630 }
00631
00632
00633
00634
00635
00636
00637 if ((nextNode->type == SF_WILDCARD) || (nextNode->type == SF_VARIABLE))
00638 { numberOfSingleFields++; }
00639 else
00640 { numberOfMultifields++; }
00641
00642
00643
00644
00645
00646 nextNode->slot = theSlot;
00647 nextNode->slotNumber = slotNumber;
00648 nextNode->index = position++;
00649
00650
00651
00652
00653
00654
00655
00656 if (! multifieldSlot)
00657 {
00658 if (theConstraints == NULL)
00659 {
00660 if (nextNode->type == SF_VARIABLE)
00661 { nextNode->constraints = GetConstraintRecord(theEnv); }
00662 else nextNode->constraints = NULL;
00663 }
00664 else nextNode->constraints = theConstraints;
00665 return(nextNode);
00666 }
00667
00668
00669
00670
00671
00672
00673 if (lastNode == NULL) topNode = nextNode;
00674 else lastNode->right = nextNode;
00675
00676 lastNode = nextNode;
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686 if ((topNode == NULL) && (! multifieldSlot))
00687 {
00688 SyntaxErrorMessage(theEnv,"defrule");
00689 return(NULL);
00690 }
00691
00692
00693
00694
00695
00696
00697 for (nextNode = topNode; nextNode != NULL; nextNode = nextNode->right)
00698 {
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 if (theConstraints == NULL)
00709 {
00710 if (nextNode->type == SF_VARIABLE)
00711 { nextNode->constraints = GetConstraintRecord(theEnv); }
00712 else
00713 { continue; }
00714 }
00715 else
00716 { nextNode->constraints = CopyConstraintRecord(theEnv,theConstraints); }
00717
00718
00719
00720
00721
00722
00723
00724 ReturnExpression(theEnv,nextNode->constraints->minFields);
00725 ReturnExpression(theEnv,nextNode->constraints->maxFields);
00726 nextNode->constraints->minFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->NegativeInfinity);
00727 nextNode->constraints->maxFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->PositiveInfinity);
00728 nextNode->derivedConstraints = TRUE;
00729
00730
00731
00732
00733
00734
00735
00736 if ((nextNode->type != MF_WILDCARD) && (nextNode->type != MF_VARIABLE))
00737 { continue; }
00738
00739
00740
00741
00742
00743
00744 tempConstraints = GetConstraintRecord(theEnv);
00745 SetConstraintType(MULTIFIELD,tempConstraints);
00746 tempConstraints->singlefieldsAllowed = FALSE;
00747 tempConstraints->multifield = nextNode->constraints;
00748 nextNode->constraints = tempConstraints;
00749
00750
00751
00752
00753
00754
00755
00756
00757 if (theConstraints->maxFields->value != SymbolData(theEnv)->PositiveInfinity)
00758 {
00759 ReturnExpression(theEnv,tempConstraints->maxFields);
00760 tempConstraints->maxFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,ValueToLong(theConstraints->maxFields->value) - numberOfSingleFields));
00761 }
00762
00763 if ((numberOfMultifields == 1) && (theConstraints->minFields->value != SymbolData(theEnv)->NegativeInfinity))
00764 {
00765 ReturnExpression(theEnv,tempConstraints->minFields);
00766 tempConstraints->minFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,ValueToLong(theConstraints->minFields->value) - numberOfSingleFields));
00767 }
00768 }
00769
00770
00771
00772
00773
00774
00775 if (multifieldSlot)
00776 {
00777 nextNode = GetLHSParseNode(theEnv);
00778 nextNode->type = MF_WILDCARD;
00779 nextNode->multifieldSlot = TRUE;
00780 nextNode->bottom = topNode;
00781 nextNode->slot = theSlot;
00782 nextNode->slotNumber = slotNumber;
00783 nextNode->index = startPosition;
00784 nextNode->constraints = theConstraints;
00785 topNode = nextNode;
00786 TallyFieldTypes(topNode->bottom);
00787 }
00788
00789
00790
00791
00792
00793 return(topNode);
00794 }
00795
00796
00797
00798
00799
00800
00801 static void TallyFieldTypes(
00802 struct lhsParseNode *theRestrictions)
00803 {
00804 struct lhsParseNode *tempNode1, *tempNode2, *tempNode3;
00805 unsigned short totalSingleFields = 0, totalMultiFields = 0;
00806 unsigned short runningSingleFields = 0, runningMultiFields = 0;
00807
00808
00809
00810
00811
00812
00813 for (tempNode1 = theRestrictions; tempNode1 != NULL; tempNode1 = tempNode1->right)
00814 {
00815 if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
00816 { totalSingleFields++; }
00817 else
00818 { totalMultiFields++; }
00819 }
00820
00821
00822
00823
00824
00825
00826 for (tempNode1 = theRestrictions; tempNode1 != NULL; tempNode1 = tempNode1->right)
00827 {
00828
00829
00830
00831
00832
00833 tempNode1->singleFieldsBefore = runningSingleFields;
00834 tempNode1->multiFieldsBefore = runningMultiFields;
00835 tempNode1->withinMultifieldSlot = TRUE;
00836
00837 if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
00838 {
00839 tempNode1->singleFieldsAfter = (unsigned short) (totalSingleFields - (runningSingleFields + 1));
00840 tempNode1->multiFieldsAfter = (unsigned short) (totalMultiFields - runningMultiFields);
00841 }
00842 else
00843 {
00844 tempNode1->singleFieldsAfter = (unsigned short) (totalSingleFields - runningSingleFields);
00845 tempNode1->multiFieldsAfter = (unsigned short) (totalMultiFields - (runningMultiFields + 1));
00846 }
00847
00848
00849
00850
00851
00852
00853 for (tempNode2 = tempNode1->bottom; tempNode2 != NULL; tempNode2 = tempNode2->bottom)
00854 {
00855 for (tempNode3 = tempNode2; tempNode3 != NULL; tempNode3 = tempNode3->right)
00856 {
00857 tempNode3->singleFieldsBefore = tempNode1->singleFieldsBefore;
00858 tempNode3->singleFieldsAfter = tempNode1->singleFieldsAfter;
00859 tempNode3->multiFieldsBefore = tempNode1->multiFieldsBefore;
00860 tempNode3->multiFieldsAfter = tempNode1->multiFieldsAfter;
00861 tempNode3->withinMultifieldSlot = TRUE;
00862 }
00863 }
00864
00865
00866
00867
00868
00869
00870 if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
00871 { runningSingleFields++; }
00872 else
00873 { runningMultiFields++; }
00874 }
00875 }
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 static struct lhsParseNode *ConjuctiveRestrictionParse(
00890 void *theEnv,
00891 char *readSource,
00892 struct token *theToken,
00893 int *error)
00894 {
00895 struct lhsParseNode *bindNode;
00896 struct lhsParseNode *theNode, *nextOr, *nextAnd;
00897 int connectorType;
00898
00899
00900
00901
00902
00903
00904 theNode = LiteralRestrictionParse(theEnv,readSource,theToken,error);
00905
00906 if (*error == TRUE)
00907 { return(NULL); }
00908
00909 GetToken(theEnv,readSource,theToken);
00910
00911 if (((theNode->type == SF_VARIABLE) || (theNode->type == MF_VARIABLE)) &&
00912 (theNode->negated == FALSE) &&
00913 (theToken->type != OR_CONSTRAINT))
00914 {
00915 theNode->bindingVariable = TRUE;
00916 bindNode = theNode;
00917 nextOr = NULL;
00918 nextAnd = NULL;
00919 }
00920 else
00921 {
00922 bindNode = GetLHSParseNode(theEnv);
00923 if (theNode->type == MF_VARIABLE) bindNode->type = MF_WILDCARD;
00924 else bindNode->type = SF_WILDCARD;
00925 bindNode->negated = FALSE;
00926 bindNode->bottom = theNode;
00927 nextOr = theNode;
00928 nextAnd = theNode;
00929 }
00930
00931
00932
00933
00934
00935
00936 while ((theToken->type == OR_CONSTRAINT) || (theToken->type == AND_CONSTRAINT))
00937 {
00938
00939
00940
00941
00942 connectorType = theToken->type;
00943
00944 GetToken(theEnv,readSource,theToken);
00945 theNode = LiteralRestrictionParse(theEnv,readSource,theToken,error);
00946
00947 if (*error == TRUE)
00948 {
00949 ReturnLHSParseNodes(theEnv,bindNode);
00950 return(NULL);
00951 }
00952
00953
00954
00955
00956
00957
00958 if (connectorType == OR_CONSTRAINT)
00959 {
00960 if (nextOr == NULL)
00961 { bindNode->bottom = theNode; }
00962 else
00963 { nextOr->bottom = theNode; }
00964 nextOr = theNode;
00965 nextAnd = theNode;
00966 }
00967 else if (connectorType == AND_CONSTRAINT)
00968 {
00969 if (nextAnd == NULL)
00970 {
00971 bindNode->bottom = theNode;
00972 nextOr = theNode;
00973 }
00974 else
00975 { nextAnd->right = theNode; }
00976 nextAnd = theNode;
00977 }
00978 else
00979 {
00980 SystemError(theEnv,"RULEPSR",1);
00981 EnvExitRouter(theEnv,EXIT_FAILURE);
00982 }
00983
00984
00985
00986
00987
00988
00989 GetToken(theEnv,readSource,theToken);
00990 }
00991
00992
00993
00994
00995
00996
00997 if (CheckForVariableMixing(theEnv,bindNode))
00998 {
00999 *error = TRUE;
01000 ReturnLHSParseNodes(theEnv,bindNode);
01001 return(NULL);
01002 }
01003
01004
01005
01006
01007
01008 return(bindNode);
01009 }
01010
01011
01012
01013
01014
01015
01016 static int CheckForVariableMixing(
01017 void *theEnv,
01018 struct lhsParseNode *theRestriction)
01019 {
01020 struct lhsParseNode *tempRestriction;
01021 CONSTRAINT_RECORD *theConstraint;
01022 int multifield = FALSE;
01023 int singlefield = FALSE;
01024 int constant = FALSE;
01025 int singleReturnValue = FALSE;
01026 int multiReturnValue = FALSE;
01027
01028
01029
01030
01031
01032
01033
01034 if (theRestriction->type == SF_VARIABLE) singlefield = TRUE;
01035 else if (theRestriction->type == MF_VARIABLE) multifield = TRUE;
01036
01037
01038
01039
01040
01041
01042 for (theRestriction = theRestriction->bottom;
01043 theRestriction != NULL;
01044 theRestriction = theRestriction->bottom)
01045 {
01046
01047
01048
01049
01050
01051 for (tempRestriction = theRestriction;
01052 tempRestriction != NULL;
01053 tempRestriction = tempRestriction->right)
01054 {
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 if (tempRestriction->type == SF_VARIABLE) singlefield = TRUE;
01065 else if (tempRestriction->type == MF_VARIABLE) multifield = TRUE;
01066 else if (ConstantType(tempRestriction->type)) constant = TRUE;
01067 else if (tempRestriction->type == RETURN_VALUE_CONSTRAINT)
01068 {
01069 theConstraint = FunctionCallToConstraintRecord(theEnv,tempRestriction->expression->value);
01070 if (theConstraint->anyAllowed) { }
01071 else if (theConstraint->multifieldsAllowed) multiReturnValue = TRUE;
01072 else singleReturnValue = TRUE;
01073 RemoveConstraint(theEnv,theConstraint);
01074 }
01075 }
01076 }
01077
01078
01079
01080
01081
01082
01083
01084
01085 if ((singlefield || constant || singleReturnValue) &&
01086 (multifield || multiReturnValue))
01087
01088 {
01089 PrintErrorID(theEnv,"PATTERN",2,TRUE);
01090 EnvPrintRouter(theEnv,WERROR,"Single and multifield constraints cannot be mixed in a field constraint\n");
01091 return(TRUE);
01092 }
01093
01094
01095
01096
01097
01098
01099 return(FALSE);
01100 }
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 static struct lhsParseNode *LiteralRestrictionParse(
01118 void *theEnv,
01119 char *readSource,
01120 struct token *theToken,
01121 int *error)
01122 {
01123 struct lhsParseNode *topNode;
01124 struct expr *theExpression;
01125
01126
01127
01128
01129
01130 topNode = GetLHSParseNode(theEnv);
01131
01132
01133
01134
01135
01136
01137
01138 if (theToken->type == NOT_CONSTRAINT)
01139 {
01140 GetToken(theEnv,readSource,theToken);
01141 topNode->negated = TRUE;
01142 }
01143 else
01144 { topNode->negated = FALSE; }
01145
01146
01147
01148
01149
01150
01151
01152
01153 topNode->type = theToken->type;
01154
01155
01156
01157
01158
01159
01160
01161 if (theToken->type == SYMBOL)
01162 {
01163
01164
01165
01166
01167
01168 if (strcmp(ValueToString(theToken->value),"=") == 0)
01169 {
01170 theExpression = Function0Parse(theEnv,readSource);
01171 if (theExpression == NULL)
01172 {
01173 *error = TRUE;
01174 ReturnLHSParseNodes(theEnv,topNode);
01175 return(NULL);
01176 }
01177 topNode->type = RETURN_VALUE_CONSTRAINT;
01178 topNode->expression = ExpressionToLHSParseNodes(theEnv,theExpression);
01179 ReturnExpression(theEnv,theExpression);
01180 }
01181
01182
01183
01184
01185
01186
01187 else if (strcmp(ValueToString(theToken->value),":") == 0)
01188 {
01189 theExpression = Function0Parse(theEnv,readSource);
01190 if (theExpression == NULL)
01191 {
01192 *error = TRUE;
01193 ReturnLHSParseNodes(theEnv,topNode);
01194 return(NULL);
01195 }
01196 topNode->type = PREDICATE_CONSTRAINT;
01197 topNode->expression = ExpressionToLHSParseNodes(theEnv,theExpression);
01198 ReturnExpression(theEnv,theExpression);
01199 }
01200
01201
01202
01203
01204
01205 else
01206 { topNode->value = theToken->value; }
01207 }
01208
01209
01210
01211
01212
01213
01214 else if ((theToken->type == SF_VARIABLE) ||
01215 (theToken->type == MF_VARIABLE) ||
01216 (theToken->type == FLOAT) ||
01217 (theToken->type == INTEGER) ||
01218 (theToken->type == STRING) ||
01219 (theToken->type == INSTANCE_NAME))
01220 { topNode->value = theToken->value; }
01221
01222
01223
01224
01225
01226 else
01227 {
01228 SyntaxErrorMessage(theEnv,"defrule");
01229 *error = TRUE;
01230 ReturnLHSParseNodes(theEnv,topNode);
01231 return(NULL);
01232 }
01233
01234
01235
01236
01237
01238 return(topNode);
01239 }
01240
01241 #endif
01242
01243 #endif
01244
01245
01246
01247