]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/rbbinode.cpp
2 ***************************************************************************
3 * Copyright (C) 2002-2006 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 if (fLeftChild
!= NULL
) {
153 n
->fLeftChild
= fLeftChild
->cloneTree();
154 n
->fLeftChild
->fParent
= n
;
156 if (fRightChild
!= NULL
) {
157 n
->fRightChild
= fRightChild
->cloneTree();
158 n
->fRightChild
->fParent
= n
;
166 //-------------------------------------------------------------------------
168 // flattenVariables Walk a parse tree, replacing any variable
169 // references with a copy of the variable's definition.
170 // Aside from variables, the tree is not changed.
172 // Return the root of the tree. If the root was not a variable
173 // reference, it remains unchanged - the root we started with
174 // is the root we return. If, however, the root was a variable
175 // reference, the root of the newly cloned replacement tree will
176 // be returned, and the original tree deleted.
178 // This function works by recursively walking the tree
179 // without doing anything until a variable reference is
180 // found, then calling cloneTree() at that point. Any
181 // nested references are handled by cloneTree(), not here.
183 //-------------------------------------------------------------------------
184 RBBINode
*RBBINode::flattenVariables() {
185 if (fType
== varRef
) {
186 RBBINode
*retNode
= fLeftChild
->cloneTree();
191 if (fLeftChild
!= NULL
) {
192 fLeftChild
= fLeftChild
->flattenVariables();
193 fLeftChild
->fParent
= this;
195 if (fRightChild
!= NULL
) {
196 fRightChild
= fRightChild
->flattenVariables();
197 fRightChild
->fParent
= this;
203 //-------------------------------------------------------------------------
205 // flattenSets Walk the parse tree, replacing any nodes of type setRef
206 // with a copy of the expression tree for the set. A set's
207 // equivalent expression tree is precomputed and saved as
208 // the left child of the uset node.
210 //-------------------------------------------------------------------------
211 void RBBINode::flattenSets() {
212 U_ASSERT(fType
!= setRef
);
214 if (fLeftChild
!= NULL
) {
215 if (fLeftChild
->fType
==setRef
) {
216 RBBINode
*setRefNode
= fLeftChild
;
217 RBBINode
*usetNode
= setRefNode
->fLeftChild
;
218 RBBINode
*replTree
= usetNode
->fLeftChild
;
219 fLeftChild
= replTree
->cloneTree();
220 fLeftChild
->fParent
= this;
223 fLeftChild
->flattenSets();
227 if (fRightChild
!= NULL
) {
228 if (fRightChild
->fType
==setRef
) {
229 RBBINode
*setRefNode
= fRightChild
;
230 RBBINode
*usetNode
= setRefNode
->fLeftChild
;
231 RBBINode
*replTree
= usetNode
->fLeftChild
;
232 fRightChild
= replTree
->cloneTree();
233 fRightChild
->fParent
= this;
236 fRightChild
->flattenSets();
243 //-------------------------------------------------------------------------
245 // findNodes() Locate all the nodes of the specified type, starting
246 // at the specified root.
248 //-------------------------------------------------------------------------
249 void RBBINode::findNodes(UVector
*dest
, RBBINode::NodeType kind
, UErrorCode
&status
) {
250 /* test for buffer overflows */
251 if (U_FAILURE(status
)) {
255 dest
->addElement(this, status
);
257 if (fLeftChild
!= NULL
) {
258 fLeftChild
->findNodes(dest
, kind
, status
);
260 if (fRightChild
!= NULL
) {
261 fRightChild
->findNodes(dest
, kind
, status
);
266 //-------------------------------------------------------------------------
268 // print. Print out a single node, for debugging.
270 //-------------------------------------------------------------------------
272 void RBBINode::printNode() {
273 static const char * const nodeTypeNames
[] = {
293 RBBIDebugPrintf("%10p", (void *)this);
295 RBBIDebugPrintf("%10p %12s %10p %10p %10p %4d %6d %d ",
296 (void *)this, nodeTypeNames
[fType
], (void *)fParent
, (void *)fLeftChild
, (void *)fRightChild
,
297 fSerialNum
, fFirstPos
, fVal
);
298 if (fType
== varRef
) {
299 RBBI_DEBUG_printUnicodeString(fText
);
302 RBBIDebugPrintf("\n");
308 U_CFUNC
void RBBI_DEBUG_printUnicodeString(const UnicodeString
&s
, int minWidth
)
311 for (i
=0; i
<s
.length(); i
++) {
312 RBBIDebugPrintf("%c", s
.charAt(i
));
313 // putc(s.charAt(i), stdout);
315 for (i
=s
.length(); i
<minWidth
; i
++) {
316 RBBIDebugPrintf(" ");
322 //-------------------------------------------------------------------------
324 // print. Print out the tree of nodes rooted at "this"
326 //-------------------------------------------------------------------------
328 void RBBINode::printTree(UBool printHeading
) {
330 RBBIDebugPrintf( "-------------------------------------------------------------------\n"
331 " Address type Parent LeftChild RightChild serial position value\n"
336 // Only dump the definition under a variable reference if asked to.
337 // Unconditinally dump children of all other node types.
338 if (fType
!= varRef
) {
339 if (fLeftChild
!= NULL
) {
340 fLeftChild
->printTree(FALSE
);
343 if (fRightChild
!= NULL
) {
344 fRightChild
->printTree(FALSE
);
355 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */