]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/rbbinode.cpp
2 ***************************************************************************
3 * Copyright (C) 2002-2016 International Business Machines Corporation *
4 * and others. All rights reserved. *
5 ***************************************************************************
11 // Implementation of class RBBINode, which represents a node in the
12 // tree generated when parsing the Rules Based Break Iterator rules.
14 // This "Class" is actually closer to a struct.
15 // Code using it is expected to directly access fields much of the time.
18 #include "unicode/utypes.h"
20 #if !UCONFIG_NO_BREAK_ITERATION
22 #include "unicode/unistr.h"
23 #include "unicode/uniset.h"
24 #include "unicode/uchar.h"
25 #include "unicode/parsepos.h"
37 static int gLastSerial
= 0;
41 //-------------------------------------------------------------------------
43 // Constructor. Just set the fields to reasonable default values.
45 //-------------------------------------------------------------------------
46 RBBINode::RBBINode(NodeType t
) : UMemory() {
48 fSerialNum
= ++gLastSerial
;
58 fLookAheadEnd
= FALSE
;
62 fPrecedence
= precZero
;
64 UErrorCode status
= U_ZERO_ERROR
;
65 fFirstPosSet
= new UVector(status
); // TODO - get a real status from somewhere
66 fLastPosSet
= new UVector(status
);
67 fFollowPos
= new UVector(status
);
68 if (t
==opCat
) {fPrecedence
= precOpCat
;}
69 else if (t
==opOr
) {fPrecedence
= precOpOr
;}
70 else if (t
==opStart
) {fPrecedence
= precStart
;}
71 else if (t
==opLParen
) {fPrecedence
= precLParen
;}
76 RBBINode::RBBINode(const RBBINode
&other
) : UMemory(other
) {
78 fSerialNum
= ++gLastSerial
;
84 fInputSet
= other
.fInputSet
;
85 fPrecedence
= other
.fPrecedence
;
87 fFirstPos
= other
.fFirstPos
;
88 fLastPos
= other
.fLastPos
;
89 fNullable
= other
.fNullable
;
92 fChainIn
= other
.fChainIn
;
93 UErrorCode status
= U_ZERO_ERROR
;
94 fFirstPosSet
= new UVector(status
); // TODO - get a real status from somewhere
95 fLastPosSet
= new UVector(status
);
96 fFollowPos
= new UVector(status
);
100 //-------------------------------------------------------------------------
102 // Destructor. Deletes both this node AND any child nodes,
103 // except in the case of variable reference nodes. For
104 // these, the l. child points back to the definition, which
105 // is common for all references to the variable, meaning
106 // it can't be deleted here.
108 //-------------------------------------------------------------------------
109 RBBINode::~RBBINode() {
110 // printf("deleting node %8x serial %4d\n", this, this->fSerialNum);
114 switch (this->fType
) {
117 // for these node types, multiple instances point to the same "children"
118 // Storage ownership of children handled elsewhere. Don't delete here.
136 //-------------------------------------------------------------------------
138 // cloneTree Make a copy of the subtree rooted at this node.
139 // Discard any variable references encountered along the way,
140 // and replace with copies of the variable's definitions.
141 // Used to replicate the expression underneath variable
142 // references in preparation for generating the DFA tables.
144 //-------------------------------------------------------------------------
145 RBBINode
*RBBINode::cloneTree() {
148 if (fType
== RBBINode::varRef
) {
149 // If the current node is a variable reference, skip over it
150 // and clone the definition of the variable instead.
151 n
= fLeftChild
->cloneTree();
152 } else if (fType
== RBBINode::uset
) {
155 n
= new RBBINode(*this);
156 // Check for null pointer.
158 if (fLeftChild
!= NULL
) {
159 n
->fLeftChild
= fLeftChild
->cloneTree();
160 n
->fLeftChild
->fParent
= n
;
162 if (fRightChild
!= NULL
) {
163 n
->fRightChild
= fRightChild
->cloneTree();
164 n
->fRightChild
->fParent
= n
;
168 n
->fRuleRoot
= this->fRuleRoot
;
169 n
->fChainIn
= this->fChainIn
;
175 //-------------------------------------------------------------------------
177 // flattenVariables Walk a parse tree, replacing any variable
178 // references with a copy of the variable's definition.
179 // Aside from variables, the tree is not changed.
181 // Return the root of the tree. If the root was not a variable
182 // reference, it remains unchanged - the root we started with
183 // is the root we return. If, however, the root was a variable
184 // reference, the root of the newly cloned replacement tree will
185 // be returned, and the original tree deleted.
187 // This function works by recursively walking the tree
188 // without doing anything until a variable reference is
189 // found, then calling cloneTree() at that point. Any
190 // nested references are handled by cloneTree(), not here.
192 //-------------------------------------------------------------------------
193 RBBINode
*RBBINode::flattenVariables() {
194 if (fType
== varRef
) {
195 RBBINode
*retNode
= fLeftChild
->cloneTree();
200 if (fLeftChild
!= NULL
) {
201 fLeftChild
= fLeftChild
->flattenVariables();
202 fLeftChild
->fParent
= this;
204 if (fRightChild
!= NULL
) {
205 fRightChild
= fRightChild
->flattenVariables();
206 fRightChild
->fParent
= this;
212 //-------------------------------------------------------------------------
214 // flattenSets Walk the parse tree, replacing any nodes of type setRef
215 // with a copy of the expression tree for the set. A set's
216 // equivalent expression tree is precomputed and saved as
217 // the left child of the uset node.
219 //-------------------------------------------------------------------------
220 void RBBINode::flattenSets() {
221 U_ASSERT(fType
!= setRef
);
223 if (fLeftChild
!= NULL
) {
224 if (fLeftChild
->fType
==setRef
) {
225 RBBINode
*setRefNode
= fLeftChild
;
226 RBBINode
*usetNode
= setRefNode
->fLeftChild
;
227 RBBINode
*replTree
= usetNode
->fLeftChild
;
228 fLeftChild
= replTree
->cloneTree();
229 fLeftChild
->fParent
= this;
232 fLeftChild
->flattenSets();
236 if (fRightChild
!= NULL
) {
237 if (fRightChild
->fType
==setRef
) {
238 RBBINode
*setRefNode
= fRightChild
;
239 RBBINode
*usetNode
= setRefNode
->fLeftChild
;
240 RBBINode
*replTree
= usetNode
->fLeftChild
;
241 fRightChild
= replTree
->cloneTree();
242 fRightChild
->fParent
= this;
245 fRightChild
->flattenSets();
252 //-------------------------------------------------------------------------
254 // findNodes() Locate all the nodes of the specified type, starting
255 // at the specified root.
257 //-------------------------------------------------------------------------
258 void RBBINode::findNodes(UVector
*dest
, RBBINode::NodeType kind
, UErrorCode
&status
) {
259 /* test for buffer overflows */
260 if (U_FAILURE(status
)) {
264 dest
->addElement(this, status
);
266 if (fLeftChild
!= NULL
) {
267 fLeftChild
->findNodes(dest
, kind
, status
);
269 if (fRightChild
!= NULL
) {
270 fRightChild
->findNodes(dest
, kind
, status
);
275 //-------------------------------------------------------------------------
277 // print. Print out a single node, for debugging.
279 //-------------------------------------------------------------------------
282 static int32_t serial(const RBBINode
*node
) {
283 return (node
== NULL
? -1 : node
->fSerialNum
);
287 void RBBINode::printNode() {
288 static const char * const nodeTypeNames
[] = {
308 RBBIDebugPrintf("%10p", (void *)this);
310 RBBIDebugPrintf("%10p %5d %12s %c%c %5d %5d %5d %6d %d ",
311 (void *)this, fSerialNum
, nodeTypeNames
[fType
], fRuleRoot
?'R':' ', fChainIn
?'C':' ',
312 serial(fLeftChild
), serial(fRightChild
), serial(fParent
),
314 if (fType
== varRef
) {
315 RBBI_DEBUG_printUnicodeString(fText
);
318 RBBIDebugPrintf("\n");
324 U_CFUNC
void RBBI_DEBUG_printUnicodeString(const UnicodeString
&s
, int minWidth
)
327 for (i
=0; i
<s
.length(); i
++) {
328 RBBIDebugPrintf("%c", s
.charAt(i
));
329 // putc(s.charAt(i), stdout);
331 for (i
=s
.length(); i
<minWidth
; i
++) {
332 RBBIDebugPrintf(" ");
338 //-------------------------------------------------------------------------
340 // print. Print out the tree of nodes rooted at "this"
342 //-------------------------------------------------------------------------
344 void RBBINode::printNodeHeader() {
345 RBBIDebugPrintf(" Address serial type LeftChild RightChild Parent position value\n");
348 void RBBINode::printTree(UBool printHeading
) {
354 // Only dump the definition under a variable reference if asked to.
355 // Unconditinally dump children of all other node types.
356 if (fType
!= varRef
) {
357 if (fLeftChild
!= NULL
) {
358 fLeftChild
->printTree(FALSE
);
361 if (fRightChild
!= NULL
) {
362 fRightChild
->printTree(FALSE
);
373 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */