+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
**********************************************************************
-* Copyright (c) 2002-2008, International Business Machines
+* Copyright (c) 2002-2016, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
fTree = fTree->flattenVariables();
#ifdef RBBI_DEBUG
if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "ftree")) {
- RBBIDebugPuts("Parse tree after flattening variable references.");
- fTree->printTree(TRUE);
+ RBBIDebugPuts("\nParse tree after flattening variable references.");
+ RBBINode::printTree(fTree, TRUE);
}
#endif
fTree->flattenSets();
#ifdef RBBI_DEBUG
if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "stree")) {
- RBBIDebugPuts("Parse tree after flattening Unicode Set references.");
- fTree->printTree(TRUE);
+ RBBIDebugPuts("\nParse tree after flattening Unicode Set references.");
+ RBBINode::printTree(fTree, TRUE);
}
#endif
}
+//-----------------------------------------------------------------------------
+//
+// addRuleRootNodes Recursively walk a parse tree, adding all nodes flagged
+// as roots of a rule to a destination vector.
+//
+//-----------------------------------------------------------------------------
+void RBBITableBuilder::addRuleRootNodes(UVector *dest, RBBINode *node) {
+ if (node == NULL || U_FAILURE(*fStatus)) {
+ return;
+ }
+ if (node->fRuleRoot) {
+ dest->addElement(node, *fStatus);
+ // Note: rules cannot nest. If we found a rule start node,
+ // no child node can also be a start node.
+ return;
+ }
+ addRuleRootNodes(dest, node->fLeftChild);
+ addRuleRootNodes(dest, node->fRightChild);
+}
//-----------------------------------------------------------------------------
//
return;
}
- // Get all nodes that can be the start a match, which is FirstPosition()
- // of the portion of the tree corresponding to user-written rules.
- // See the tree description in bofFixup().
- RBBINode *userRuleRoot = tree;
- if (fRB->fSetBuilder->sawBOF()) {
- userRuleRoot = tree->fLeftChild->fRightChild;
- }
- U_ASSERT(userRuleRoot != NULL);
- UVector *matchStartNodes = userRuleRoot->fFirstPosSet;
+ // Collect all leaf nodes that can start matches for rules
+ // with inbound chaining enabled, which is the union of the
+ // firstPosition sets from each of the rule root nodes.
+
+ UVector ruleRootNodes(*fStatus);
+ addRuleRootNodes(&ruleRootNodes, tree);
+ UVector matchStartNodes(*fStatus);
+ for (int i=0; i<ruleRootNodes.size(); ++i) {
+ RBBINode *node = static_cast<RBBINode *>(ruleRootNodes.elementAt(i));
+ if (node->fChainIn) {
+ setAdd(&matchStartNodes, node->fFirstPosSet);
+ }
+ }
+ if (U_FAILURE(*fStatus)) {
+ return;
+ }
- // Iteratate over all leaf nodes,
- //
int32_t endNodeIx;
int32_t startNodeIx;
// Now iterate over the nodes that can start a match, looking for ones
// with the same char class as our ending node.
RBBINode *startNode;
- for (startNodeIx = 0; startNodeIx<matchStartNodes->size(); startNodeIx++) {
- startNode = (RBBINode *)matchStartNodes->elementAt(startNodeIx);
+ for (startNodeIx = 0; startNodeIx<matchStartNodes.size(); startNodeIx++) {
+ startNode = (RBBINode *)matchStartNodes.elementAt(startNodeIx);
if (startNode->fType != RBBINode::leafChar) {
continue;
}
int32_t destOriginalSize = dest->size();
int32_t sourceSize = source->size();
int32_t di = 0;
- void *(destS[16]), *(sourceS[16]); // Handle small cases without malloc
- void **destH = 0, **sourceH = 0;
- void **destBuff, **sourceBuff;
+ MaybeStackArray<void *, 16> destArray, sourceArray; // Handle small cases without malloc
+ void **destPtr, **sourcePtr;
void **destLim, **sourceLim;
- if (destOriginalSize > (int32_t)(sizeof(destS)/sizeof(destS[0]))) {
- destH = (void **)uprv_malloc(sizeof(void *) * destOriginalSize);
- destBuff = destH;
- }
- else {
- destBuff = destS;
- }
- if (destBuff == 0) {
- return;
+ if (destOriginalSize > destArray.getCapacity()) {
+ if (destArray.resize(destOriginalSize) == NULL) {
+ return;
+ }
}
- destLim = destBuff + destOriginalSize;
+ destPtr = destArray.getAlias();
+ destLim = destPtr + destOriginalSize; // destArray.getArrayLimit()?
- if (sourceSize > (int32_t)(sizeof(sourceS)/sizeof(sourceS[0]))) {
- sourceH = (void **)uprv_malloc(sizeof(void *) * sourceSize);
- sourceBuff = sourceH;
- }
- else {
- sourceBuff = sourceS;
- }
- if (sourceBuff == 0) {
- if (destH) {
- uprv_free(destH);
+ if (sourceSize > sourceArray.getCapacity()) {
+ if (sourceArray.resize(sourceSize) == NULL) {
+ return;
}
- return;
}
- sourceLim = sourceBuff + sourceSize;
+ sourcePtr = sourceArray.getAlias();
+ sourceLim = sourcePtr + sourceSize; // sourceArray.getArrayLimit()?
// Avoid multiple "get element" calls by getting the contents into arrays
- (void) dest->toArray(destBuff);
- (void) source->toArray(sourceBuff);
+ (void) dest->toArray(destPtr);
+ (void) source->toArray(sourcePtr);
dest->setSize(sourceSize+destOriginalSize, *fStatus);
- while (sourceBuff < sourceLim && destBuff < destLim) {
- if (*destBuff == *sourceBuff) {
- dest->setElementAt(*sourceBuff++, di++);
- destBuff++;
+ while (sourcePtr < sourceLim && destPtr < destLim) {
+ if (*destPtr == *sourcePtr) {
+ dest->setElementAt(*sourcePtr++, di++);
+ destPtr++;
}
// This check is required for machines with segmented memory, like i5/OS.
// Direct pointer comparison is not recommended.
- else if (uprv_memcmp(destBuff, sourceBuff, sizeof(void *)) < 0) {
- dest->setElementAt(*destBuff++, di++);
+ else if (uprv_memcmp(destPtr, sourcePtr, sizeof(void *)) < 0) {
+ dest->setElementAt(*destPtr++, di++);
}
- else { /* *sourceBuff < *destBuff */
- dest->setElementAt(*sourceBuff++, di++);
+ else { /* *sourcePtr < *destPtr */
+ dest->setElementAt(*sourcePtr++, di++);
}
}
// At most one of these two cleanup loops will execute
- while (destBuff < destLim) {
- dest->setElementAt(*destBuff++, di++);
+ while (destPtr < destLim) {
+ dest->setElementAt(*destPtr++, di++);
}
- while (sourceBuff < sourceLim) {
- dest->setElementAt(*sourceBuff++, di++);
+ while (sourcePtr < sourceLim) {
+ dest->setElementAt(*sourcePtr++, di++);
}
dest->setSize(di, *fStatus);
- if (destH) {
- uprv_free(destH);
- }
- if (sourceH) {
- uprv_free(sourceH);
- }
}
if (n==NULL) {
return;
}
- n->printNode();
+ printf("\n");
+ RBBINode::printNodeHeader();
+ RBBINode::printNode(n);
RBBIDebugPrintf(" Nullable: %s\n", n->fNullable?"TRUE":"FALSE");
RBBIDebugPrintf(" firstpos: ");
void RBBITableBuilder::printSet(UVector *s) {
int32_t i;
for (i=0; i<s->size(); i++) {
- void *v = s->elementAt(i);
- RBBIDebugPrintf("%10p", v);
+ const RBBINode *v = static_cast<const RBBINode *>(s->elementAt(i));
+ RBBIDebugPrintf("%5d", v==NULL? -1 : v->fSerialNum);
}
RBBIDebugPrintf("\n");
}