]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/rbbinode.cpp
2 ***************************************************************************
3 * Copyright (C) 2002-2003 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"
36 int RBBINode::gLastSerial
= 0;
40 //-------------------------------------------------------------------------
42 // Constructor. Just set the fields to reasonable default values.
44 //-------------------------------------------------------------------------
45 RBBINode::RBBINode(NodeType t
) : UMemory() {
46 fSerialNum
= ++gLastSerial
;
55 fLookAheadEnd
= FALSE
;
57 fPrecedence
= precZero
;
59 UErrorCode status
= U_ZERO_ERROR
;
60 fFirstPosSet
= new UVector(status
); // TODO - get a real status from somewhere
61 fLastPosSet
= new UVector(status
);
62 fFollowPos
= new UVector(status
);
63 if (t
==opCat
) {fPrecedence
= precOpCat
;}
64 else if (t
==opOr
) {fPrecedence
= precOpOr
;}
65 else if (t
==opStart
) {fPrecedence
= precStart
;}
66 else if (t
==opLParen
) {fPrecedence
= precLParen
;}
71 RBBINode::RBBINode(const RBBINode
&other
) : UMemory(other
) {
72 fSerialNum
= ++gLastSerial
;
77 fInputSet
= other
.fInputSet
;
78 fPrecedence
= other
.fPrecedence
;
80 fFirstPos
= other
.fFirstPos
;
81 fLastPos
= other
.fLastPos
;
82 fNullable
= other
.fNullable
;
84 UErrorCode status
= U_ZERO_ERROR
;
85 fFirstPosSet
= new UVector(status
); // TODO - get a real status from somewhere
86 fLastPosSet
= new UVector(status
);
87 fFollowPos
= new UVector(status
);
91 //-------------------------------------------------------------------------
93 // Destructor. Deletes both this node AND any child nodes,
94 // except in the case of variable reference nodes. For
95 // these, the l. child points back to the definition, which
96 // is common for all references to the variable, meaning
97 // it can't be deleted here.
99 //-------------------------------------------------------------------------
100 RBBINode::~RBBINode() {
101 // printf("deleting node %8x serial %4d\n", this, this->fSerialNum);
105 switch (this->fType
) {
108 // for these node types, multiple instances point to the same "children"
109 // Storage ownership of children handled elsewhere. Don't delete here.
127 //-------------------------------------------------------------------------
129 // cloneTree Make a copy of the subtree rooted at this node.
130 // Discard any variable references encountered along the way,
131 // and replace with copies of the variable's definitions.
132 // Used to replicate the expression underneath variable
133 // references in preparation for generating the DFA tables.
135 //-------------------------------------------------------------------------
136 RBBINode
*RBBINode::cloneTree() {
139 if (fType
== RBBINode::varRef
) {
140 // If the current node is a variable reference, skip over it
141 // and clone the definition of the variable instead.
142 n
= fLeftChild
->cloneTree();
143 } else if (fType
== RBBINode::uset
) {
146 n
= new RBBINode(*this);
147 if (fLeftChild
!= NULL
) {
148 n
->fLeftChild
= fLeftChild
->cloneTree();
149 n
->fLeftChild
->fParent
= n
;
151 if (fRightChild
!= NULL
) {
152 n
->fRightChild
= fRightChild
->cloneTree();
153 n
->fRightChild
->fParent
= n
;
161 //-------------------------------------------------------------------------
163 // flattenVariables Walk a parse tree, replacing any variable
164 // references with a copy of the variable's definition.
165 // Aside from variables, the tree is not changed.
167 // Return the root of the tree. If the root was not a variable
168 // reference, it remains unchanged - the root we started with
169 // is the root we return. If, however, the root was a variable
170 // reference, the root of the newly cloned replacement tree will
171 // be returned, and the original tree deleted.
173 // This function works by recursively walking the tree
174 // without doing anything until a variable reference is
175 // found, then calling cloneTree() at that point. Any
176 // nested references are handled by cloneTree(), not here.
178 //-------------------------------------------------------------------------
179 RBBINode
*RBBINode::flattenVariables() {
180 if (fType
== varRef
) {
181 RBBINode
*retNode
= fLeftChild
->cloneTree();
186 if (fLeftChild
!= NULL
) {
187 fLeftChild
= fLeftChild
->flattenVariables();
188 fLeftChild
->fParent
= this;
190 if (fRightChild
!= NULL
) {
191 fRightChild
= fRightChild
->flattenVariables();
192 fRightChild
->fParent
= this;
198 //-------------------------------------------------------------------------
200 // flattenSets Walk the parse tree, replacing any nodes of type setRef
201 // with a copy of the expression tree for the set. A set's
202 // equivalent expression tree is precomputed and saved as
203 // the left child of the uset node.
205 //-------------------------------------------------------------------------
206 void RBBINode::flattenSets() {
207 U_ASSERT(fType
!= setRef
);
209 if (fLeftChild
!= NULL
) {
210 if (fLeftChild
->fType
==setRef
) {
211 RBBINode
*setRefNode
= fLeftChild
;
212 RBBINode
*usetNode
= setRefNode
->fLeftChild
;
213 RBBINode
*replTree
= usetNode
->fLeftChild
;
214 fLeftChild
= replTree
->cloneTree();
215 fLeftChild
->fParent
= this;
218 fLeftChild
->flattenSets();
222 if (fRightChild
!= NULL
) {
223 if (fRightChild
->fType
==setRef
) {
224 RBBINode
*setRefNode
= fRightChild
;
225 RBBINode
*usetNode
= setRefNode
->fLeftChild
;
226 RBBINode
*replTree
= usetNode
->fLeftChild
;
227 fRightChild
= replTree
->cloneTree();
228 fRightChild
->fParent
= this;
231 fRightChild
->flattenSets();
238 //-------------------------------------------------------------------------
240 // findNodes() Locate all the nodes of the specified type, starting
241 // at the specified root.
243 //-------------------------------------------------------------------------
244 void RBBINode::findNodes(UVector
*dest
, RBBINode::NodeType kind
, UErrorCode
&status
) {
245 /* test for buffer overflows */
246 if (U_FAILURE(status
)) {
250 dest
->addElement(this, status
);
252 if (fLeftChild
!= NULL
) {
253 fLeftChild
->findNodes(dest
, kind
, status
);
255 if (fRightChild
!= NULL
) {
256 fRightChild
->findNodes(dest
, kind
, status
);
261 //-------------------------------------------------------------------------
263 // print. Print out a single node, for debugging.
265 //-------------------------------------------------------------------------
267 void RBBINode::printNode() {
268 static const char * const nodeTypeNames
[] = {
288 RBBIDebugPrintf("%10p", (void *)this);
290 RBBIDebugPrintf("%10p %12s %10p %10p %10p %4d %6d %d ",
291 (void *)this, nodeTypeNames
[fType
], (void *)fParent
, (void *)fLeftChild
, (void *)fRightChild
,
292 fSerialNum
, fFirstPos
, fVal
);
293 if (fType
== varRef
) {
294 RBBI_DEBUG_printUnicodeString(fText
);
297 RBBIDebugPrintf("\n");
303 U_CFUNC
void RBBI_DEBUG_printUnicodeString(const UnicodeString
&s
, int minWidth
)
306 for (i
=0; i
<s
.length(); i
++) {
307 RBBIDebugPrintf("%c", s
.charAt(i
));
308 // putc(s.charAt(i), stdout);
310 for (i
=s
.length(); i
<minWidth
; i
++) {
311 RBBIDebugPrintf(" ");
317 //-------------------------------------------------------------------------
319 // print. Print out the tree of nodes rooted at "this"
321 //-------------------------------------------------------------------------
323 void RBBINode::printTree(UBool printHeading
) {
325 RBBIDebugPrintf( "-------------------------------------------------------------------\n"
326 " Address type Parent LeftChild RightChild serial position value\n"
331 // Only dump the definition under a variable reference if asked to.
332 // Unconditinally dump children of all other node types.
333 if (fType
!= varRef
) {
334 if (fLeftChild
!= NULL
) {
335 fLeftChild
->printTree(FALSE
);
338 if (fRightChild
!= NULL
) {
339 fRightChild
->printTree(FALSE
);
350 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */