]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/rbbinode.cpp
2 ***************************************************************************
3 * Copyright (C) 2002-2008 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
;
60 fPrecedence
= precZero
;
62 UErrorCode status
= U_ZERO_ERROR
;
63 fFirstPosSet
= new UVector(status
); // TODO - get a real status from somewhere
64 fLastPosSet
= new UVector(status
);
65 fFollowPos
= new UVector(status
);
66 if (t
==opCat
) {fPrecedence
= precOpCat
;}
67 else if (t
==opOr
) {fPrecedence
= precOpOr
;}
68 else if (t
==opStart
) {fPrecedence
= precStart
;}
69 else if (t
==opLParen
) {fPrecedence
= precLParen
;}
74 RBBINode::RBBINode(const RBBINode
&other
) : UMemory(other
) {
76 fSerialNum
= ++gLastSerial
;
82 fInputSet
= other
.fInputSet
;
83 fPrecedence
= other
.fPrecedence
;
85 fFirstPos
= other
.fFirstPos
;
86 fLastPos
= other
.fLastPos
;
87 fNullable
= other
.fNullable
;
89 UErrorCode status
= U_ZERO_ERROR
;
90 fFirstPosSet
= new UVector(status
); // TODO - get a real status from somewhere
91 fLastPosSet
= new UVector(status
);
92 fFollowPos
= new UVector(status
);
96 //-------------------------------------------------------------------------
98 // Destructor. Deletes both this node AND any child nodes,
99 // except in the case of variable reference nodes. For
100 // these, the l. child points back to the definition, which
101 // is common for all references to the variable, meaning
102 // it can't be deleted here.
104 //-------------------------------------------------------------------------
105 RBBINode::~RBBINode() {
106 // printf("deleting node %8x serial %4d\n", this, this->fSerialNum);
110 switch (this->fType
) {
113 // for these node types, multiple instances point to the same "children"
114 // Storage ownership of children handled elsewhere. Don't delete here.
132 //-------------------------------------------------------------------------
134 // cloneTree Make a copy of the subtree rooted at this node.
135 // Discard any variable references encountered along the way,
136 // and replace with copies of the variable's definitions.
137 // Used to replicate the expression underneath variable
138 // references in preparation for generating the DFA tables.
140 //-------------------------------------------------------------------------
141 RBBINode
*RBBINode::cloneTree() {
144 if (fType
== RBBINode::varRef
) {
145 // If the current node is a variable reference, skip over it
146 // and clone the definition of the variable instead.
147 n
= fLeftChild
->cloneTree();
148 } else if (fType
== RBBINode::uset
) {
151 n
= new RBBINode(*this);
152 // Check for null pointer.
154 if (fLeftChild
!= NULL
) {
155 n
->fLeftChild
= fLeftChild
->cloneTree();
156 n
->fLeftChild
->fParent
= n
;
158 if (fRightChild
!= NULL
) {
159 n
->fRightChild
= fRightChild
->cloneTree();
160 n
->fRightChild
->fParent
= n
;
169 //-------------------------------------------------------------------------
171 // flattenVariables Walk a parse tree, replacing any variable
172 // references with a copy of the variable's definition.
173 // Aside from variables, the tree is not changed.
175 // Return the root of the tree. If the root was not a variable
176 // reference, it remains unchanged - the root we started with
177 // is the root we return. If, however, the root was a variable
178 // reference, the root of the newly cloned replacement tree will
179 // be returned, and the original tree deleted.
181 // This function works by recursively walking the tree
182 // without doing anything until a variable reference is
183 // found, then calling cloneTree() at that point. Any
184 // nested references are handled by cloneTree(), not here.
186 //-------------------------------------------------------------------------
187 RBBINode
*RBBINode::flattenVariables() {
188 if (fType
== varRef
) {
189 RBBINode
*retNode
= fLeftChild
->cloneTree();
194 if (fLeftChild
!= NULL
) {
195 fLeftChild
= fLeftChild
->flattenVariables();
196 fLeftChild
->fParent
= this;
198 if (fRightChild
!= NULL
) {
199 fRightChild
= fRightChild
->flattenVariables();
200 fRightChild
->fParent
= this;
206 //-------------------------------------------------------------------------
208 // flattenSets Walk the parse tree, replacing any nodes of type setRef
209 // with a copy of the expression tree for the set. A set's
210 // equivalent expression tree is precomputed and saved as
211 // the left child of the uset node.
213 //-------------------------------------------------------------------------
214 void RBBINode::flattenSets() {
215 U_ASSERT(fType
!= setRef
);
217 if (fLeftChild
!= NULL
) {
218 if (fLeftChild
->fType
==setRef
) {
219 RBBINode
*setRefNode
= fLeftChild
;
220 RBBINode
*usetNode
= setRefNode
->fLeftChild
;
221 RBBINode
*replTree
= usetNode
->fLeftChild
;
222 fLeftChild
= replTree
->cloneTree();
223 fLeftChild
->fParent
= this;
226 fLeftChild
->flattenSets();
230 if (fRightChild
!= NULL
) {
231 if (fRightChild
->fType
==setRef
) {
232 RBBINode
*setRefNode
= fRightChild
;
233 RBBINode
*usetNode
= setRefNode
->fLeftChild
;
234 RBBINode
*replTree
= usetNode
->fLeftChild
;
235 fRightChild
= replTree
->cloneTree();
236 fRightChild
->fParent
= this;
239 fRightChild
->flattenSets();
246 //-------------------------------------------------------------------------
248 // findNodes() Locate all the nodes of the specified type, starting
249 // at the specified root.
251 //-------------------------------------------------------------------------
252 void RBBINode::findNodes(UVector
*dest
, RBBINode::NodeType kind
, UErrorCode
&status
) {
253 /* test for buffer overflows */
254 if (U_FAILURE(status
)) {
258 dest
->addElement(this, status
);
260 if (fLeftChild
!= NULL
) {
261 fLeftChild
->findNodes(dest
, kind
, status
);
263 if (fRightChild
!= NULL
) {
264 fRightChild
->findNodes(dest
, kind
, status
);
269 //-------------------------------------------------------------------------
271 // print. Print out a single node, for debugging.
273 //-------------------------------------------------------------------------
275 void RBBINode::printNode() {
276 static const char * const nodeTypeNames
[] = {
296 RBBIDebugPrintf("%10p", (void *)this);
298 RBBIDebugPrintf("%10p %12s %10p %10p %10p %4d %6d %d ",
299 (void *)this, nodeTypeNames
[fType
], (void *)fParent
, (void *)fLeftChild
, (void *)fRightChild
,
300 fSerialNum
, fFirstPos
, fVal
);
301 if (fType
== varRef
) {
302 RBBI_DEBUG_printUnicodeString(fText
);
305 RBBIDebugPrintf("\n");
311 U_CFUNC
void RBBI_DEBUG_printUnicodeString(const UnicodeString
&s
, int minWidth
)
314 for (i
=0; i
<s
.length(); i
++) {
315 RBBIDebugPrintf("%c", s
.charAt(i
));
316 // putc(s.charAt(i), stdout);
318 for (i
=s
.length(); i
<minWidth
; i
++) {
319 RBBIDebugPrintf(" ");
325 //-------------------------------------------------------------------------
327 // print. Print out the tree of nodes rooted at "this"
329 //-------------------------------------------------------------------------
331 void RBBINode::printTree(UBool printHeading
) {
333 RBBIDebugPrintf( "-------------------------------------------------------------------\n"
334 " Address type Parent LeftChild RightChild serial position value\n"
339 // Only dump the definition under a variable reference if asked to.
340 // Unconditinally dump children of all other node types.
341 if (fType
!= varRef
) {
342 if (fLeftChild
!= NULL
) {
343 fLeftChild
->printTree(FALSE
);
346 if (fRightChild
!= NULL
) {
347 fRightChild
->printTree(FALSE
);
358 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */