Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / icu / source / common / rbbiscan.cpp
1
2 //
3 //  file:  rbbiscan.cpp
4 //
5 //  Copyright (C) 2002-2012, International Business Machines Corporation and others.
6 //  All Rights Reserved.
7 //
8 //  This file contains the Rule Based Break Iterator Rule Builder functions for
9 //   scanning the rules and assembling a parse tree.  This is the first phase
10 //   of compiling the rules.
11 //
12 //  The overall of the rules is managed by class RBBIRuleBuilder, which will
13 //  create and use an instance of this class as part of the process.
14 //
15
16 #include "unicode/utypes.h"
17
18 #if !UCONFIG_NO_BREAK_ITERATION
19
20 #include "unicode/unistr.h"
21 #include "unicode/uniset.h"
22 #include "unicode/uchar.h"
23 #include "unicode/uchriter.h"
24 #include "unicode/parsepos.h"
25 #include "unicode/parseerr.h"
26 #include "cmemory.h"
27 #include "cstring.h"
28
29 #include "rbbirpt.h"   // Contains state table for the rbbi rules parser.
30                        //   generated by a Perl script.
31 #include "rbbirb.h"
32 #include "rbbinode.h"
33 #include "rbbiscan.h"
34 #include "rbbitblb.h"
35
36 #include "uassert.h"
37
38 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
39
40 //------------------------------------------------------------------------------
41 //
42 // Unicode Set init strings for each of the character classes needed for parsing a rule file.
43 //               (Initialized with hex values for portability to EBCDIC based machines.
44 //                Really ugly, but there's no good way to avoid it.)
45 //
46 //              The sets are referred to by name in the rbbirpt.txt, which is the
47 //              source form of the state transition table for the RBBI rule parser.
48 //
49 //------------------------------------------------------------------------------
50 static const UChar gRuleSet_rule_char_pattern[]       = {
51  //   [    ^      [    \     p     {      Z     }     \     u    0      0    2      0
52     0x5b, 0x5e, 0x5b, 0x5c, 0x70, 0x7b, 0x5a, 0x7d, 0x5c, 0x75, 0x30, 0x30, 0x32, 0x30,
53  //   -    \      u    0     0     7      f     ]     -     [    \      p
54     0x2d, 0x5c, 0x75, 0x30, 0x30, 0x37, 0x66, 0x5d, 0x2d, 0x5b, 0x5c, 0x70,
55  //   {     L     }    ]     -     [      \     p     {     N    }      ]     ]
56     0x7b, 0x4c, 0x7d, 0x5d, 0x2d, 0x5b, 0x5c, 0x70, 0x7b, 0x4e, 0x7d, 0x5d, 0x5d, 0};
57
58 static const UChar gRuleSet_name_char_pattern[]       = {
59 //    [    _      \    p     {     L      }     \     p     {    N      }     ]
60     0x5b, 0x5f, 0x5c, 0x70, 0x7b, 0x4c, 0x7d, 0x5c, 0x70, 0x7b, 0x4e, 0x7d, 0x5d, 0};
61
62 static const UChar gRuleSet_digit_char_pattern[] = {
63 //    [    0      -    9     ]
64     0x5b, 0x30, 0x2d, 0x39, 0x5d, 0};
65
66 static const UChar gRuleSet_name_start_char_pattern[] = {
67 //    [    _      \    p     {     L      }     ]
68     0x5b, 0x5f, 0x5c, 0x70, 0x7b, 0x4c, 0x7d, 0x5d, 0 };
69
70 static const UChar kAny[] = {0x61, 0x6e, 0x79, 0x00};  // "any"
71
72
73 U_CDECL_BEGIN
74 static void U_CALLCONV RBBISetTable_deleter(void *p) {
75     icu::RBBISetTableEl *px = (icu::RBBISetTableEl *)p;
76     delete px->key;
77     // Note:  px->val is owned by the linked list "fSetsListHead" in scanner.
78     //        Don't delete the value nodes here.
79     uprv_free(px);
80 }
81 U_CDECL_END
82
83 U_NAMESPACE_BEGIN
84
85 //------------------------------------------------------------------------------
86 //
87 //  Constructor.
88 //
89 //------------------------------------------------------------------------------
90 RBBIRuleScanner::RBBIRuleScanner(RBBIRuleBuilder *rb)
91 {
92     fRB                 = rb;
93     fStackPtr           = 0;
94     fStack[fStackPtr]   = 0;
95     fNodeStackPtr       = 0;
96     fRuleNum            = 0;
97     fNodeStack[0]       = NULL;
98
99     fSymbolTable                            = NULL;
100     fSetTable                               = NULL;
101
102     fScanIndex = 0;
103     fNextIndex = 0;
104
105     fReverseRule        = FALSE;
106     fLookAheadRule      = FALSE;
107
108     fLineNum    = 1;
109     fCharNum    = 0;
110     fQuoteMode  = FALSE;
111
112     // Do not check status until after all critical fields are sufficiently initialized
113     //   that the destructor can run cleanly.
114     if (U_FAILURE(*rb->fStatus)) {
115         return;
116     }
117
118     //
119     //  Set up the constant Unicode Sets.
120     //     Note:  These could be made static, lazily initialized, and shared among
121     //            all instances of RBBIRuleScanners.  BUT this is quite a bit simpler,
122     //            and the time to build these few sets should be small compared to a
123     //            full break iterator build.
124     fRuleSets[kRuleSet_rule_char-128]
125         = UnicodeSet(UnicodeString(gRuleSet_rule_char_pattern),       *rb->fStatus);
126     // fRuleSets[kRuleSet_white_space-128] = [:Pattern_White_Space:]
127     fRuleSets[kRuleSet_white_space-128].
128         add(9, 0xd).add(0x20).add(0x85).add(0x200e, 0x200f).add(0x2028, 0x2029);
129     fRuleSets[kRuleSet_name_char-128]
130         = UnicodeSet(UnicodeString(gRuleSet_name_char_pattern),       *rb->fStatus);
131     fRuleSets[kRuleSet_name_start_char-128]
132         = UnicodeSet(UnicodeString(gRuleSet_name_start_char_pattern), *rb->fStatus);
133     fRuleSets[kRuleSet_digit_char-128]
134         = UnicodeSet(UnicodeString(gRuleSet_digit_char_pattern),      *rb->fStatus);
135     if (*rb->fStatus == U_ILLEGAL_ARGUMENT_ERROR) {
136         // This case happens if ICU's data is missing.  UnicodeSet tries to look up property
137         //   names from the init string, can't find them, and claims an illegal argument.
138         //   Change the error so that the actual problem will be clearer to users.
139         *rb->fStatus = U_BRK_INIT_ERROR;
140     }
141     if (U_FAILURE(*rb->fStatus)) {
142         return;
143     }
144
145     fSymbolTable = new RBBISymbolTable(this, rb->fRules, *rb->fStatus);
146     if (fSymbolTable == NULL) {
147         *rb->fStatus = U_MEMORY_ALLOCATION_ERROR;
148         return;
149     }
150     fSetTable    = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, rb->fStatus);
151     if (U_FAILURE(*rb->fStatus)) {
152         return;
153     }
154     uhash_setValueDeleter(fSetTable, RBBISetTable_deleter);
155 }
156
157
158
159 //------------------------------------------------------------------------------
160 //
161 //  Destructor
162 //
163 //------------------------------------------------------------------------------
164 RBBIRuleScanner::~RBBIRuleScanner() {
165     delete fSymbolTable;
166     if (fSetTable != NULL) {
167          uhash_close(fSetTable);
168          fSetTable = NULL;
169
170     }
171
172
173     // Node Stack.
174     //   Normally has one entry, which is the entire parse tree for the rules.
175     //   If errors occured, there may be additional subtrees left on the stack.
176     while (fNodeStackPtr > 0) {
177         delete fNodeStack[fNodeStackPtr];
178         fNodeStackPtr--;
179     }
180
181 }
182
183 //------------------------------------------------------------------------------
184 //
185 //  doParseAction        Do some action during rule parsing.
186 //                       Called by the parse state machine.
187 //                       Actions build the parse tree and Unicode Sets,
188 //                       and maintain the parse stack for nested expressions.
189 //
190 //                       TODO:  unify EParseAction and RBBI_RuleParseAction enum types.
191 //                              They represent exactly the same thing.  They're separate
192 //                              only to work around enum forward declaration restrictions
193 //                              in some compilers, while at the same time avoiding multiple
194 //                              definitions problems.  I'm sure that there's a better way.
195 //
196 //------------------------------------------------------------------------------
197 UBool RBBIRuleScanner::doParseActions(int32_t action)
198 {
199     RBBINode *n       = NULL;
200
201     UBool   returnVal = TRUE;
202
203     switch (action) {
204
205     case doExprStart:
206         pushNewNode(RBBINode::opStart);
207         fRuleNum++;
208         break;
209
210
211     case doExprOrOperator:
212         {
213             fixOpStack(RBBINode::precOpCat);
214             RBBINode  *operandNode = fNodeStack[fNodeStackPtr--];
215             RBBINode  *orNode      = pushNewNode(RBBINode::opOr);
216             orNode->fLeftChild     = operandNode;
217             operandNode->fParent   = orNode;
218         }
219         break;
220
221     case doExprCatOperator:
222         // concatenation operator.
223         // For the implicit concatenation of adjacent terms in an expression that are
224         //   not separated by any other operator.  Action is invoked between the
225         //   actions for the two terms.
226         {
227             fixOpStack(RBBINode::precOpCat);
228             RBBINode  *operandNode = fNodeStack[fNodeStackPtr--];
229             RBBINode  *catNode     = pushNewNode(RBBINode::opCat);
230             catNode->fLeftChild    = operandNode;
231             operandNode->fParent   = catNode;
232         }
233         break;
234
235     case doLParen:
236         // Open Paren.
237         //   The openParen node is a dummy operation type with a low precedence,
238         //     which has the affect of ensuring that any real binary op that
239         //     follows within the parens binds more tightly to the operands than
240         //     stuff outside of the parens.
241         pushNewNode(RBBINode::opLParen);
242         break;
243
244     case doExprRParen:
245         fixOpStack(RBBINode::precLParen);
246         break;
247
248     case doNOP:
249         break;
250
251     case doStartAssign:
252         // We've just scanned "$variable = "
253         // The top of the node stack has the $variable ref node.
254
255         // Save the start position of the RHS text in the StartExpression node
256         //   that precedes the $variableReference node on the stack.
257         //   This will eventually be used when saving the full $variable replacement
258         //   text as a string.
259         n = fNodeStack[fNodeStackPtr-1];
260         n->fFirstPos = fNextIndex;              // move past the '='
261
262         // Push a new start-of-expression node; needed to keep parse of the
263         //   RHS expression happy.
264         pushNewNode(RBBINode::opStart);
265         break;
266
267
268
269
270     case doEndAssign:
271         {
272             // We have reached the end of an assignement statement.
273             //   Current scan char is the ';' that terminates the assignment.
274
275             // Terminate expression, leaves expression parse tree rooted in TOS node.
276             fixOpStack(RBBINode::precStart);
277
278             RBBINode *startExprNode  = fNodeStack[fNodeStackPtr-2];
279             RBBINode *varRefNode     = fNodeStack[fNodeStackPtr-1];
280             RBBINode *RHSExprNode    = fNodeStack[fNodeStackPtr];
281
282             // Save original text of right side of assignment, excluding the terminating ';'
283             //  in the root of the node for the right-hand-side expression.
284             RHSExprNode->fFirstPos = startExprNode->fFirstPos;
285             RHSExprNode->fLastPos  = fScanIndex;
286             fRB->fRules.extractBetween(RHSExprNode->fFirstPos, RHSExprNode->fLastPos, RHSExprNode->fText);
287
288             // Expression parse tree becomes l. child of the $variable reference node.
289             varRefNode->fLeftChild = RHSExprNode;
290             RHSExprNode->fParent   = varRefNode;
291
292             // Make a symbol table entry for the $variableRef node.
293             fSymbolTable->addEntry(varRefNode->fText, varRefNode, *fRB->fStatus);
294             if (U_FAILURE(*fRB->fStatus)) {
295                 // This is a round-about way to get the parse position set
296                 //  so that duplicate symbols error messages include a line number.
297                 UErrorCode t = *fRB->fStatus;
298                 *fRB->fStatus = U_ZERO_ERROR;
299                 error(t);
300             }
301
302             // Clean up the stack.
303             delete startExprNode;
304             fNodeStackPtr-=3;
305             break;
306         }
307
308     case doEndOfRule:
309         {
310         fixOpStack(RBBINode::precStart);      // Terminate expression, leaves expression
311         if (U_FAILURE(*fRB->fStatus)) {       //   parse tree rooted in TOS node.
312             break;
313         }
314 #ifdef RBBI_DEBUG
315         if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "rtree")) {printNodeStack("end of rule");}
316 #endif
317         U_ASSERT(fNodeStackPtr == 1);
318
319         // If this rule includes a look-ahead '/', add a endMark node to the
320         //   expression tree.
321         if (fLookAheadRule) {
322             RBBINode  *thisRule       = fNodeStack[fNodeStackPtr];
323             RBBINode  *endNode        = pushNewNode(RBBINode::endMark);
324             RBBINode  *catNode        = pushNewNode(RBBINode::opCat);
325             fNodeStackPtr -= 2;
326             catNode->fLeftChild       = thisRule;
327             catNode->fRightChild      = endNode;
328             fNodeStack[fNodeStackPtr] = catNode;
329             endNode->fVal             = fRuleNum;
330             endNode->fLookAheadEnd    = TRUE;
331         }
332
333         // All rule expressions are ORed together.
334         // The ';' that terminates an expression really just functions as a '|' with
335         //   a low operator prededence.
336         //
337         // Each of the four sets of rules are collected separately.
338         //  (forward, reverse, safe_forward, safe_reverse)
339         //  OR this rule into the appropriate group of them.
340         //
341         RBBINode **destRules = (fReverseRule? &fRB->fReverseTree : fRB->fDefaultTree);
342
343         if (*destRules != NULL) {
344             // This is not the first rule encounted.
345             // OR previous stuff  (from *destRules)
346             // with the current rule expression (on the Node Stack)
347             //  with the resulting OR expression going to *destRules
348             //
349             RBBINode  *thisRule    = fNodeStack[fNodeStackPtr];
350             RBBINode  *prevRules   = *destRules;
351             RBBINode  *orNode      = pushNewNode(RBBINode::opOr);
352             orNode->fLeftChild     = prevRules;
353             prevRules->fParent     = orNode;
354             orNode->fRightChild    = thisRule;
355             thisRule->fParent      = orNode;
356             *destRules             = orNode;
357         }
358         else
359         {
360             // This is the first rule encountered (for this direction).
361             // Just move its parse tree from the stack to *destRules.
362             *destRules = fNodeStack[fNodeStackPtr];
363         }
364         fReverseRule   = FALSE;   // in preparation for the next rule.
365         fLookAheadRule = FALSE;
366         fNodeStackPtr  = 0;
367         }
368         break;
369
370
371     case doRuleError:
372         error(U_BRK_RULE_SYNTAX);
373         returnVal = FALSE;
374         break;
375
376
377     case doVariableNameExpectedErr:
378         error(U_BRK_RULE_SYNTAX);
379         break;
380
381
382     //
383     //  Unary operands  + ? *
384     //    These all appear after the operand to which they apply.
385     //    When we hit one, the operand (may be a whole sub expression)
386     //    will be on the top of the stack.
387     //    Unary Operator becomes TOS, with the old TOS as its one child.
388     case doUnaryOpPlus:
389         {
390             RBBINode  *operandNode = fNodeStack[fNodeStackPtr--];
391             RBBINode  *plusNode    = pushNewNode(RBBINode::opPlus);
392             plusNode->fLeftChild   = operandNode;
393             operandNode->fParent   = plusNode;
394         }
395         break;
396
397     case doUnaryOpQuestion:
398         {
399             RBBINode  *operandNode = fNodeStack[fNodeStackPtr--];
400             RBBINode  *qNode       = pushNewNode(RBBINode::opQuestion);
401             qNode->fLeftChild      = operandNode;
402             operandNode->fParent   = qNode;
403         }
404         break;
405
406     case doUnaryOpStar:
407         {
408             RBBINode  *operandNode = fNodeStack[fNodeStackPtr--];
409             RBBINode  *starNode    = pushNewNode(RBBINode::opStar);
410             starNode->fLeftChild   = operandNode;
411             operandNode->fParent   = starNode;
412         }
413         break;
414
415     case doRuleChar:
416         // A "Rule Character" is any single character that is a literal part
417         // of the regular expression.  Like a, b and c in the expression "(abc*) | [:L:]"
418         // These are pretty uncommon in break rules; the terms are more commonly
419         //  sets.  To keep things uniform, treat these characters like as
420         // sets that just happen to contain only one character.
421         {
422             n = pushNewNode(RBBINode::setRef);
423             findSetFor(UnicodeString(fC.fChar), n);
424             n->fFirstPos = fScanIndex;
425             n->fLastPos  = fNextIndex;
426             fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText);
427             break;
428         }
429
430     case doDotAny:
431         // scanned a ".", meaning match any single character.
432         {
433             n = pushNewNode(RBBINode::setRef);
434             findSetFor(UnicodeString(TRUE, kAny, 3), n);
435             n->fFirstPos = fScanIndex;
436             n->fLastPos  = fNextIndex;
437             fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText);
438             break;
439         }
440
441     case doSlash:
442         // Scanned a '/', which identifies a look-ahead break position in a rule.
443         n = pushNewNode(RBBINode::lookAhead);
444         n->fVal      = fRuleNum;
445         n->fFirstPos = fScanIndex;
446         n->fLastPos  = fNextIndex;
447         fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText);
448         fLookAheadRule = TRUE;
449         break;
450
451
452     case doStartTagValue:
453         // Scanned a '{', the opening delimiter for a tag value within a rule.
454         n = pushNewNode(RBBINode::tag);
455         n->fVal      = 0;
456         n->fFirstPos = fScanIndex;
457         n->fLastPos  = fNextIndex;
458         break;
459
460     case doTagDigit:
461         // Just scanned a decimal digit that's part of a tag value
462         {
463             n = fNodeStack[fNodeStackPtr];
464             uint32_t v = u_charDigitValue(fC.fChar);
465             U_ASSERT(v < 10);
466             n->fVal = n->fVal*10 + v;
467             break;
468         }
469
470     case doTagValue:
471         n = fNodeStack[fNodeStackPtr];
472         n->fLastPos = fNextIndex;
473         fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText);
474         break;
475
476     case doTagExpectedError:
477         error(U_BRK_MALFORMED_RULE_TAG);
478         returnVal = FALSE;
479         break;
480
481     case doOptionStart:
482         // Scanning a !!option.   At the start of string.
483         fOptionStart = fScanIndex;
484         break;
485
486     case doOptionEnd:
487         {
488             UnicodeString opt(fRB->fRules, fOptionStart, fScanIndex-fOptionStart);
489             if (opt == UNICODE_STRING("chain", 5)) {
490                 fRB->fChainRules = TRUE;
491             } else if (opt == UNICODE_STRING("LBCMNoChain", 11)) {
492                 fRB->fLBCMNoChain = TRUE;
493             } else if (opt == UNICODE_STRING("forward", 7)) {
494                 fRB->fDefaultTree   = &fRB->fForwardTree;
495             } else if (opt == UNICODE_STRING("reverse", 7)) {
496                 fRB->fDefaultTree   = &fRB->fReverseTree;
497             } else if (opt == UNICODE_STRING("safe_forward", 12)) {
498                 fRB->fDefaultTree   = &fRB->fSafeFwdTree;
499             } else if (opt == UNICODE_STRING("safe_reverse", 12)) {
500                 fRB->fDefaultTree   = &fRB->fSafeRevTree;
501             } else if (opt == UNICODE_STRING("lookAheadHardBreak", 18)) {
502                 fRB->fLookAheadHardBreak = TRUE;
503             } else {
504                 error(U_BRK_UNRECOGNIZED_OPTION);
505             }
506         }
507         break;
508
509     case doReverseDir:
510         fReverseRule = TRUE;
511         break;
512
513     case doStartVariableName:
514         n = pushNewNode(RBBINode::varRef);
515         if (U_FAILURE(*fRB->fStatus)) {
516             break;
517         }
518         n->fFirstPos = fScanIndex;
519         break;
520
521     case doEndVariableName:
522         n = fNodeStack[fNodeStackPtr];
523         if (n==NULL || n->fType != RBBINode::varRef) {
524             error(U_BRK_INTERNAL_ERROR);
525             break;
526         }
527         n->fLastPos = fScanIndex;
528         fRB->fRules.extractBetween(n->fFirstPos+1, n->fLastPos, n->fText);
529         // Look the newly scanned name up in the symbol table
530         //   If there's an entry, set the l. child of the var ref to the replacement expression.
531         //   (We also pass through here when scanning assignments, but no harm is done, other
532         //    than a slight wasted effort that seems hard to avoid.  Lookup will be null)
533         n->fLeftChild = fSymbolTable->lookupNode(n->fText);
534         break;
535
536     case doCheckVarDef:
537         n = fNodeStack[fNodeStackPtr];
538         if (n->fLeftChild == NULL) {
539             error(U_BRK_UNDEFINED_VARIABLE);
540             returnVal = FALSE;
541         }
542         break;
543
544     case doExprFinished:
545         break;
546
547     case doRuleErrorAssignExpr:
548         error(U_BRK_ASSIGN_ERROR);
549         returnVal = FALSE;
550         break;
551
552     case doExit:
553         returnVal = FALSE;
554         break;
555
556     case doScanUnicodeSet:
557         scanSet();
558         break;
559
560     default:
561         error(U_BRK_INTERNAL_ERROR);
562         returnVal = FALSE;
563         break;
564     }
565     return returnVal;
566 }
567
568
569
570
571 //------------------------------------------------------------------------------
572 //
573 //  Error         Report a rule parse error.
574 //                Only report it if no previous error has been recorded.
575 //
576 //------------------------------------------------------------------------------
577 void RBBIRuleScanner::error(UErrorCode e) {
578     if (U_SUCCESS(*fRB->fStatus)) {
579         *fRB->fStatus = e;
580         if (fRB->fParseError) {
581             fRB->fParseError->line  = fLineNum;
582             fRB->fParseError->offset = fCharNum;
583             fRB->fParseError->preContext[0] = 0;
584             fRB->fParseError->preContext[0] = 0;
585         }
586     }
587 }
588
589
590
591
592 //------------------------------------------------------------------------------
593 //
594 //  fixOpStack   The parse stack holds partially assembled chunks of the parse tree.
595 //               An entry on the stack may be as small as a single setRef node,
596 //               or as large as the parse tree
597 //               for an entire expression (this will be the one item left on the stack
598 //               when the parsing of an RBBI rule completes.
599 //
600 //               This function is called when a binary operator is encountered.
601 //               It looks back up the stack for operators that are not yet associated
602 //               with a right operand, and if the precedence of the stacked operator >=
603 //               the precedence of the current operator, binds the operand left,
604 //               to the previously encountered operator.
605 //
606 //------------------------------------------------------------------------------
607 void RBBIRuleScanner::fixOpStack(RBBINode::OpPrecedence p) {
608     RBBINode *n;
609     // printNodeStack("entering fixOpStack()");
610     for (;;) {
611         n = fNodeStack[fNodeStackPtr-1];   // an operator node
612         if (n->fPrecedence == 0) {
613             RBBIDebugPuts("RBBIRuleScanner::fixOpStack, bad operator node");
614             error(U_BRK_INTERNAL_ERROR);
615             return;
616         }
617
618         if (n->fPrecedence < p || n->fPrecedence <= RBBINode::precLParen) {
619             // The most recent operand goes with the current operator,
620             //   not with the previously stacked one.
621             break;
622         }
623             // Stack operator is a binary op  ( '|' or concatenation)
624             //   TOS operand becomes right child of this operator.
625             //   Resulting subexpression becomes the TOS operand.
626             n->fRightChild = fNodeStack[fNodeStackPtr];
627             fNodeStack[fNodeStackPtr]->fParent = n;
628             fNodeStackPtr--;
629         // printNodeStack("looping in fixOpStack()   ");
630     }
631
632     if (p <= RBBINode::precLParen) {
633         // Scan is at a right paren or end of expression.
634         //  The scanned item must match the stack, or else there was an error.
635         //  Discard the left paren (or start expr) node from the stack,
636             //  leaving the completed (sub)expression as TOS.
637             if (n->fPrecedence != p) {
638                 // Right paren encountered matched start of expression node, or
639                 // end of expression matched with a left paren node.
640                 error(U_BRK_MISMATCHED_PAREN);
641             }
642             fNodeStack[fNodeStackPtr-1] = fNodeStack[fNodeStackPtr];
643             fNodeStackPtr--;
644             // Delete the now-discarded LParen or Start node.
645             delete n;
646     }
647     // printNodeStack("leaving fixOpStack()");
648 }
649
650
651
652
653 //------------------------------------------------------------------------------
654 //
655 //   findSetFor    given a UnicodeString,
656 //                  - find the corresponding Unicode Set  (uset node)
657 //                         (create one if necessary)
658 //                  - Set fLeftChild of the caller's node (should be a setRef node)
659 //                         to the uset node
660 //                 Maintain a hash table of uset nodes, so the same one is always used
661 //                    for the same string.
662 //                 If a "to adopt" set is provided and we haven't seen this key before,
663 //                    add the provided set to the hash table.
664 //                 If the string is one (32 bit) char in length, the set contains
665 //                    just one element which is the char in question.
666 //                 If the string is "any", return a set containing all chars.
667 //
668 //------------------------------------------------------------------------------
669 void RBBIRuleScanner::findSetFor(const UnicodeString &s, RBBINode *node, UnicodeSet *setToAdopt) {
670
671     RBBISetTableEl   *el;
672
673     // First check whether we've already cached a set for this string.
674     // If so, just use the cached set in the new node.
675     //   delete any set provided by the caller, since we own it.
676     el = (RBBISetTableEl *)uhash_get(fSetTable, &s);
677     if (el != NULL) {
678         delete setToAdopt;
679         node->fLeftChild = el->val;
680         U_ASSERT(node->fLeftChild->fType == RBBINode::uset);
681         return;
682     }
683
684     // Haven't seen this set before.
685     // If the caller didn't provide us with a prebuilt set,
686     //   create a new UnicodeSet now.
687     if (setToAdopt == NULL) {
688         if (s.compare(kAny, -1) == 0) {
689             setToAdopt = new UnicodeSet(0x000000, 0x10ffff);
690         } else {
691             UChar32 c;
692             c = s.char32At(0);
693             setToAdopt = new UnicodeSet(c, c);
694         }
695     }
696
697     //
698     // Make a new uset node to refer to this UnicodeSet
699     // This new uset node becomes the child of the caller's setReference node.
700     //
701     RBBINode *usetNode    = new RBBINode(RBBINode::uset);
702     if (usetNode == NULL) {
703         error(U_MEMORY_ALLOCATION_ERROR);
704         return;
705     }
706     usetNode->fInputSet   = setToAdopt;
707     usetNode->fParent     = node;
708     node->fLeftChild      = usetNode;
709     usetNode->fText = s;
710
711
712     //
713     // Add the new uset node to the list of all uset nodes.
714     //
715     fRB->fUSetNodes->addElement(usetNode, *fRB->fStatus);
716
717
718     //
719     // Add the new set to the set hash table.
720     //
721     el      = (RBBISetTableEl *)uprv_malloc(sizeof(RBBISetTableEl));
722     UnicodeString *tkey = new UnicodeString(s);
723     if (tkey == NULL || el == NULL || setToAdopt == NULL) {
724         // Delete to avoid memory leak
725         delete tkey;
726         tkey = NULL;
727         uprv_free(el);
728         el = NULL;
729         delete setToAdopt;
730         setToAdopt = NULL;
731
732         error(U_MEMORY_ALLOCATION_ERROR);
733         return;
734     }
735     el->key = tkey;
736     el->val = usetNode;
737     uhash_put(fSetTable, el->key, el, fRB->fStatus);
738
739     return;
740 }
741
742
743
744 //
745 //  Assorted Unicode character constants.
746 //     Numeric because there is no portable way to enter them as literals.
747 //     (Think EBCDIC).
748 //
749 static const UChar      chCR        = 0x0d;      // New lines, for terminating comments.
750 static const UChar      chLF        = 0x0a;
751 static const UChar      chNEL       = 0x85;      //    NEL newline variant
752 static const UChar      chLS        = 0x2028;    //    Unicode Line Separator
753 static const UChar      chApos      = 0x27;      //  single quote, for quoted chars.
754 static const UChar      chPound     = 0x23;      // '#', introduces a comment.
755 static const UChar      chBackSlash = 0x5c;      // '\'  introduces a char escape
756 static const UChar      chLParen    = 0x28;
757 static const UChar      chRParen    = 0x29;
758
759
760 //------------------------------------------------------------------------------
761 //
762 //  stripRules    Return a rules string without unnecessary
763 //                characters.
764 //
765 //------------------------------------------------------------------------------
766 UnicodeString RBBIRuleScanner::stripRules(const UnicodeString &rules) {
767     UnicodeString strippedRules;
768     int rulesLength = rules.length();
769     for (int idx = 0; idx < rulesLength; ) {
770         UChar ch = rules[idx++];
771         if (ch == chPound) {
772             while (idx < rulesLength
773                 && ch != chCR && ch != chLF && ch != chNEL)
774             {
775                 ch = rules[idx++];
776             }
777         }
778         if (!u_isISOControl(ch)) {
779             strippedRules.append(ch);
780         }
781     }
782     // strippedRules = strippedRules.unescape();
783     return strippedRules;
784 }
785
786
787 //------------------------------------------------------------------------------
788 //
789 //  nextCharLL    Low Level Next Char from rule input source.
790 //                Get a char from the input character iterator,
791 //                keep track of input position for error reporting.
792 //
793 //------------------------------------------------------------------------------
794 UChar32  RBBIRuleScanner::nextCharLL() {
795     UChar32  ch;
796
797     if (fNextIndex >= fRB->fRules.length()) {
798         return (UChar32)-1;
799     }
800     ch         = fRB->fRules.char32At(fNextIndex);
801     fNextIndex = fRB->fRules.moveIndex32(fNextIndex, 1);
802
803     if (ch == chCR ||
804         ch == chNEL ||
805         ch == chLS   ||
806         (ch == chLF && fLastChar != chCR)) {
807         // Character is starting a new line.  Bump up the line number, and
808         //  reset the column to 0.
809         fLineNum++;
810         fCharNum=0;
811         if (fQuoteMode) {
812             error(U_BRK_NEW_LINE_IN_QUOTED_STRING);
813             fQuoteMode = FALSE;
814         }
815     }
816     else {
817         // Character is not starting a new line.  Except in the case of a
818         //   LF following a CR, increment the column position.
819         if (ch != chLF) {
820             fCharNum++;
821         }
822     }
823     fLastChar = ch;
824     return ch;
825 }
826
827
828 //------------------------------------------------------------------------------
829 //
830 //   nextChar     for rules scanning.  At this level, we handle stripping
831 //                out comments and processing backslash character escapes.
832 //                The rest of the rules grammar is handled at the next level up.
833 //
834 //------------------------------------------------------------------------------
835 void RBBIRuleScanner::nextChar(RBBIRuleChar &c) {
836
837     // Unicode Character constants needed for the processing done by nextChar(),
838     //   in hex because literals wont work on EBCDIC machines.
839
840     fScanIndex = fNextIndex;
841     c.fChar    = nextCharLL();
842     c.fEscaped = FALSE;
843
844     //
845     //  check for '' sequence.
846     //  These are recognized in all contexts, whether in quoted text or not.
847     //
848     if (c.fChar == chApos) {
849         if (fRB->fRules.char32At(fNextIndex) == chApos) {
850             c.fChar    = nextCharLL();        // get nextChar officially so character counts
851             c.fEscaped = TRUE;                //   stay correct.
852         }
853         else
854         {
855             // Single quote, by itself.
856             //   Toggle quoting mode.
857             //   Return either '('  or ')', because quotes cause a grouping of the quoted text.
858             fQuoteMode = !fQuoteMode;
859             if (fQuoteMode == TRUE) {
860                 c.fChar = chLParen;
861             } else {
862                 c.fChar = chRParen;
863             }
864             c.fEscaped = FALSE;      // The paren that we return is not escaped.
865             return;
866         }
867     }
868
869     if (fQuoteMode) {
870         c.fEscaped = TRUE;
871     }
872     else
873     {
874         // We are not in a 'quoted region' of the source.
875         //
876         if (c.fChar == chPound) {
877             // Start of a comment.  Consume the rest of it.
878             //  The new-line char that terminates the comment is always returned.
879             //  It will be treated as white-space, and serves to break up anything
880             //    that might otherwise incorrectly clump together with a comment in
881             //    the middle (a variable name, for example.)
882             for (;;) {
883                 c.fChar = nextCharLL();
884                 if (c.fChar == (UChar32)-1 ||  // EOF
885                     c.fChar == chCR     ||
886                     c.fChar == chLF     ||
887                     c.fChar == chNEL    ||
888                     c.fChar == chLS)       {break;}
889             }
890         }
891         if (c.fChar == (UChar32)-1) {
892             return;
893         }
894
895         //
896         //  check for backslash escaped characters.
897         //  Use UnicodeString::unescapeAt() to handle them.
898         //
899         if (c.fChar == chBackSlash) {
900             c.fEscaped = TRUE;
901             int32_t startX = fNextIndex;
902             c.fChar = fRB->fRules.unescapeAt(fNextIndex);
903             if (fNextIndex == startX) {
904                 error(U_BRK_HEX_DIGITS_EXPECTED);
905             }
906             fCharNum += fNextIndex-startX;
907         }
908     }
909     // putc(c.fChar, stdout);
910 }
911
912 //------------------------------------------------------------------------------
913 //
914 //  Parse RBBI rules.   The state machine for rules parsing is here.
915 //                      The state tables are hand-written in the file rbbirpt.txt,
916 //                      and converted to the form used here by a perl
917 //                      script rbbicst.pl
918 //
919 //------------------------------------------------------------------------------
920 void RBBIRuleScanner::parse() {
921     uint16_t                state;
922     const RBBIRuleTableEl  *tableEl;
923
924     if (U_FAILURE(*fRB->fStatus)) {
925         return;
926     }
927
928     state = 1;
929     nextChar(fC);
930     //
931     // Main loop for the rule parsing state machine.
932     //   Runs once per state transition.
933     //   Each time through optionally performs, depending on the state table,
934     //      - an advance to the the next input char
935     //      - an action to be performed.
936     //      - pushing or popping a state to/from the local state return stack.
937     //
938     for (;;) {
939         //  Bail out if anything has gone wrong.
940         //  RBBI rule file parsing stops on the first error encountered.
941         if (U_FAILURE(*fRB->fStatus)) {
942             break;
943         }
944
945         // Quit if state == 0.  This is the normal way to exit the state machine.
946         //
947         if (state == 0) {
948             break;
949         }
950
951         // Find the state table element that matches the input char from the rule, or the
952         //    class of the input character.  Start with the first table row for this
953         //    state, then linearly scan forward until we find a row that matches the
954         //    character.  The last row for each state always matches all characters, so
955         //    the search will stop there, if not before.
956         //
957         tableEl = &gRuleParseStateTable[state];
958         #ifdef RBBI_DEBUG
959             if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "scan")) {
960                 RBBIDebugPrintf("char, line, col = (\'%c\', %d, %d)    state=%s ",
961                     fC.fChar, fLineNum, fCharNum, RBBIRuleStateNames[state]);
962             }
963         #endif
964
965         for (;;) {
966             #ifdef RBBI_DEBUG
967                 if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "scan")) { RBBIDebugPrintf(".");}
968             #endif
969             if (tableEl->fCharClass < 127 && fC.fEscaped == FALSE &&   tableEl->fCharClass == fC.fChar) {
970                 // Table row specified an individual character, not a set, and
971                 //   the input character is not escaped, and
972                 //   the input character matched it.
973                 break;
974             }
975             if (tableEl->fCharClass == 255) {
976                 // Table row specified default, match anything character class.
977                 break;
978             }
979             if (tableEl->fCharClass == 254 && fC.fEscaped)  {
980                 // Table row specified "escaped" and the char was escaped.
981                 break;
982             }
983             if (tableEl->fCharClass == 253 && fC.fEscaped &&
984                 (fC.fChar == 0x50 || fC.fChar == 0x70 ))  {
985                 // Table row specified "escaped P" and the char is either 'p' or 'P'.
986                 break;
987             }
988             if (tableEl->fCharClass == 252 && fC.fChar == (UChar32)-1)  {
989                 // Table row specified eof and we hit eof on the input.
990                 break;
991             }
992
993             if (tableEl->fCharClass >= 128 && tableEl->fCharClass < 240 &&   // Table specs a char class &&
994                 fC.fEscaped == FALSE &&                                      //   char is not escaped &&
995                 fC.fChar != (UChar32)-1) {                                   //   char is not EOF
996                 U_ASSERT((tableEl->fCharClass-128) < LENGTHOF(fRuleSets));
997                 if (fRuleSets[tableEl->fCharClass-128].contains(fC.fChar)) {
998                     // Table row specified a character class, or set of characters,
999                     //   and the current char matches it.
1000                     break;
1001                 }
1002             }
1003
1004             // No match on this row, advance to the next  row for this state,
1005             tableEl++;
1006         }
1007         if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "scan")) { RBBIDebugPuts("");}
1008
1009         //
1010         // We've found the row of the state table that matches the current input
1011         //   character from the rules string.
1012         // Perform any action specified  by this row in the state table.
1013         if (doParseActions((int32_t)tableEl->fAction) == FALSE) {
1014             // Break out of the state machine loop if the
1015             //   the action signalled some kind of error, or
1016             //   the action was to exit, occurs on normal end-of-rules-input.
1017             break;
1018         }
1019
1020         if (tableEl->fPushState != 0) {
1021             fStackPtr++;
1022             if (fStackPtr >= kStackSize) {
1023                 error(U_BRK_INTERNAL_ERROR);
1024                 RBBIDebugPuts("RBBIRuleScanner::parse() - state stack overflow.");
1025                 fStackPtr--;
1026             }
1027             fStack[fStackPtr] = tableEl->fPushState;
1028         }
1029
1030         if (tableEl->fNextChar) {
1031             nextChar(fC);
1032         }
1033
1034         // Get the next state from the table entry, or from the
1035         //   state stack if the next state was specified as "pop".
1036         if (tableEl->fNextState != 255) {
1037             state = tableEl->fNextState;
1038         } else {
1039             state = fStack[fStackPtr];
1040             fStackPtr--;
1041             if (fStackPtr < 0) {
1042                 error(U_BRK_INTERNAL_ERROR);
1043                 RBBIDebugPuts("RBBIRuleScanner::parse() - state stack underflow.");
1044                 fStackPtr++;
1045             }
1046         }
1047
1048     }
1049
1050     //
1051     // If there were NO user specified reverse rules, set up the equivalent of ".*;"
1052     //
1053     if (fRB->fReverseTree == NULL) {
1054         fRB->fReverseTree  = pushNewNode(RBBINode::opStar);
1055         RBBINode  *operand = pushNewNode(RBBINode::setRef);
1056         findSetFor(UnicodeString(TRUE, kAny, 3), operand);
1057         fRB->fReverseTree->fLeftChild = operand;
1058         operand->fParent              = fRB->fReverseTree;
1059         fNodeStackPtr -= 2;
1060     }
1061
1062
1063     //
1064     // Parsing of the input RBBI rules is complete.
1065     // We now have a parse tree for the rule expressions
1066     // and a list of all UnicodeSets that are referenced.
1067     //
1068 #ifdef RBBI_DEBUG
1069     if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "symbols")) {fSymbolTable->rbbiSymtablePrint();}
1070     if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "ptree"))
1071     {
1072         RBBIDebugPrintf("Completed Forward Rules Parse Tree...\n");
1073         fRB->fForwardTree->printTree(TRUE);
1074         RBBIDebugPrintf("\nCompleted Reverse Rules Parse Tree...\n");
1075         fRB->fReverseTree->printTree(TRUE);
1076         RBBIDebugPrintf("\nCompleted Safe Point Forward Rules Parse Tree...\n");
1077         fRB->fSafeFwdTree->printTree(TRUE);
1078         RBBIDebugPrintf("\nCompleted Safe Point Reverse Rules Parse Tree...\n");
1079         fRB->fSafeRevTree->printTree(TRUE);
1080     }
1081 #endif
1082 }
1083
1084
1085 //------------------------------------------------------------------------------
1086 //
1087 //  printNodeStack     for debugging...
1088 //
1089 //------------------------------------------------------------------------------
1090 #ifdef RBBI_DEBUG
1091 void RBBIRuleScanner::printNodeStack(const char *title) {
1092     int i;
1093     RBBIDebugPrintf("%s.  Dumping node stack...\n", title);
1094     for (i=fNodeStackPtr; i>0; i--) {fNodeStack[i]->printTree(TRUE);}
1095 }
1096 #endif
1097
1098
1099
1100
1101 //------------------------------------------------------------------------------
1102 //
1103 //  pushNewNode   create a new RBBINode of the specified type and push it
1104 //                onto the stack of nodes.
1105 //
1106 //------------------------------------------------------------------------------
1107 RBBINode  *RBBIRuleScanner::pushNewNode(RBBINode::NodeType  t) {
1108     fNodeStackPtr++;
1109     if (fNodeStackPtr >= kStackSize) {
1110         error(U_BRK_INTERNAL_ERROR);
1111         RBBIDebugPuts("RBBIRuleScanner::pushNewNode - stack overflow.");
1112         *fRB->fStatus = U_BRK_INTERNAL_ERROR;
1113         return NULL;
1114     }
1115     fNodeStack[fNodeStackPtr] = new RBBINode(t);
1116     if (fNodeStack[fNodeStackPtr] == NULL) {
1117         *fRB->fStatus = U_MEMORY_ALLOCATION_ERROR;
1118     }
1119     return fNodeStack[fNodeStackPtr];
1120 }
1121
1122
1123
1124 //------------------------------------------------------------------------------
1125 //
1126 //  scanSet    Construct a UnicodeSet from the text at the current scan
1127 //             position.  Advance the scan position to the first character
1128 //             after the set.
1129 //
1130 //             A new RBBI setref node referring to the set is pushed onto the node
1131 //             stack.
1132 //
1133 //             The scan position is normally under the control of the state machine
1134 //             that controls rule parsing.  UnicodeSets, however, are parsed by
1135 //             the UnicodeSet constructor, not by the RBBI rule parser.
1136 //
1137 //------------------------------------------------------------------------------
1138 void RBBIRuleScanner::scanSet() {
1139     UnicodeSet    *uset;
1140     ParsePosition  pos;
1141     int            startPos;
1142     int            i;
1143
1144     if (U_FAILURE(*fRB->fStatus)) {
1145         return;
1146     }
1147
1148     pos.setIndex(fScanIndex);
1149     startPos = fScanIndex;
1150     UErrorCode localStatus = U_ZERO_ERROR;
1151     uset = new UnicodeSet();
1152     if (uset == NULL) {
1153         localStatus = U_MEMORY_ALLOCATION_ERROR;
1154     } else {
1155         uset->applyPatternIgnoreSpace(fRB->fRules, pos, fSymbolTable, localStatus);
1156     }
1157     if (U_FAILURE(localStatus)) {
1158         //  TODO:  Get more accurate position of the error from UnicodeSet's return info.
1159         //         UnicodeSet appears to not be reporting correctly at this time.
1160         #ifdef RBBI_DEBUG
1161             RBBIDebugPrintf("UnicodeSet parse postion.ErrorIndex = %d\n", pos.getIndex());
1162         #endif
1163         error(localStatus);
1164         delete uset;
1165         return;
1166     }
1167
1168     // Verify that the set contains at least one code point.
1169     //
1170     U_ASSERT(uset!=NULL);
1171     if (uset->isEmpty()) {
1172         // This set is empty.
1173         //  Make it an error, because it almost certainly is not what the user wanted.
1174         //  Also, avoids having to think about corner cases in the tree manipulation code
1175         //   that occurs later on.
1176         error(U_BRK_RULE_EMPTY_SET);
1177         delete uset;
1178         return;
1179     }
1180
1181
1182     // Advance the RBBI parse postion over the UnicodeSet pattern.
1183     //   Don't just set fScanIndex because the line/char positions maintained
1184     //   for error reporting would be thrown off.
1185     i = pos.getIndex();
1186     for (;;) {
1187         if (fNextIndex >= i) {
1188             break;
1189         }
1190         nextCharLL();
1191     }
1192
1193     if (U_SUCCESS(*fRB->fStatus)) {
1194         RBBINode         *n;
1195
1196         n = pushNewNode(RBBINode::setRef);
1197         n->fFirstPos = startPos;
1198         n->fLastPos  = fNextIndex;
1199         fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText);
1200         //  findSetFor() serves several purposes here:
1201         //     - Adopts storage for the UnicodeSet, will be responsible for deleting.
1202         //     - Mantains collection of all sets in use, needed later for establishing
1203         //          character categories for run time engine.
1204         //     - Eliminates mulitiple instances of the same set.
1205         //     - Creates a new uset node if necessary (if this isn't a duplicate.)
1206         findSetFor(n->fText, n, uset);
1207     }
1208
1209 }
1210
1211 U_NAMESPACE_END
1212
1213 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */