Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* |
michael@0 | 2 | *************************************************************************** |
michael@0 | 3 | * Copyright (C) 2002-2008 International Business Machines Corporation * |
michael@0 | 4 | * and others. All rights reserved. * |
michael@0 | 5 | *************************************************************************** |
michael@0 | 6 | */ |
michael@0 | 7 | |
michael@0 | 8 | // |
michael@0 | 9 | // File: rbbinode.cpp |
michael@0 | 10 | // |
michael@0 | 11 | // Implementation of class RBBINode, which represents a node in the |
michael@0 | 12 | // tree generated when parsing the Rules Based Break Iterator rules. |
michael@0 | 13 | // |
michael@0 | 14 | // This "Class" is actually closer to a struct. |
michael@0 | 15 | // Code using it is expected to directly access fields much of the time. |
michael@0 | 16 | // |
michael@0 | 17 | |
michael@0 | 18 | #include "unicode/utypes.h" |
michael@0 | 19 | |
michael@0 | 20 | #if !UCONFIG_NO_BREAK_ITERATION |
michael@0 | 21 | |
michael@0 | 22 | #include "unicode/unistr.h" |
michael@0 | 23 | #include "unicode/uniset.h" |
michael@0 | 24 | #include "unicode/uchar.h" |
michael@0 | 25 | #include "unicode/parsepos.h" |
michael@0 | 26 | #include "uvector.h" |
michael@0 | 27 | |
michael@0 | 28 | #include "rbbirb.h" |
michael@0 | 29 | #include "rbbinode.h" |
michael@0 | 30 | |
michael@0 | 31 | #include "uassert.h" |
michael@0 | 32 | |
michael@0 | 33 | |
michael@0 | 34 | U_NAMESPACE_BEGIN |
michael@0 | 35 | |
michael@0 | 36 | #ifdef RBBI_DEBUG |
michael@0 | 37 | static int gLastSerial = 0; |
michael@0 | 38 | #endif |
michael@0 | 39 | |
michael@0 | 40 | |
michael@0 | 41 | //------------------------------------------------------------------------- |
michael@0 | 42 | // |
michael@0 | 43 | // Constructor. Just set the fields to reasonable default values. |
michael@0 | 44 | // |
michael@0 | 45 | //------------------------------------------------------------------------- |
michael@0 | 46 | RBBINode::RBBINode(NodeType t) : UMemory() { |
michael@0 | 47 | #ifdef RBBI_DEBUG |
michael@0 | 48 | fSerialNum = ++gLastSerial; |
michael@0 | 49 | #endif |
michael@0 | 50 | fType = t; |
michael@0 | 51 | fParent = NULL; |
michael@0 | 52 | fLeftChild = NULL; |
michael@0 | 53 | fRightChild = NULL; |
michael@0 | 54 | fInputSet = NULL; |
michael@0 | 55 | fFirstPos = 0; |
michael@0 | 56 | fLastPos = 0; |
michael@0 | 57 | fNullable = FALSE; |
michael@0 | 58 | fLookAheadEnd = FALSE; |
michael@0 | 59 | fVal = 0; |
michael@0 | 60 | fPrecedence = precZero; |
michael@0 | 61 | |
michael@0 | 62 | UErrorCode status = U_ZERO_ERROR; |
michael@0 | 63 | fFirstPosSet = new UVector(status); // TODO - get a real status from somewhere |
michael@0 | 64 | fLastPosSet = new UVector(status); |
michael@0 | 65 | fFollowPos = new UVector(status); |
michael@0 | 66 | if (t==opCat) {fPrecedence = precOpCat;} |
michael@0 | 67 | else if (t==opOr) {fPrecedence = precOpOr;} |
michael@0 | 68 | else if (t==opStart) {fPrecedence = precStart;} |
michael@0 | 69 | else if (t==opLParen) {fPrecedence = precLParen;} |
michael@0 | 70 | |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | |
michael@0 | 74 | RBBINode::RBBINode(const RBBINode &other) : UMemory(other) { |
michael@0 | 75 | #ifdef RBBI_DEBUG |
michael@0 | 76 | fSerialNum = ++gLastSerial; |
michael@0 | 77 | #endif |
michael@0 | 78 | fType = other.fType; |
michael@0 | 79 | fParent = NULL; |
michael@0 | 80 | fLeftChild = NULL; |
michael@0 | 81 | fRightChild = NULL; |
michael@0 | 82 | fInputSet = other.fInputSet; |
michael@0 | 83 | fPrecedence = other.fPrecedence; |
michael@0 | 84 | fText = other.fText; |
michael@0 | 85 | fFirstPos = other.fFirstPos; |
michael@0 | 86 | fLastPos = other.fLastPos; |
michael@0 | 87 | fNullable = other.fNullable; |
michael@0 | 88 | fVal = other.fVal; |
michael@0 | 89 | UErrorCode status = U_ZERO_ERROR; |
michael@0 | 90 | fFirstPosSet = new UVector(status); // TODO - get a real status from somewhere |
michael@0 | 91 | fLastPosSet = new UVector(status); |
michael@0 | 92 | fFollowPos = new UVector(status); |
michael@0 | 93 | } |
michael@0 | 94 | |
michael@0 | 95 | |
michael@0 | 96 | //------------------------------------------------------------------------- |
michael@0 | 97 | // |
michael@0 | 98 | // Destructor. Deletes both this node AND any child nodes, |
michael@0 | 99 | // except in the case of variable reference nodes. For |
michael@0 | 100 | // these, the l. child points back to the definition, which |
michael@0 | 101 | // is common for all references to the variable, meaning |
michael@0 | 102 | // it can't be deleted here. |
michael@0 | 103 | // |
michael@0 | 104 | //------------------------------------------------------------------------- |
michael@0 | 105 | RBBINode::~RBBINode() { |
michael@0 | 106 | // printf("deleting node %8x serial %4d\n", this, this->fSerialNum); |
michael@0 | 107 | delete fInputSet; |
michael@0 | 108 | fInputSet = NULL; |
michael@0 | 109 | |
michael@0 | 110 | switch (this->fType) { |
michael@0 | 111 | case varRef: |
michael@0 | 112 | case setRef: |
michael@0 | 113 | // for these node types, multiple instances point to the same "children" |
michael@0 | 114 | // Storage ownership of children handled elsewhere. Don't delete here. |
michael@0 | 115 | break; |
michael@0 | 116 | |
michael@0 | 117 | default: |
michael@0 | 118 | delete fLeftChild; |
michael@0 | 119 | fLeftChild = NULL; |
michael@0 | 120 | delete fRightChild; |
michael@0 | 121 | fRightChild = NULL; |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | |
michael@0 | 125 | delete fFirstPosSet; |
michael@0 | 126 | delete fLastPosSet; |
michael@0 | 127 | delete fFollowPos; |
michael@0 | 128 | |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | |
michael@0 | 132 | //------------------------------------------------------------------------- |
michael@0 | 133 | // |
michael@0 | 134 | // cloneTree Make a copy of the subtree rooted at this node. |
michael@0 | 135 | // Discard any variable references encountered along the way, |
michael@0 | 136 | // and replace with copies of the variable's definitions. |
michael@0 | 137 | // Used to replicate the expression underneath variable |
michael@0 | 138 | // references in preparation for generating the DFA tables. |
michael@0 | 139 | // |
michael@0 | 140 | //------------------------------------------------------------------------- |
michael@0 | 141 | RBBINode *RBBINode::cloneTree() { |
michael@0 | 142 | RBBINode *n; |
michael@0 | 143 | |
michael@0 | 144 | if (fType == RBBINode::varRef) { |
michael@0 | 145 | // If the current node is a variable reference, skip over it |
michael@0 | 146 | // and clone the definition of the variable instead. |
michael@0 | 147 | n = fLeftChild->cloneTree(); |
michael@0 | 148 | } else if (fType == RBBINode::uset) { |
michael@0 | 149 | n = this; |
michael@0 | 150 | } else { |
michael@0 | 151 | n = new RBBINode(*this); |
michael@0 | 152 | // Check for null pointer. |
michael@0 | 153 | if (n != NULL) { |
michael@0 | 154 | if (fLeftChild != NULL) { |
michael@0 | 155 | n->fLeftChild = fLeftChild->cloneTree(); |
michael@0 | 156 | n->fLeftChild->fParent = n; |
michael@0 | 157 | } |
michael@0 | 158 | if (fRightChild != NULL) { |
michael@0 | 159 | n->fRightChild = fRightChild->cloneTree(); |
michael@0 | 160 | n->fRightChild->fParent = n; |
michael@0 | 161 | } |
michael@0 | 162 | } |
michael@0 | 163 | } |
michael@0 | 164 | return n; |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | |
michael@0 | 168 | |
michael@0 | 169 | //------------------------------------------------------------------------- |
michael@0 | 170 | // |
michael@0 | 171 | // flattenVariables Walk a parse tree, replacing any variable |
michael@0 | 172 | // references with a copy of the variable's definition. |
michael@0 | 173 | // Aside from variables, the tree is not changed. |
michael@0 | 174 | // |
michael@0 | 175 | // Return the root of the tree. If the root was not a variable |
michael@0 | 176 | // reference, it remains unchanged - the root we started with |
michael@0 | 177 | // is the root we return. If, however, the root was a variable |
michael@0 | 178 | // reference, the root of the newly cloned replacement tree will |
michael@0 | 179 | // be returned, and the original tree deleted. |
michael@0 | 180 | // |
michael@0 | 181 | // This function works by recursively walking the tree |
michael@0 | 182 | // without doing anything until a variable reference is |
michael@0 | 183 | // found, then calling cloneTree() at that point. Any |
michael@0 | 184 | // nested references are handled by cloneTree(), not here. |
michael@0 | 185 | // |
michael@0 | 186 | //------------------------------------------------------------------------- |
michael@0 | 187 | RBBINode *RBBINode::flattenVariables() { |
michael@0 | 188 | if (fType == varRef) { |
michael@0 | 189 | RBBINode *retNode = fLeftChild->cloneTree(); |
michael@0 | 190 | delete this; |
michael@0 | 191 | return retNode; |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | if (fLeftChild != NULL) { |
michael@0 | 195 | fLeftChild = fLeftChild->flattenVariables(); |
michael@0 | 196 | fLeftChild->fParent = this; |
michael@0 | 197 | } |
michael@0 | 198 | if (fRightChild != NULL) { |
michael@0 | 199 | fRightChild = fRightChild->flattenVariables(); |
michael@0 | 200 | fRightChild->fParent = this; |
michael@0 | 201 | } |
michael@0 | 202 | return this; |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | |
michael@0 | 206 | //------------------------------------------------------------------------- |
michael@0 | 207 | // |
michael@0 | 208 | // flattenSets Walk the parse tree, replacing any nodes of type setRef |
michael@0 | 209 | // with a copy of the expression tree for the set. A set's |
michael@0 | 210 | // equivalent expression tree is precomputed and saved as |
michael@0 | 211 | // the left child of the uset node. |
michael@0 | 212 | // |
michael@0 | 213 | //------------------------------------------------------------------------- |
michael@0 | 214 | void RBBINode::flattenSets() { |
michael@0 | 215 | U_ASSERT(fType != setRef); |
michael@0 | 216 | |
michael@0 | 217 | if (fLeftChild != NULL) { |
michael@0 | 218 | if (fLeftChild->fType==setRef) { |
michael@0 | 219 | RBBINode *setRefNode = fLeftChild; |
michael@0 | 220 | RBBINode *usetNode = setRefNode->fLeftChild; |
michael@0 | 221 | RBBINode *replTree = usetNode->fLeftChild; |
michael@0 | 222 | fLeftChild = replTree->cloneTree(); |
michael@0 | 223 | fLeftChild->fParent = this; |
michael@0 | 224 | delete setRefNode; |
michael@0 | 225 | } else { |
michael@0 | 226 | fLeftChild->flattenSets(); |
michael@0 | 227 | } |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | if (fRightChild != NULL) { |
michael@0 | 231 | if (fRightChild->fType==setRef) { |
michael@0 | 232 | RBBINode *setRefNode = fRightChild; |
michael@0 | 233 | RBBINode *usetNode = setRefNode->fLeftChild; |
michael@0 | 234 | RBBINode *replTree = usetNode->fLeftChild; |
michael@0 | 235 | fRightChild = replTree->cloneTree(); |
michael@0 | 236 | fRightChild->fParent = this; |
michael@0 | 237 | delete setRefNode; |
michael@0 | 238 | } else { |
michael@0 | 239 | fRightChild->flattenSets(); |
michael@0 | 240 | } |
michael@0 | 241 | } |
michael@0 | 242 | } |
michael@0 | 243 | |
michael@0 | 244 | |
michael@0 | 245 | |
michael@0 | 246 | //------------------------------------------------------------------------- |
michael@0 | 247 | // |
michael@0 | 248 | // findNodes() Locate all the nodes of the specified type, starting |
michael@0 | 249 | // at the specified root. |
michael@0 | 250 | // |
michael@0 | 251 | //------------------------------------------------------------------------- |
michael@0 | 252 | void RBBINode::findNodes(UVector *dest, RBBINode::NodeType kind, UErrorCode &status) { |
michael@0 | 253 | /* test for buffer overflows */ |
michael@0 | 254 | if (U_FAILURE(status)) { |
michael@0 | 255 | return; |
michael@0 | 256 | } |
michael@0 | 257 | if (fType == kind) { |
michael@0 | 258 | dest->addElement(this, status); |
michael@0 | 259 | } |
michael@0 | 260 | if (fLeftChild != NULL) { |
michael@0 | 261 | fLeftChild->findNodes(dest, kind, status); |
michael@0 | 262 | } |
michael@0 | 263 | if (fRightChild != NULL) { |
michael@0 | 264 | fRightChild->findNodes(dest, kind, status); |
michael@0 | 265 | } |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | |
michael@0 | 269 | //------------------------------------------------------------------------- |
michael@0 | 270 | // |
michael@0 | 271 | // print. Print out a single node, for debugging. |
michael@0 | 272 | // |
michael@0 | 273 | //------------------------------------------------------------------------- |
michael@0 | 274 | #ifdef RBBI_DEBUG |
michael@0 | 275 | void RBBINode::printNode() { |
michael@0 | 276 | static const char * const nodeTypeNames[] = { |
michael@0 | 277 | "setRef", |
michael@0 | 278 | "uset", |
michael@0 | 279 | "varRef", |
michael@0 | 280 | "leafChar", |
michael@0 | 281 | "lookAhead", |
michael@0 | 282 | "tag", |
michael@0 | 283 | "endMark", |
michael@0 | 284 | "opStart", |
michael@0 | 285 | "opCat", |
michael@0 | 286 | "opOr", |
michael@0 | 287 | "opStar", |
michael@0 | 288 | "opPlus", |
michael@0 | 289 | "opQuestion", |
michael@0 | 290 | "opBreak", |
michael@0 | 291 | "opReverse", |
michael@0 | 292 | "opLParen" |
michael@0 | 293 | }; |
michael@0 | 294 | |
michael@0 | 295 | if (this==NULL) { |
michael@0 | 296 | RBBIDebugPrintf("%10p", (void *)this); |
michael@0 | 297 | } else { |
michael@0 | 298 | RBBIDebugPrintf("%10p %12s %10p %10p %10p %4d %6d %d ", |
michael@0 | 299 | (void *)this, nodeTypeNames[fType], (void *)fParent, (void *)fLeftChild, (void *)fRightChild, |
michael@0 | 300 | fSerialNum, fFirstPos, fVal); |
michael@0 | 301 | if (fType == varRef) { |
michael@0 | 302 | RBBI_DEBUG_printUnicodeString(fText); |
michael@0 | 303 | } |
michael@0 | 304 | } |
michael@0 | 305 | RBBIDebugPrintf("\n"); |
michael@0 | 306 | } |
michael@0 | 307 | #endif |
michael@0 | 308 | |
michael@0 | 309 | |
michael@0 | 310 | #ifdef RBBI_DEBUG |
michael@0 | 311 | U_CFUNC void RBBI_DEBUG_printUnicodeString(const UnicodeString &s, int minWidth) |
michael@0 | 312 | { |
michael@0 | 313 | int i; |
michael@0 | 314 | for (i=0; i<s.length(); i++) { |
michael@0 | 315 | RBBIDebugPrintf("%c", s.charAt(i)); |
michael@0 | 316 | // putc(s.charAt(i), stdout); |
michael@0 | 317 | } |
michael@0 | 318 | for (i=s.length(); i<minWidth; i++) { |
michael@0 | 319 | RBBIDebugPrintf(" "); |
michael@0 | 320 | } |
michael@0 | 321 | } |
michael@0 | 322 | #endif |
michael@0 | 323 | |
michael@0 | 324 | |
michael@0 | 325 | //------------------------------------------------------------------------- |
michael@0 | 326 | // |
michael@0 | 327 | // print. Print out the tree of nodes rooted at "this" |
michael@0 | 328 | // |
michael@0 | 329 | //------------------------------------------------------------------------- |
michael@0 | 330 | #ifdef RBBI_DEBUG |
michael@0 | 331 | void RBBINode::printTree(UBool printHeading) { |
michael@0 | 332 | if (printHeading) { |
michael@0 | 333 | RBBIDebugPrintf( "-------------------------------------------------------------------\n" |
michael@0 | 334 | " Address type Parent LeftChild RightChild serial position value\n" |
michael@0 | 335 | ); |
michael@0 | 336 | } |
michael@0 | 337 | this->printNode(); |
michael@0 | 338 | if (this != NULL) { |
michael@0 | 339 | // Only dump the definition under a variable reference if asked to. |
michael@0 | 340 | // Unconditinally dump children of all other node types. |
michael@0 | 341 | if (fType != varRef) { |
michael@0 | 342 | if (fLeftChild != NULL) { |
michael@0 | 343 | fLeftChild->printTree(FALSE); |
michael@0 | 344 | } |
michael@0 | 345 | |
michael@0 | 346 | if (fRightChild != NULL) { |
michael@0 | 347 | fRightChild->printTree(FALSE); |
michael@0 | 348 | } |
michael@0 | 349 | } |
michael@0 | 350 | } |
michael@0 | 351 | } |
michael@0 | 352 | #endif |
michael@0 | 353 | |
michael@0 | 354 | |
michael@0 | 355 | |
michael@0 | 356 | U_NAMESPACE_END |
michael@0 | 357 | |
michael@0 | 358 | #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ |