// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /* *************************************************************************** * Copyright (C) 2002-2016 International Business Machines Corporation * * and others. All rights reserved. * *************************************************************************** */ // // File: rbbinode.cpp // // Implementation of class RBBINode, which represents a node in the // tree generated when parsing the Rules Based Break Iterator rules. // // This "Class" is actually closer to a struct. // Code using it is expected to directly access fields much of the time. // #include "unicode/utypes.h" #if !UCONFIG_NO_BREAK_ITERATION #include "unicode/unistr.h" #include "unicode/uniset.h" #include "unicode/uchar.h" #include "unicode/parsepos.h" #include "cstr.h" #include "uvector.h" #include "rbbirb.h" #include "rbbinode.h" #include "uassert.h" U_NAMESPACE_BEGIN #ifdef RBBI_DEBUG static int gLastSerial = 0; #endif //------------------------------------------------------------------------- // // Constructor. Just set the fields to reasonable default values. // //------------------------------------------------------------------------- RBBINode::RBBINode(NodeType t) : … { … } RBBINode::RBBINode(const RBBINode &other) : … { … } //------------------------------------------------------------------------- // // Destructor. Deletes both this node AND any child nodes, // except in the case of variable reference nodes. For // these, the l. child points back to the definition, which // is common for all references to the variable, meaning // it can't be deleted here. // //------------------------------------------------------------------------- RBBINode::~RBBINode() { … } /** * Non-recursive delete of a node + its children. Used from the node destructor * instead of the more obvious recursive implementation to avoid problems with * stack overflow with some perverse test rule data (from fuzzing). */ void RBBINode::NRDeleteNode(RBBINode *node) { … } //------------------------------------------------------------------------- // // cloneTree Make a copy of the subtree rooted at this node. // Discard any variable references encountered along the way, // and replace with copies of the variable's definitions. // Used to replicate the expression underneath variable // references in preparation for generating the DFA tables. // //------------------------------------------------------------------------- RBBINode *RBBINode::cloneTree() { … } //------------------------------------------------------------------------- // // flattenVariables Walk a parse tree, replacing any variable // references with a copy of the variable's definition. // Aside from variables, the tree is not changed. // // Return the root of the tree. If the root was not a variable // reference, it remains unchanged - the root we started with // is the root we return. If, however, the root was a variable // reference, the root of the newly cloned replacement tree will // be returned, and the original tree deleted. // // This function works by recursively walking the tree // without doing anything until a variable reference is // found, then calling cloneTree() at that point. Any // nested references are handled by cloneTree(), not here. // //------------------------------------------------------------------------- constexpr int kRecursiveDepthLimit = …; RBBINode *RBBINode::flattenVariables(UErrorCode& status, int depth) { … } //------------------------------------------------------------------------- // // flattenSets Walk the parse tree, replacing any nodes of type setRef // with a copy of the expression tree for the set. A set's // equivalent expression tree is precomputed and saved as // the left child of the uset node. // //------------------------------------------------------------------------- void RBBINode::flattenSets() { … } //------------------------------------------------------------------------- // // findNodes() Locate all the nodes of the specified type, starting // at the specified root. // //------------------------------------------------------------------------- void RBBINode::findNodes(UVector *dest, RBBINode::NodeType kind, UErrorCode &status) { … } //------------------------------------------------------------------------- // // print. Print out a single node, for debugging. // //------------------------------------------------------------------------- #ifdef RBBI_DEBUG static int32_t serial(const RBBINode *node) { return (node == nullptr? -1 : node->fSerialNum); } void RBBINode::printNode(const RBBINode *node) { static const char * const nodeTypeNames[] = { "setRef", "uset", "varRef", "leafChar", "lookAhead", "tag", "endMark", "opStart", "opCat", "opOr", "opStar", "opPlus", "opQuestion", "opBreak", "opReverse", "opLParen" }; if (node==nullptr) { RBBIDebugPrintf("%10p", (void *)node); } else { RBBIDebugPrintf("%10p %5d %12s %c%c %5d %5d %5d %6d %d ", (void *)node, node->fSerialNum, nodeTypeNames[node->fType], node->fRuleRoot?'R':' ', node->fChainIn?'C':' ', serial(node->fLeftChild), serial(node->fRightChild), serial(node->fParent), node->fFirstPos, node->fVal); if (node->fType == varRef) { RBBI_DEBUG_printUnicodeString(node->fText); } } RBBIDebugPrintf("\n"); } #endif #ifdef RBBI_DEBUG U_CFUNC void RBBI_DEBUG_printUnicodeString(const UnicodeString &s, int minWidth) { RBBIDebugPrintf("%*s", minWidth, CStr(s)()); } #endif //------------------------------------------------------------------------- // // print. Print out the tree of nodes rooted at "this" // //------------------------------------------------------------------------- #ifdef RBBI_DEBUG void RBBINode::printNodeHeader() { RBBIDebugPrintf(" Address serial type LeftChild RightChild Parent position value\n"); } void RBBINode::printTree(const RBBINode *node, UBool printHeading) { if (printHeading) { printNodeHeader(); } printNode(node); if (node != nullptr) { // Only dump the definition under a variable reference if asked to. // Unconditionally dump children of all other node types. if (node->fType != varRef) { if (node->fLeftChild != nullptr) { printTree(node->fLeftChild, false); } if (node->fRightChild != nullptr) { printTree(node->fRightChild, false); } } } } #endif U_NAMESPACE_END #endif /* #if !UCONFIG_NO_BREAK_ITERATION */