rbbitblb.cpp 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. **********************************************************************
  5. * Copyright (c) 2002-2016, International Business Machines
  6. * Corporation and others. All Rights Reserved.
  7. **********************************************************************
  8. */
  9. //
  10. // rbbitblb.cpp
  11. //
  12. #include "unicode/utypes.h"
  13. #if !UCONFIG_NO_BREAK_ITERATION
  14. #include "unicode/unistr.h"
  15. #include "rbbitblb.h"
  16. #include "rbbirb.h"
  17. #include "rbbiscan.h"
  18. #include "rbbisetb.h"
  19. #include "rbbidata.h"
  20. #include "cstring.h"
  21. #include "uassert.h"
  22. #include "uvectr32.h"
  23. #include "cmemory.h"
  24. U_NAMESPACE_BEGIN
  25. const int32_t kMaxStateFor8BitsTable = 255;
  26. RBBITableBuilder::RBBITableBuilder(RBBIRuleBuilder *rb, RBBINode **rootNode, UErrorCode &status) :
  27. fRB(rb),
  28. fTree(*rootNode),
  29. fStatus(&status),
  30. fDStates(nullptr),
  31. fSafeTable(nullptr) {
  32. if (U_FAILURE(status)) {
  33. return;
  34. }
  35. // fDStates is UVector<RBBIStateDescriptor *>
  36. fDStates = new UVector(status);
  37. if (U_SUCCESS(status) && fDStates == nullptr ) {
  38. status = U_MEMORY_ALLOCATION_ERROR;
  39. }
  40. }
  41. RBBITableBuilder::~RBBITableBuilder() {
  42. int i;
  43. for (i=0; i<fDStates->size(); i++) {
  44. delete (RBBIStateDescriptor *)fDStates->elementAt(i);
  45. }
  46. delete fDStates;
  47. delete fSafeTable;
  48. delete fLookAheadRuleMap;
  49. }
  50. //-----------------------------------------------------------------------------
  51. //
  52. // RBBITableBuilder::buildForwardTable - This is the main function for building
  53. // the DFA state transition table from the RBBI rules parse tree.
  54. //
  55. //-----------------------------------------------------------------------------
  56. void RBBITableBuilder::buildForwardTable() {
  57. if (U_FAILURE(*fStatus)) {
  58. return;
  59. }
  60. // If there were no rules, just return. This situation can easily arise
  61. // for the reverse rules.
  62. if (fTree==nullptr) {
  63. return;
  64. }
  65. //
  66. // Walk through the tree, replacing any references to $variables with a copy of the
  67. // parse tree for the substitution expression.
  68. //
  69. fTree = fTree->flattenVariables();
  70. #ifdef RBBI_DEBUG
  71. if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "ftree")) {
  72. RBBIDebugPuts("\nParse tree after flattening variable references.");
  73. RBBINode::printTree(fTree, true);
  74. }
  75. #endif
  76. //
  77. // If the rules contained any references to {bof}
  78. // add a {bof} <cat> <former root of tree> to the
  79. // tree. Means that all matches must start out with the
  80. // {bof} fake character.
  81. //
  82. if (fRB->fSetBuilder->sawBOF()) {
  83. RBBINode *bofTop = new RBBINode(RBBINode::opCat);
  84. RBBINode *bofLeaf = new RBBINode(RBBINode::leafChar);
  85. // Delete and exit if memory allocation failed.
  86. if (bofTop == nullptr || bofLeaf == nullptr) {
  87. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  88. delete bofTop;
  89. delete bofLeaf;
  90. return;
  91. }
  92. bofTop->fLeftChild = bofLeaf;
  93. bofTop->fRightChild = fTree;
  94. bofLeaf->fParent = bofTop;
  95. bofLeaf->fVal = 2; // Reserved value for {bof}.
  96. fTree = bofTop;
  97. }
  98. //
  99. // Add a unique right-end marker to the expression.
  100. // Appears as a cat-node, left child being the original tree,
  101. // right child being the end marker.
  102. //
  103. RBBINode *cn = new RBBINode(RBBINode::opCat);
  104. // Exit if memory allocation failed.
  105. if (cn == nullptr) {
  106. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  107. return;
  108. }
  109. cn->fLeftChild = fTree;
  110. fTree->fParent = cn;
  111. RBBINode *endMarkerNode = cn->fRightChild = new RBBINode(RBBINode::endMark);
  112. // Delete and exit if memory allocation failed.
  113. if (cn->fRightChild == nullptr) {
  114. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  115. delete cn;
  116. return;
  117. }
  118. cn->fRightChild->fParent = cn;
  119. fTree = cn;
  120. //
  121. // Replace all references to UnicodeSets with the tree for the equivalent
  122. // expression.
  123. //
  124. fTree->flattenSets();
  125. #ifdef RBBI_DEBUG
  126. if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "stree")) {
  127. RBBIDebugPuts("\nParse tree after flattening Unicode Set references.");
  128. RBBINode::printTree(fTree, true);
  129. }
  130. #endif
  131. //
  132. // calculate the functions nullable, firstpos, lastpos and followpos on
  133. // nodes in the parse tree.
  134. // See the algorithm description in Aho.
  135. // Understanding how this works by looking at the code alone will be
  136. // nearly impossible.
  137. //
  138. calcNullable(fTree);
  139. calcFirstPos(fTree);
  140. calcLastPos(fTree);
  141. calcFollowPos(fTree);
  142. if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "pos")) {
  143. RBBIDebugPuts("\n");
  144. printPosSets(fTree);
  145. }
  146. //
  147. // For "chained" rules, modify the followPos sets
  148. //
  149. if (fRB->fChainRules) {
  150. calcChainedFollowPos(fTree, endMarkerNode);
  151. }
  152. //
  153. // BOF (start of input) test fixup.
  154. //
  155. if (fRB->fSetBuilder->sawBOF()) {
  156. bofFixup();
  157. }
  158. //
  159. // Build the DFA state transition tables.
  160. //
  161. buildStateTable();
  162. mapLookAheadRules();
  163. flagAcceptingStates();
  164. flagLookAheadStates();
  165. flagTaggedStates();
  166. //
  167. // Update the global table of rule status {tag} values
  168. // The rule builder has a global vector of status values that are common
  169. // for all tables. Merge the ones from this table into the global set.
  170. //
  171. mergeRuleStatusVals();
  172. }
  173. //-----------------------------------------------------------------------------
  174. //
  175. // calcNullable. Impossible to explain succinctly. See Aho, section 3.9
  176. //
  177. //-----------------------------------------------------------------------------
  178. void RBBITableBuilder::calcNullable(RBBINode *n) {
  179. if (n == nullptr) {
  180. return;
  181. }
  182. if (n->fType == RBBINode::setRef ||
  183. n->fType == RBBINode::endMark ) {
  184. // These are non-empty leaf node types.
  185. n->fNullable = false;
  186. return;
  187. }
  188. if (n->fType == RBBINode::lookAhead || n->fType == RBBINode::tag) {
  189. // Lookahead marker node. It's a leaf, so no recursion on children.
  190. // It's nullable because it does not match any literal text from the input stream.
  191. n->fNullable = true;
  192. return;
  193. }
  194. // The node is not a leaf.
  195. // Calculate nullable on its children.
  196. calcNullable(n->fLeftChild);
  197. calcNullable(n->fRightChild);
  198. // Apply functions from table 3.40 in Aho
  199. if (n->fType == RBBINode::opOr) {
  200. n->fNullable = n->fLeftChild->fNullable || n->fRightChild->fNullable;
  201. }
  202. else if (n->fType == RBBINode::opCat) {
  203. n->fNullable = n->fLeftChild->fNullable && n->fRightChild->fNullable;
  204. }
  205. else if (n->fType == RBBINode::opStar || n->fType == RBBINode::opQuestion) {
  206. n->fNullable = true;
  207. }
  208. else {
  209. n->fNullable = false;
  210. }
  211. }
  212. //-----------------------------------------------------------------------------
  213. //
  214. // calcFirstPos. Impossible to explain succinctly. See Aho, section 3.9
  215. //
  216. //-----------------------------------------------------------------------------
  217. void RBBITableBuilder::calcFirstPos(RBBINode *n) {
  218. if (n == nullptr) {
  219. return;
  220. }
  221. if (n->fType == RBBINode::leafChar ||
  222. n->fType == RBBINode::endMark ||
  223. n->fType == RBBINode::lookAhead ||
  224. n->fType == RBBINode::tag) {
  225. // These are non-empty leaf node types.
  226. // Note: In order to maintain the sort invariant on the set,
  227. // this function should only be called on a node whose set is
  228. // empty to start with.
  229. n->fFirstPosSet->addElement(n, *fStatus);
  230. return;
  231. }
  232. // The node is not a leaf.
  233. // Calculate firstPos on its children.
  234. calcFirstPos(n->fLeftChild);
  235. calcFirstPos(n->fRightChild);
  236. // Apply functions from table 3.40 in Aho
  237. if (n->fType == RBBINode::opOr) {
  238. setAdd(n->fFirstPosSet, n->fLeftChild->fFirstPosSet);
  239. setAdd(n->fFirstPosSet, n->fRightChild->fFirstPosSet);
  240. }
  241. else if (n->fType == RBBINode::opCat) {
  242. setAdd(n->fFirstPosSet, n->fLeftChild->fFirstPosSet);
  243. if (n->fLeftChild->fNullable) {
  244. setAdd(n->fFirstPosSet, n->fRightChild->fFirstPosSet);
  245. }
  246. }
  247. else if (n->fType == RBBINode::opStar ||
  248. n->fType == RBBINode::opQuestion ||
  249. n->fType == RBBINode::opPlus) {
  250. setAdd(n->fFirstPosSet, n->fLeftChild->fFirstPosSet);
  251. }
  252. }
  253. //-----------------------------------------------------------------------------
  254. //
  255. // calcLastPos. Impossible to explain succinctly. See Aho, section 3.9
  256. //
  257. //-----------------------------------------------------------------------------
  258. void RBBITableBuilder::calcLastPos(RBBINode *n) {
  259. if (n == nullptr) {
  260. return;
  261. }
  262. if (n->fType == RBBINode::leafChar ||
  263. n->fType == RBBINode::endMark ||
  264. n->fType == RBBINode::lookAhead ||
  265. n->fType == RBBINode::tag) {
  266. // These are non-empty leaf node types.
  267. // Note: In order to maintain the sort invariant on the set,
  268. // this function should only be called on a node whose set is
  269. // empty to start with.
  270. n->fLastPosSet->addElement(n, *fStatus);
  271. return;
  272. }
  273. // The node is not a leaf.
  274. // Calculate lastPos on its children.
  275. calcLastPos(n->fLeftChild);
  276. calcLastPos(n->fRightChild);
  277. // Apply functions from table 3.40 in Aho
  278. if (n->fType == RBBINode::opOr) {
  279. setAdd(n->fLastPosSet, n->fLeftChild->fLastPosSet);
  280. setAdd(n->fLastPosSet, n->fRightChild->fLastPosSet);
  281. }
  282. else if (n->fType == RBBINode::opCat) {
  283. setAdd(n->fLastPosSet, n->fRightChild->fLastPosSet);
  284. if (n->fRightChild->fNullable) {
  285. setAdd(n->fLastPosSet, n->fLeftChild->fLastPosSet);
  286. }
  287. }
  288. else if (n->fType == RBBINode::opStar ||
  289. n->fType == RBBINode::opQuestion ||
  290. n->fType == RBBINode::opPlus) {
  291. setAdd(n->fLastPosSet, n->fLeftChild->fLastPosSet);
  292. }
  293. }
  294. //-----------------------------------------------------------------------------
  295. //
  296. // calcFollowPos. Impossible to explain succinctly. See Aho, section 3.9
  297. //
  298. //-----------------------------------------------------------------------------
  299. void RBBITableBuilder::calcFollowPos(RBBINode *n) {
  300. if (n == nullptr ||
  301. n->fType == RBBINode::leafChar ||
  302. n->fType == RBBINode::endMark) {
  303. return;
  304. }
  305. calcFollowPos(n->fLeftChild);
  306. calcFollowPos(n->fRightChild);
  307. // Aho rule #1
  308. if (n->fType == RBBINode::opCat) {
  309. RBBINode *i; // is 'i' in Aho's description
  310. uint32_t ix;
  311. UVector *LastPosOfLeftChild = n->fLeftChild->fLastPosSet;
  312. for (ix=0; ix<(uint32_t)LastPosOfLeftChild->size(); ix++) {
  313. i = (RBBINode *)LastPosOfLeftChild->elementAt(ix);
  314. setAdd(i->fFollowPos, n->fRightChild->fFirstPosSet);
  315. }
  316. }
  317. // Aho rule #2
  318. if (n->fType == RBBINode::opStar ||
  319. n->fType == RBBINode::opPlus) {
  320. RBBINode *i; // again, n and i are the names from Aho's description.
  321. uint32_t ix;
  322. for (ix=0; ix<(uint32_t)n->fLastPosSet->size(); ix++) {
  323. i = (RBBINode *)n->fLastPosSet->elementAt(ix);
  324. setAdd(i->fFollowPos, n->fFirstPosSet);
  325. }
  326. }
  327. }
  328. //-----------------------------------------------------------------------------
  329. //
  330. // addRuleRootNodes Recursively walk a parse tree, adding all nodes flagged
  331. // as roots of a rule to a destination vector.
  332. //
  333. //-----------------------------------------------------------------------------
  334. void RBBITableBuilder::addRuleRootNodes(UVector *dest, RBBINode *node) {
  335. if (node == nullptr || U_FAILURE(*fStatus)) {
  336. return;
  337. }
  338. U_ASSERT(!dest->hasDeleter());
  339. if (node->fRuleRoot) {
  340. dest->addElement(node, *fStatus);
  341. // Note: rules cannot nest. If we found a rule start node,
  342. // no child node can also be a start node.
  343. return;
  344. }
  345. addRuleRootNodes(dest, node->fLeftChild);
  346. addRuleRootNodes(dest, node->fRightChild);
  347. }
  348. //-----------------------------------------------------------------------------
  349. //
  350. // calcChainedFollowPos. Modify the previously calculated followPos sets
  351. // to implement rule chaining. NOT described by Aho
  352. //
  353. //-----------------------------------------------------------------------------
  354. void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree, RBBINode *endMarkNode) {
  355. UVector leafNodes(*fStatus);
  356. if (U_FAILURE(*fStatus)) {
  357. return;
  358. }
  359. // get a list all leaf nodes
  360. tree->findNodes(&leafNodes, RBBINode::leafChar, *fStatus);
  361. if (U_FAILURE(*fStatus)) {
  362. return;
  363. }
  364. // Collect all leaf nodes that can start matches for rules
  365. // with inbound chaining enabled, which is the union of the
  366. // firstPosition sets from each of the rule root nodes.
  367. UVector ruleRootNodes(*fStatus);
  368. addRuleRootNodes(&ruleRootNodes, tree);
  369. UVector matchStartNodes(*fStatus);
  370. for (int j=0; j<ruleRootNodes.size(); ++j) {
  371. RBBINode *node = static_cast<RBBINode *>(ruleRootNodes.elementAt(j));
  372. if (node->fChainIn) {
  373. setAdd(&matchStartNodes, node->fFirstPosSet);
  374. }
  375. }
  376. if (U_FAILURE(*fStatus)) {
  377. return;
  378. }
  379. int32_t endNodeIx;
  380. int32_t startNodeIx;
  381. for (endNodeIx=0; endNodeIx<leafNodes.size(); endNodeIx++) {
  382. RBBINode *endNode = (RBBINode *)leafNodes.elementAt(endNodeIx);
  383. // Identify leaf nodes that correspond to overall rule match positions.
  384. // These include the endMarkNode in their followPos sets.
  385. //
  386. // Note: do not consider other end marker nodes, those that are added to
  387. // look-ahead rules. These can't chain; a match immediately stops
  388. // further matching. This leaves exactly one end marker node, the one
  389. // at the end of the complete tree.
  390. if (!endNode->fFollowPos->contains(endMarkNode)) {
  391. continue;
  392. }
  393. // We've got a node that can end a match.
  394. // !!LBCMNoChain implementation: If this node's val correspond to
  395. // the Line Break $CM char class, don't chain from it.
  396. // TODO: Remove this. !!LBCMNoChain is deprecated, and is not used
  397. // by any of the standard ICU rules.
  398. if (fRB->fLBCMNoChain) {
  399. UChar32 c = this->fRB->fSetBuilder->getFirstChar(endNode->fVal);
  400. if (c != -1) {
  401. // c == -1 occurs with sets containing only the {eof} marker string.
  402. ULineBreak cLBProp = (ULineBreak)u_getIntPropertyValue(c, UCHAR_LINE_BREAK);
  403. if (cLBProp == U_LB_COMBINING_MARK) {
  404. continue;
  405. }
  406. }
  407. }
  408. // Now iterate over the nodes that can start a match, looking for ones
  409. // with the same char class as our ending node.
  410. RBBINode *startNode;
  411. for (startNodeIx = 0; startNodeIx<matchStartNodes.size(); startNodeIx++) {
  412. startNode = (RBBINode *)matchStartNodes.elementAt(startNodeIx);
  413. if (startNode->fType != RBBINode::leafChar) {
  414. continue;
  415. }
  416. if (endNode->fVal == startNode->fVal) {
  417. // The end val (character class) of one possible match is the
  418. // same as the start of another.
  419. // Add all nodes from the followPos of the start node to the
  420. // followPos set of the end node, which will have the effect of
  421. // letting matches transition from a match state at endNode
  422. // to the second char of a match starting with startNode.
  423. setAdd(endNode->fFollowPos, startNode->fFollowPos);
  424. }
  425. }
  426. }
  427. }
  428. //-----------------------------------------------------------------------------
  429. //
  430. // bofFixup. Fixup for state tables that include {bof} beginning of input testing.
  431. // Do an swizzle similar to chaining, modifying the followPos set of
  432. // the bofNode to include the followPos nodes from other {bot} nodes
  433. // scattered through the tree.
  434. //
  435. // This function has much in common with calcChainedFollowPos().
  436. //
  437. //-----------------------------------------------------------------------------
  438. void RBBITableBuilder::bofFixup() {
  439. if (U_FAILURE(*fStatus)) {
  440. return;
  441. }
  442. // The parse tree looks like this ...
  443. // fTree root ---> <cat>
  444. // / \ .
  445. // <cat> <#end node>
  446. // / \ .
  447. // <bofNode> rest
  448. // of tree
  449. //
  450. // We will be adding things to the followPos set of the <bofNode>
  451. //
  452. RBBINode *bofNode = fTree->fLeftChild->fLeftChild;
  453. U_ASSERT(bofNode->fType == RBBINode::leafChar);
  454. U_ASSERT(bofNode->fVal == 2);
  455. // Get all nodes that can be the start a match of the user-written rules
  456. // (excluding the fake bofNode)
  457. // We want the nodes that can start a match in the
  458. // part labeled "rest of tree"
  459. //
  460. UVector *matchStartNodes = fTree->fLeftChild->fRightChild->fFirstPosSet;
  461. RBBINode *startNode;
  462. int startNodeIx;
  463. for (startNodeIx = 0; startNodeIx<matchStartNodes->size(); startNodeIx++) {
  464. startNode = (RBBINode *)matchStartNodes->elementAt(startNodeIx);
  465. if (startNode->fType != RBBINode::leafChar) {
  466. continue;
  467. }
  468. if (startNode->fVal == bofNode->fVal) {
  469. // We found a leaf node corresponding to a {bof} that was
  470. // explicitly written into a rule.
  471. // Add everything from the followPos set of this node to the
  472. // followPos set of the fake bofNode at the start of the tree.
  473. //
  474. setAdd(bofNode->fFollowPos, startNode->fFollowPos);
  475. }
  476. }
  477. }
  478. //-----------------------------------------------------------------------------
  479. //
  480. // buildStateTable() Determine the set of runtime DFA states and the
  481. // transition tables for these states, by the algorithm
  482. // of fig. 3.44 in Aho.
  483. //
  484. // Most of the comments are quotes of Aho's psuedo-code.
  485. //
  486. //-----------------------------------------------------------------------------
  487. void RBBITableBuilder::buildStateTable() {
  488. if (U_FAILURE(*fStatus)) {
  489. return;
  490. }
  491. RBBIStateDescriptor *failState;
  492. // Set it to nullptr to avoid uninitialized warning
  493. RBBIStateDescriptor *initialState = nullptr;
  494. //
  495. // Add a dummy state 0 - the stop state. Not from Aho.
  496. int lastInputSymbol = fRB->fSetBuilder->getNumCharCategories() - 1;
  497. failState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
  498. if (failState == nullptr) {
  499. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  500. goto ExitBuildSTdeleteall;
  501. }
  502. failState->fPositions = new UVector(*fStatus);
  503. if (failState->fPositions == nullptr) {
  504. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  505. }
  506. if (failState->fPositions == nullptr || U_FAILURE(*fStatus)) {
  507. goto ExitBuildSTdeleteall;
  508. }
  509. fDStates->addElement(failState, *fStatus);
  510. if (U_FAILURE(*fStatus)) {
  511. goto ExitBuildSTdeleteall;
  512. }
  513. // initially, the only unmarked state in Dstates is firstpos(root),
  514. // where toot is the root of the syntax tree for (r)#;
  515. initialState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
  516. if (initialState == nullptr) {
  517. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  518. }
  519. if (U_FAILURE(*fStatus)) {
  520. goto ExitBuildSTdeleteall;
  521. }
  522. initialState->fPositions = new UVector(*fStatus);
  523. if (initialState->fPositions == nullptr) {
  524. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  525. }
  526. if (U_FAILURE(*fStatus)) {
  527. goto ExitBuildSTdeleteall;
  528. }
  529. setAdd(initialState->fPositions, fTree->fFirstPosSet);
  530. fDStates->addElement(initialState, *fStatus);
  531. if (U_FAILURE(*fStatus)) {
  532. goto ExitBuildSTdeleteall;
  533. }
  534. // while there is an unmarked state T in Dstates do begin
  535. for (;;) {
  536. RBBIStateDescriptor *T = nullptr;
  537. int32_t tx;
  538. for (tx=1; tx<fDStates->size(); tx++) {
  539. RBBIStateDescriptor *temp;
  540. temp = (RBBIStateDescriptor *)fDStates->elementAt(tx);
  541. if (temp->fMarked == false) {
  542. T = temp;
  543. break;
  544. }
  545. }
  546. if (T == nullptr) {
  547. break;
  548. }
  549. // mark T;
  550. T->fMarked = true;
  551. // for each input symbol a do begin
  552. int32_t a;
  553. for (a = 1; a<=lastInputSymbol; a++) {
  554. // let U be the set of positions that are in followpos(p)
  555. // for some position p in T
  556. // such that the symbol at position p is a;
  557. UVector *U = nullptr;
  558. RBBINode *p;
  559. int32_t px;
  560. for (px=0; px<T->fPositions->size(); px++) {
  561. p = (RBBINode *)T->fPositions->elementAt(px);
  562. if ((p->fType == RBBINode::leafChar) && (p->fVal == a)) {
  563. if (U == nullptr) {
  564. U = new UVector(*fStatus);
  565. if (U == nullptr) {
  566. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  567. goto ExitBuildSTdeleteall;
  568. }
  569. }
  570. setAdd(U, p->fFollowPos);
  571. }
  572. }
  573. // if U is not empty and not in DStates then
  574. int32_t ux = 0;
  575. UBool UinDstates = false;
  576. if (U != nullptr) {
  577. U_ASSERT(U->size() > 0);
  578. int ix;
  579. for (ix=0; ix<fDStates->size(); ix++) {
  580. RBBIStateDescriptor *temp2;
  581. temp2 = (RBBIStateDescriptor *)fDStates->elementAt(ix);
  582. if (setEquals(U, temp2->fPositions)) {
  583. delete U;
  584. U = temp2->fPositions;
  585. ux = ix;
  586. UinDstates = true;
  587. break;
  588. }
  589. }
  590. // Add U as an unmarked state to Dstates
  591. if (!UinDstates)
  592. {
  593. RBBIStateDescriptor *newState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
  594. if (newState == nullptr) {
  595. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  596. }
  597. if (U_FAILURE(*fStatus)) {
  598. goto ExitBuildSTdeleteall;
  599. }
  600. newState->fPositions = U;
  601. fDStates->addElement(newState, *fStatus);
  602. if (U_FAILURE(*fStatus)) {
  603. return;
  604. }
  605. ux = fDStates->size()-1;
  606. }
  607. // Dtran[T, a] := U;
  608. T->fDtran->setElementAt(ux, a);
  609. }
  610. }
  611. }
  612. return;
  613. // delete local pointers only if error occurred.
  614. ExitBuildSTdeleteall:
  615. delete initialState;
  616. delete failState;
  617. }
  618. /**
  619. * mapLookAheadRules
  620. *
  621. */
  622. void RBBITableBuilder::mapLookAheadRules() {
  623. fLookAheadRuleMap = new UVector32(fRB->fScanner->numRules() + 1, *fStatus);
  624. if (fLookAheadRuleMap == nullptr) {
  625. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  626. }
  627. if (U_FAILURE(*fStatus)) {
  628. return;
  629. }
  630. fLookAheadRuleMap->setSize(fRB->fScanner->numRules() + 1);
  631. for (int32_t n=0; n<fDStates->size(); n++) {
  632. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n);
  633. int32_t laSlotForState = 0;
  634. // Establish the look-ahead slot for this state, if the state covers
  635. // any look-ahead nodes - corresponding to the '/' in look-ahead rules.
  636. // If any of the look-ahead nodes already have a slot assigned, use it,
  637. // otherwise assign a new one.
  638. bool sawLookAheadNode = false;
  639. for (int32_t ipos=0; ipos<sd->fPositions->size(); ++ipos) {
  640. RBBINode *node = static_cast<RBBINode *>(sd->fPositions->elementAt(ipos));
  641. if (node->fType != RBBINode::NodeType::lookAhead) {
  642. continue;
  643. }
  644. sawLookAheadNode = true;
  645. int32_t ruleNum = node->fVal; // Set when rule was originally parsed.
  646. U_ASSERT(ruleNum < fLookAheadRuleMap->size());
  647. U_ASSERT(ruleNum > 0);
  648. int32_t laSlot = fLookAheadRuleMap->elementAti(ruleNum);
  649. if (laSlot != 0) {
  650. if (laSlotForState == 0) {
  651. laSlotForState = laSlot;
  652. } else {
  653. // TODO: figure out if this can fail, change to setting an error code if so.
  654. U_ASSERT(laSlot == laSlotForState);
  655. }
  656. }
  657. }
  658. if (!sawLookAheadNode) {
  659. continue;
  660. }
  661. if (laSlotForState == 0) {
  662. laSlotForState = ++fLASlotsInUse;
  663. }
  664. // For each look ahead node covered by this state,
  665. // set the mapping from the node's rule number to the look ahead slot.
  666. // There can be multiple nodes/rule numbers going to the same la slot.
  667. for (int32_t ipos=0; ipos<sd->fPositions->size(); ++ipos) {
  668. RBBINode *node = static_cast<RBBINode *>(sd->fPositions->elementAt(ipos));
  669. if (node->fType != RBBINode::NodeType::lookAhead) {
  670. continue;
  671. }
  672. int32_t ruleNum = node->fVal; // Set when rule was originally parsed.
  673. int32_t existingVal = fLookAheadRuleMap->elementAti(ruleNum);
  674. (void)existingVal;
  675. U_ASSERT(existingVal == 0 || existingVal == laSlotForState);
  676. fLookAheadRuleMap->setElementAt(laSlotForState, ruleNum);
  677. }
  678. }
  679. }
  680. //-----------------------------------------------------------------------------
  681. //
  682. // flagAcceptingStates Identify accepting states.
  683. // First get a list of all of the end marker nodes.
  684. // Then, for each state s,
  685. // if s contains one of the end marker nodes in its list of tree positions then
  686. // s is an accepting state.
  687. //
  688. //-----------------------------------------------------------------------------
  689. void RBBITableBuilder::flagAcceptingStates() {
  690. if (U_FAILURE(*fStatus)) {
  691. return;
  692. }
  693. UVector endMarkerNodes(*fStatus);
  694. RBBINode *endMarker;
  695. int32_t i;
  696. int32_t n;
  697. if (U_FAILURE(*fStatus)) {
  698. return;
  699. }
  700. fTree->findNodes(&endMarkerNodes, RBBINode::endMark, *fStatus);
  701. if (U_FAILURE(*fStatus)) {
  702. return;
  703. }
  704. for (i=0; i<endMarkerNodes.size(); i++) {
  705. endMarker = (RBBINode *)endMarkerNodes.elementAt(i);
  706. for (n=0; n<fDStates->size(); n++) {
  707. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n);
  708. if (sd->fPositions->indexOf(endMarker) >= 0) {
  709. // Any non-zero value for fAccepting means this is an accepting node.
  710. // The value is what will be returned to the user as the break status.
  711. // If no other value was specified, force it to ACCEPTING_UNCONDITIONAL (1).
  712. if (sd->fAccepting==0) {
  713. // State hasn't been marked as accepting yet. Do it now.
  714. sd->fAccepting = fLookAheadRuleMap->elementAti(endMarker->fVal);
  715. if (sd->fAccepting == 0) {
  716. sd->fAccepting = ACCEPTING_UNCONDITIONAL;
  717. }
  718. }
  719. if (sd->fAccepting==ACCEPTING_UNCONDITIONAL && endMarker->fVal != 0) {
  720. // Both lookahead and non-lookahead accepting for this state.
  721. // Favor the look-ahead, because a look-ahead match needs to
  722. // immediately stop the run-time engine. First match, not longest.
  723. sd->fAccepting = fLookAheadRuleMap->elementAti(endMarker->fVal);
  724. }
  725. // implicit else:
  726. // if sd->fAccepting already had a value other than 0 or 1, leave it be.
  727. }
  728. }
  729. }
  730. }
  731. //-----------------------------------------------------------------------------
  732. //
  733. // flagLookAheadStates Very similar to flagAcceptingStates, above.
  734. //
  735. //-----------------------------------------------------------------------------
  736. void RBBITableBuilder::flagLookAheadStates() {
  737. if (U_FAILURE(*fStatus)) {
  738. return;
  739. }
  740. UVector lookAheadNodes(*fStatus);
  741. RBBINode *lookAheadNode;
  742. int32_t i;
  743. int32_t n;
  744. fTree->findNodes(&lookAheadNodes, RBBINode::lookAhead, *fStatus);
  745. if (U_FAILURE(*fStatus)) {
  746. return;
  747. }
  748. for (i=0; i<lookAheadNodes.size(); i++) {
  749. lookAheadNode = (RBBINode *)lookAheadNodes.elementAt(i);
  750. U_ASSERT(lookAheadNode->fType == RBBINode::NodeType::lookAhead);
  751. for (n=0; n<fDStates->size(); n++) {
  752. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n);
  753. int32_t positionsIdx = sd->fPositions->indexOf(lookAheadNode);
  754. if (positionsIdx >= 0) {
  755. U_ASSERT(lookAheadNode == sd->fPositions->elementAt(positionsIdx));
  756. uint32_t lookaheadSlot = fLookAheadRuleMap->elementAti(lookAheadNode->fVal);
  757. U_ASSERT(sd->fLookAhead == 0 || sd->fLookAhead == lookaheadSlot);
  758. // if (sd->fLookAhead != 0 && sd->fLookAhead != lookaheadSlot) {
  759. // printf("%s:%d Bingo. sd->fLookAhead:%d lookaheadSlot:%d\n",
  760. // __FILE__, __LINE__, sd->fLookAhead, lookaheadSlot);
  761. // }
  762. sd->fLookAhead = lookaheadSlot;
  763. }
  764. }
  765. }
  766. }
  767. //-----------------------------------------------------------------------------
  768. //
  769. // flagTaggedStates
  770. //
  771. //-----------------------------------------------------------------------------
  772. void RBBITableBuilder::flagTaggedStates() {
  773. if (U_FAILURE(*fStatus)) {
  774. return;
  775. }
  776. UVector tagNodes(*fStatus);
  777. RBBINode *tagNode;
  778. int32_t i;
  779. int32_t n;
  780. if (U_FAILURE(*fStatus)) {
  781. return;
  782. }
  783. fTree->findNodes(&tagNodes, RBBINode::tag, *fStatus);
  784. if (U_FAILURE(*fStatus)) {
  785. return;
  786. }
  787. for (i=0; i<tagNodes.size(); i++) { // For each tag node t (all of 'em)
  788. tagNode = (RBBINode *)tagNodes.elementAt(i);
  789. for (n=0; n<fDStates->size(); n++) { // For each state s (row in the state table)
  790. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n);
  791. if (sd->fPositions->indexOf(tagNode) >= 0) { // if s include the tag node t
  792. sortedAdd(&sd->fTagVals, tagNode->fVal);
  793. }
  794. }
  795. }
  796. }
  797. //-----------------------------------------------------------------------------
  798. //
  799. // mergeRuleStatusVals
  800. //
  801. // Update the global table of rule status {tag} values
  802. // The rule builder has a global vector of status values that are common
  803. // for all tables. Merge the ones from this table into the global set.
  804. //
  805. //-----------------------------------------------------------------------------
  806. void RBBITableBuilder::mergeRuleStatusVals() {
  807. //
  808. // The basic outline of what happens here is this...
  809. //
  810. // for each state in this state table
  811. // if the status tag list for this state is in the global statuses list
  812. // record where and
  813. // continue with the next state
  814. // else
  815. // add the tag list for this state to the global list.
  816. //
  817. int i;
  818. int n;
  819. // Pre-set a single tag of {0} into the table.
  820. // We will need this as a default, for rule sets with no explicit tagging.
  821. if (fRB->fRuleStatusVals->size() == 0) {
  822. fRB->fRuleStatusVals->addElement(1, *fStatus); // Num of statuses in group
  823. fRB->fRuleStatusVals->addElement((int32_t)0, *fStatus); // and our single status of zero
  824. }
  825. // For each state
  826. for (n=0; n<fDStates->size(); n++) {
  827. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n);
  828. UVector *thisStatesTagValues = sd->fTagVals;
  829. if (thisStatesTagValues == nullptr) {
  830. // No tag values are explicitly associated with this state.
  831. // Set the default tag value.
  832. sd->fTagsIdx = 0;
  833. continue;
  834. }
  835. // There are tag(s) associated with this state.
  836. // fTagsIdx will be the index into the global tag list for this state's tag values.
  837. // Initial value of -1 flags that we haven't got it set yet.
  838. sd->fTagsIdx = -1;
  839. int32_t thisTagGroupStart = 0; // indexes into the global rule status vals list
  840. int32_t nextTagGroupStart = 0;
  841. // Loop runs once per group of tags in the global list
  842. while (nextTagGroupStart < fRB->fRuleStatusVals->size()) {
  843. thisTagGroupStart = nextTagGroupStart;
  844. nextTagGroupStart += fRB->fRuleStatusVals->elementAti(thisTagGroupStart) + 1;
  845. if (thisStatesTagValues->size() != fRB->fRuleStatusVals->elementAti(thisTagGroupStart)) {
  846. // The number of tags for this state is different from
  847. // the number of tags in this group from the global list.
  848. // Continue with the next group from the global list.
  849. continue;
  850. }
  851. // The lengths match, go ahead and compare the actual tag values
  852. // between this state and the group from the global list.
  853. for (i=0; i<thisStatesTagValues->size(); i++) {
  854. if (thisStatesTagValues->elementAti(i) !=
  855. fRB->fRuleStatusVals->elementAti(thisTagGroupStart + 1 + i) ) {
  856. // Mismatch.
  857. break;
  858. }
  859. }
  860. if (i == thisStatesTagValues->size()) {
  861. // We found a set of tag values in the global list that match
  862. // those for this state. Use them.
  863. sd->fTagsIdx = thisTagGroupStart;
  864. break;
  865. }
  866. }
  867. if (sd->fTagsIdx == -1) {
  868. // No suitable entry in the global tag list already. Add one
  869. sd->fTagsIdx = fRB->fRuleStatusVals->size();
  870. fRB->fRuleStatusVals->addElement(thisStatesTagValues->size(), *fStatus);
  871. for (i=0; i<thisStatesTagValues->size(); i++) {
  872. fRB->fRuleStatusVals->addElement(thisStatesTagValues->elementAti(i), *fStatus);
  873. }
  874. }
  875. }
  876. }
  877. //-----------------------------------------------------------------------------
  878. //
  879. // sortedAdd Add a value to a vector of sorted values (ints).
  880. // Do not replicate entries; if the value is already there, do not
  881. // add a second one.
  882. // Lazily create the vector if it does not already exist.
  883. //
  884. //-----------------------------------------------------------------------------
  885. void RBBITableBuilder::sortedAdd(UVector **vector, int32_t val) {
  886. int32_t i;
  887. if (*vector == nullptr) {
  888. *vector = new UVector(*fStatus);
  889. }
  890. if (*vector == nullptr || U_FAILURE(*fStatus)) {
  891. return;
  892. }
  893. UVector *vec = *vector;
  894. int32_t vSize = vec->size();
  895. for (i=0; i<vSize; i++) {
  896. int32_t valAtI = vec->elementAti(i);
  897. if (valAtI == val) {
  898. // The value is already in the vector. Don't add it again.
  899. return;
  900. }
  901. if (valAtI > val) {
  902. break;
  903. }
  904. }
  905. vec->insertElementAt(val, i, *fStatus);
  906. }
  907. //-----------------------------------------------------------------------------
  908. //
  909. // setAdd Set operation on UVector
  910. // dest = dest union source
  911. // Elements may only appear once and must be sorted.
  912. //
  913. //-----------------------------------------------------------------------------
  914. void RBBITableBuilder::setAdd(UVector *dest, UVector *source) {
  915. U_ASSERT(!dest->hasDeleter());
  916. U_ASSERT(!source->hasDeleter());
  917. int32_t destOriginalSize = dest->size();
  918. int32_t sourceSize = source->size();
  919. int32_t di = 0;
  920. MaybeStackArray<void *, 16> destArray, sourceArray; // Handle small cases without malloc
  921. void **destPtr, **sourcePtr;
  922. void **destLim, **sourceLim;
  923. if (destOriginalSize > destArray.getCapacity()) {
  924. if (destArray.resize(destOriginalSize) == nullptr) {
  925. return;
  926. }
  927. }
  928. destPtr = destArray.getAlias();
  929. destLim = destPtr + destOriginalSize; // destArray.getArrayLimit()?
  930. if (sourceSize > sourceArray.getCapacity()) {
  931. if (sourceArray.resize(sourceSize) == nullptr) {
  932. return;
  933. }
  934. }
  935. sourcePtr = sourceArray.getAlias();
  936. sourceLim = sourcePtr + sourceSize; // sourceArray.getArrayLimit()?
  937. // Avoid multiple "get element" calls by getting the contents into arrays
  938. (void) dest->toArray(destPtr);
  939. (void) source->toArray(sourcePtr);
  940. dest->setSize(sourceSize+destOriginalSize, *fStatus);
  941. if (U_FAILURE(*fStatus)) {
  942. return;
  943. }
  944. while (sourcePtr < sourceLim && destPtr < destLim) {
  945. if (*destPtr == *sourcePtr) {
  946. dest->setElementAt(*sourcePtr++, di++);
  947. destPtr++;
  948. }
  949. // This check is required for machines with segmented memory, like i5/OS.
  950. // Direct pointer comparison is not recommended.
  951. else if (uprv_memcmp(destPtr, sourcePtr, sizeof(void *)) < 0) {
  952. dest->setElementAt(*destPtr++, di++);
  953. }
  954. else { /* *sourcePtr < *destPtr */
  955. dest->setElementAt(*sourcePtr++, di++);
  956. }
  957. }
  958. // At most one of these two cleanup loops will execute
  959. while (destPtr < destLim) {
  960. dest->setElementAt(*destPtr++, di++);
  961. }
  962. while (sourcePtr < sourceLim) {
  963. dest->setElementAt(*sourcePtr++, di++);
  964. }
  965. dest->setSize(di, *fStatus);
  966. }
  967. //-----------------------------------------------------------------------------
  968. //
  969. // setEqual Set operation on UVector.
  970. // Compare for equality.
  971. // Elements must be sorted.
  972. //
  973. //-----------------------------------------------------------------------------
  974. UBool RBBITableBuilder::setEquals(UVector *a, UVector *b) {
  975. return a->equals(*b);
  976. }
  977. //-----------------------------------------------------------------------------
  978. //
  979. // printPosSets Debug function. Dump Nullable, firstpos, lastpos and followpos
  980. // for each node in the tree.
  981. //
  982. //-----------------------------------------------------------------------------
  983. #ifdef RBBI_DEBUG
  984. void RBBITableBuilder::printPosSets(RBBINode *n) {
  985. if (n==nullptr) {
  986. return;
  987. }
  988. printf("\n");
  989. RBBINode::printNodeHeader();
  990. RBBINode::printNode(n);
  991. RBBIDebugPrintf(" Nullable: %s\n", n->fNullable?"true":"false");
  992. RBBIDebugPrintf(" firstpos: ");
  993. printSet(n->fFirstPosSet);
  994. RBBIDebugPrintf(" lastpos: ");
  995. printSet(n->fLastPosSet);
  996. RBBIDebugPrintf(" followpos: ");
  997. printSet(n->fFollowPos);
  998. printPosSets(n->fLeftChild);
  999. printPosSets(n->fRightChild);
  1000. }
  1001. #endif
  1002. //
  1003. // findDuplCharClassFrom()
  1004. //
  1005. bool RBBITableBuilder::findDuplCharClassFrom(IntPair *categories) {
  1006. int32_t numStates = fDStates->size();
  1007. int32_t numCols = fRB->fSetBuilder->getNumCharCategories();
  1008. for (; categories->first < numCols-1; categories->first++) {
  1009. // Note: dictionary & non-dictionary columns cannot be merged.
  1010. // The limitSecond value prevents considering mixed pairs.
  1011. // Dictionary categories are >= DictCategoriesStart.
  1012. // Non dict categories are < DictCategoriesStart.
  1013. int limitSecond = categories->first < fRB->fSetBuilder->getDictCategoriesStart() ?
  1014. fRB->fSetBuilder->getDictCategoriesStart() : numCols;
  1015. for (categories->second=categories->first+1; categories->second < limitSecond; categories->second++) {
  1016. // Initialized to different values to prevent returning true if numStates = 0 (implies no duplicates).
  1017. uint16_t table_base = 0;
  1018. uint16_t table_dupl = 1;
  1019. for (int32_t state=0; state<numStates; state++) {
  1020. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(state);
  1021. table_base = (uint16_t)sd->fDtran->elementAti(categories->first);
  1022. table_dupl = (uint16_t)sd->fDtran->elementAti(categories->second);
  1023. if (table_base != table_dupl) {
  1024. break;
  1025. }
  1026. }
  1027. if (table_base == table_dupl) {
  1028. return true;
  1029. }
  1030. }
  1031. }
  1032. return false;
  1033. }
  1034. //
  1035. // removeColumn()
  1036. //
  1037. void RBBITableBuilder::removeColumn(int32_t column) {
  1038. int32_t numStates = fDStates->size();
  1039. for (int32_t state=0; state<numStates; state++) {
  1040. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(state);
  1041. U_ASSERT(column < sd->fDtran->size());
  1042. sd->fDtran->removeElementAt(column);
  1043. }
  1044. }
  1045. /*
  1046. * findDuplicateState
  1047. */
  1048. bool RBBITableBuilder::findDuplicateState(IntPair *states) {
  1049. int32_t numStates = fDStates->size();
  1050. int32_t numCols = fRB->fSetBuilder->getNumCharCategories();
  1051. for (; states->first<numStates-1; states->first++) {
  1052. RBBIStateDescriptor *firstSD = (RBBIStateDescriptor *)fDStates->elementAt(states->first);
  1053. for (states->second=states->first+1; states->second<numStates; states->second++) {
  1054. RBBIStateDescriptor *duplSD = (RBBIStateDescriptor *)fDStates->elementAt(states->second);
  1055. if (firstSD->fAccepting != duplSD->fAccepting ||
  1056. firstSD->fLookAhead != duplSD->fLookAhead ||
  1057. firstSD->fTagsIdx != duplSD->fTagsIdx) {
  1058. continue;
  1059. }
  1060. bool rowsMatch = true;
  1061. for (int32_t col=0; col < numCols; ++col) {
  1062. int32_t firstVal = firstSD->fDtran->elementAti(col);
  1063. int32_t duplVal = duplSD->fDtran->elementAti(col);
  1064. if (!((firstVal == duplVal) ||
  1065. ((firstVal == states->first || firstVal == states->second) &&
  1066. (duplVal == states->first || duplVal == states->second)))) {
  1067. rowsMatch = false;
  1068. break;
  1069. }
  1070. }
  1071. if (rowsMatch) {
  1072. return true;
  1073. }
  1074. }
  1075. }
  1076. return false;
  1077. }
  1078. bool RBBITableBuilder::findDuplicateSafeState(IntPair *states) {
  1079. int32_t numStates = fSafeTable->size();
  1080. for (; states->first<numStates-1; states->first++) {
  1081. UnicodeString *firstRow = static_cast<UnicodeString *>(fSafeTable->elementAt(states->first));
  1082. for (states->second=states->first+1; states->second<numStates; states->second++) {
  1083. UnicodeString *duplRow = static_cast<UnicodeString *>(fSafeTable->elementAt(states->second));
  1084. bool rowsMatch = true;
  1085. int32_t numCols = firstRow->length();
  1086. for (int32_t col=0; col < numCols; ++col) {
  1087. int32_t firstVal = firstRow->charAt(col);
  1088. int32_t duplVal = duplRow->charAt(col);
  1089. if (!((firstVal == duplVal) ||
  1090. ((firstVal == states->first || firstVal == states->second) &&
  1091. (duplVal == states->first || duplVal == states->second)))) {
  1092. rowsMatch = false;
  1093. break;
  1094. }
  1095. }
  1096. if (rowsMatch) {
  1097. return true;
  1098. }
  1099. }
  1100. }
  1101. return false;
  1102. }
  1103. void RBBITableBuilder::removeState(IntPair duplStates) {
  1104. const int32_t keepState = duplStates.first;
  1105. const int32_t duplState = duplStates.second;
  1106. U_ASSERT(keepState < duplState);
  1107. U_ASSERT(duplState < fDStates->size());
  1108. RBBIStateDescriptor *duplSD = (RBBIStateDescriptor *)fDStates->elementAt(duplState);
  1109. fDStates->removeElementAt(duplState);
  1110. delete duplSD;
  1111. int32_t numStates = fDStates->size();
  1112. int32_t numCols = fRB->fSetBuilder->getNumCharCategories();
  1113. for (int32_t state=0; state<numStates; ++state) {
  1114. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(state);
  1115. for (int32_t col=0; col<numCols; col++) {
  1116. int32_t existingVal = sd->fDtran->elementAti(col);
  1117. int32_t newVal = existingVal;
  1118. if (existingVal == duplState) {
  1119. newVal = keepState;
  1120. } else if (existingVal > duplState) {
  1121. newVal = existingVal - 1;
  1122. }
  1123. sd->fDtran->setElementAt(newVal, col);
  1124. }
  1125. }
  1126. }
  1127. void RBBITableBuilder::removeSafeState(IntPair duplStates) {
  1128. const int32_t keepState = duplStates.first;
  1129. const int32_t duplState = duplStates.second;
  1130. U_ASSERT(keepState < duplState);
  1131. U_ASSERT(duplState < fSafeTable->size());
  1132. fSafeTable->removeElementAt(duplState); // Note that fSafeTable has a deleter function
  1133. // and will auto-delete the removed element.
  1134. int32_t numStates = fSafeTable->size();
  1135. for (int32_t state=0; state<numStates; ++state) {
  1136. UnicodeString *sd = (UnicodeString *)fSafeTable->elementAt(state);
  1137. int32_t numCols = sd->length();
  1138. for (int32_t col=0; col<numCols; col++) {
  1139. int32_t existingVal = sd->charAt(col);
  1140. int32_t newVal = existingVal;
  1141. if (existingVal == duplState) {
  1142. newVal = keepState;
  1143. } else if (existingVal > duplState) {
  1144. newVal = existingVal - 1;
  1145. }
  1146. sd->setCharAt(col, static_cast<char16_t>(newVal));
  1147. }
  1148. }
  1149. }
  1150. /*
  1151. * RemoveDuplicateStates
  1152. */
  1153. int32_t RBBITableBuilder::removeDuplicateStates() {
  1154. IntPair dupls = {3, 0};
  1155. int32_t numStatesRemoved = 0;
  1156. while (findDuplicateState(&dupls)) {
  1157. // printf("Removing duplicate states (%d, %d)\n", dupls.first, dupls.second);
  1158. removeState(dupls);
  1159. ++numStatesRemoved;
  1160. }
  1161. return numStatesRemoved;
  1162. }
  1163. //-----------------------------------------------------------------------------
  1164. //
  1165. // getTableSize() Calculate the size of the runtime form of this
  1166. // state transition table.
  1167. //
  1168. //-----------------------------------------------------------------------------
  1169. int32_t RBBITableBuilder::getTableSize() const {
  1170. int32_t size = 0;
  1171. int32_t numRows;
  1172. int32_t numCols;
  1173. int32_t rowSize;
  1174. if (fTree == nullptr) {
  1175. return 0;
  1176. }
  1177. size = offsetof(RBBIStateTable, fTableData); // The header, with no rows to the table.
  1178. numRows = fDStates->size();
  1179. numCols = fRB->fSetBuilder->getNumCharCategories();
  1180. if (use8BitsForTable()) {
  1181. rowSize = offsetof(RBBIStateTableRow8, fNextState) + sizeof(int8_t)*numCols;
  1182. } else {
  1183. rowSize = offsetof(RBBIStateTableRow16, fNextState) + sizeof(int16_t)*numCols;
  1184. }
  1185. size += numRows * rowSize;
  1186. return size;
  1187. }
  1188. bool RBBITableBuilder::use8BitsForTable() const {
  1189. return fDStates->size() <= kMaxStateFor8BitsTable;
  1190. }
  1191. //-----------------------------------------------------------------------------
  1192. //
  1193. // exportTable() export the state transition table in the format required
  1194. // by the runtime engine. getTableSize() bytes of memory
  1195. // must be available at the output address "where".
  1196. //
  1197. //-----------------------------------------------------------------------------
  1198. void RBBITableBuilder::exportTable(void *where) {
  1199. RBBIStateTable *table = (RBBIStateTable *)where;
  1200. uint32_t state;
  1201. int col;
  1202. if (U_FAILURE(*fStatus) || fTree == nullptr) {
  1203. return;
  1204. }
  1205. int32_t catCount = fRB->fSetBuilder->getNumCharCategories();
  1206. if (catCount > 0x7fff ||
  1207. fDStates->size() > 0x7fff) {
  1208. *fStatus = U_BRK_INTERNAL_ERROR;
  1209. return;
  1210. }
  1211. table->fNumStates = fDStates->size();
  1212. table->fDictCategoriesStart = fRB->fSetBuilder->getDictCategoriesStart();
  1213. table->fLookAheadResultsSize = fLASlotsInUse == ACCEPTING_UNCONDITIONAL ? 0 : fLASlotsInUse + 1;
  1214. table->fFlags = 0;
  1215. if (use8BitsForTable()) {
  1216. table->fRowLen = offsetof(RBBIStateTableRow8, fNextState) + sizeof(uint8_t) * catCount;
  1217. table->fFlags |= RBBI_8BITS_ROWS;
  1218. } else {
  1219. table->fRowLen = offsetof(RBBIStateTableRow16, fNextState) + sizeof(int16_t) * catCount;
  1220. }
  1221. if (fRB->fLookAheadHardBreak) {
  1222. table->fFlags |= RBBI_LOOKAHEAD_HARD_BREAK;
  1223. }
  1224. if (fRB->fSetBuilder->sawBOF()) {
  1225. table->fFlags |= RBBI_BOF_REQUIRED;
  1226. }
  1227. for (state=0; state<table->fNumStates; state++) {
  1228. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(state);
  1229. RBBIStateTableRow *row = (RBBIStateTableRow *)(table->fTableData + state*table->fRowLen);
  1230. if (use8BitsForTable()) {
  1231. U_ASSERT (sd->fAccepting <= 255);
  1232. U_ASSERT (sd->fLookAhead <= 255);
  1233. U_ASSERT (0 <= sd->fTagsIdx && sd->fTagsIdx <= 255);
  1234. RBBIStateTableRow8 *r8 = (RBBIStateTableRow8*)row;
  1235. r8->fAccepting = sd->fAccepting;
  1236. r8->fLookAhead = sd->fLookAhead;
  1237. r8->fTagsIdx = sd->fTagsIdx;
  1238. for (col=0; col<catCount; col++) {
  1239. U_ASSERT (sd->fDtran->elementAti(col) <= kMaxStateFor8BitsTable);
  1240. r8->fNextState[col] = sd->fDtran->elementAti(col);
  1241. }
  1242. } else {
  1243. U_ASSERT (sd->fAccepting <= 0xffff);
  1244. U_ASSERT (sd->fLookAhead <= 0xffff);
  1245. U_ASSERT (0 <= sd->fTagsIdx && sd->fTagsIdx <= 0xffff);
  1246. row->r16.fAccepting = sd->fAccepting;
  1247. row->r16.fLookAhead = sd->fLookAhead;
  1248. row->r16.fTagsIdx = sd->fTagsIdx;
  1249. for (col=0; col<catCount; col++) {
  1250. row->r16.fNextState[col] = sd->fDtran->elementAti(col);
  1251. }
  1252. }
  1253. }
  1254. }
  1255. /**
  1256. * Synthesize a safe state table from the main state table.
  1257. */
  1258. void RBBITableBuilder::buildSafeReverseTable(UErrorCode &status) {
  1259. // The safe table creation has three steps:
  1260. // 1. Identify pairs of character classes that are "safe." Safe means that boundaries
  1261. // following the pair do not depend on context or state before the pair. To test
  1262. // whether a pair is safe, run it through the main forward state table, starting
  1263. // from each state. If the the final state is the same, no matter what the starting state,
  1264. // the pair is safe.
  1265. //
  1266. // 2. Build a state table that recognizes the safe pairs. It's similar to their
  1267. // forward table, with a column for each input character [class], and a row for
  1268. // each state. Row 1 is the start state, and row 0 is the stop state. Initially
  1269. // create an additional state for each input character category; being in
  1270. // one of these states means that the character has been seen, and is potentially
  1271. // the first of a pair. In each of these rows, the entry for the second character
  1272. // of a safe pair is set to the stop state (0), indicating that a match was found.
  1273. // All other table entries are set to the state corresponding the current input
  1274. // character, allowing that character to be the of a start following pair.
  1275. //
  1276. // Because the safe rules are to be run in reverse, moving backwards in the text,
  1277. // the first and second pair categories are swapped when building the table.
  1278. //
  1279. // 3. Compress the table. There are typically many rows (states) that are
  1280. // equivalent - that have zeroes (match completed) in the same columns -
  1281. // and can be folded together.
  1282. // Each safe pair is stored as two UChars in the safePair string.
  1283. UnicodeString safePairs;
  1284. int32_t numCharClasses = fRB->fSetBuilder->getNumCharCategories();
  1285. int32_t numStates = fDStates->size();
  1286. for (int32_t c1=0; c1<numCharClasses; ++c1) {
  1287. for (int32_t c2=0; c2 < numCharClasses; ++c2) {
  1288. int32_t wantedEndState = -1;
  1289. int32_t endState = 0;
  1290. for (int32_t startState = 1; startState < numStates; ++startState) {
  1291. RBBIStateDescriptor *startStateD = static_cast<RBBIStateDescriptor *>(fDStates->elementAt(startState));
  1292. int32_t s2 = startStateD->fDtran->elementAti(c1);
  1293. RBBIStateDescriptor *s2StateD = static_cast<RBBIStateDescriptor *>(fDStates->elementAt(s2));
  1294. endState = s2StateD->fDtran->elementAti(c2);
  1295. if (wantedEndState < 0) {
  1296. wantedEndState = endState;
  1297. } else {
  1298. if (wantedEndState != endState) {
  1299. break;
  1300. }
  1301. }
  1302. }
  1303. if (wantedEndState == endState) {
  1304. safePairs.append((char16_t)c1);
  1305. safePairs.append((char16_t)c2);
  1306. // printf("(%d, %d) ", c1, c2);
  1307. }
  1308. }
  1309. // printf("\n");
  1310. }
  1311. // Populate the initial safe table.
  1312. // The table as a whole is UVector<UnicodeString>
  1313. // Each row is represented by a UnicodeString, being used as a Vector<int16>.
  1314. // Row 0 is the stop state.
  1315. // Row 1 is the start state.
  1316. // Row 2 and beyond are other states, initially one per char class, but
  1317. // after initial construction, many of the states will be combined, compacting the table.
  1318. // The String holds the nextState data only. The four leading fields of a row, fAccepting,
  1319. // fLookAhead, etc. are not needed for the safe table, and are omitted at this stage of building.
  1320. U_ASSERT(fSafeTable == nullptr);
  1321. LocalPointer<UVector> lpSafeTable(
  1322. new UVector(uprv_deleteUObject, uhash_compareUnicodeString, numCharClasses + 2, status), status);
  1323. if (U_FAILURE(status)) {
  1324. return;
  1325. }
  1326. fSafeTable = lpSafeTable.orphan();
  1327. for (int32_t row=0; row<numCharClasses + 2; ++row) {
  1328. LocalPointer<UnicodeString> lpString(new UnicodeString(numCharClasses, 0, numCharClasses+4), status);
  1329. fSafeTable->adoptElement(lpString.orphan(), status);
  1330. }
  1331. if (U_FAILURE(status)) {
  1332. return;
  1333. }
  1334. // From the start state, each input char class transitions to the state for that input.
  1335. UnicodeString &startState = *static_cast<UnicodeString *>(fSafeTable->elementAt(1));
  1336. for (int32_t charClass=0; charClass < numCharClasses; ++charClass) {
  1337. // Note: +2 for the start & stop state.
  1338. startState.setCharAt(charClass, static_cast<char16_t>(charClass+2));
  1339. }
  1340. // Initially make every other state table row look like the start state row,
  1341. for (int32_t row=2; row<numCharClasses+2; ++row) {
  1342. UnicodeString &rowState = *static_cast<UnicodeString *>(fSafeTable->elementAt(row));
  1343. rowState = startState; // UnicodeString assignment, copies contents.
  1344. }
  1345. // Run through the safe pairs, set the next state to zero when pair has been seen.
  1346. // Zero being the stop state, meaning we found a safe point.
  1347. for (int32_t pairIdx=0; pairIdx<safePairs.length(); pairIdx+=2) {
  1348. int32_t c1 = safePairs.charAt(pairIdx);
  1349. int32_t c2 = safePairs.charAt(pairIdx + 1);
  1350. UnicodeString &rowState = *static_cast<UnicodeString *>(fSafeTable->elementAt(c2 + 2));
  1351. rowState.setCharAt(c1, 0);
  1352. }
  1353. // Remove duplicate or redundant rows from the table.
  1354. IntPair states = {1, 0};
  1355. while (findDuplicateSafeState(&states)) {
  1356. // printf("Removing duplicate safe states (%d, %d)\n", states.first, states.second);
  1357. removeSafeState(states);
  1358. }
  1359. }
  1360. //-----------------------------------------------------------------------------
  1361. //
  1362. // getSafeTableSize() Calculate the size of the runtime form of this
  1363. // safe state table.
  1364. //
  1365. //-----------------------------------------------------------------------------
  1366. int32_t RBBITableBuilder::getSafeTableSize() const {
  1367. int32_t size = 0;
  1368. int32_t numRows;
  1369. int32_t numCols;
  1370. int32_t rowSize;
  1371. if (fSafeTable == nullptr) {
  1372. return 0;
  1373. }
  1374. size = offsetof(RBBIStateTable, fTableData); // The header, with no rows to the table.
  1375. numRows = fSafeTable->size();
  1376. numCols = fRB->fSetBuilder->getNumCharCategories();
  1377. if (use8BitsForSafeTable()) {
  1378. rowSize = offsetof(RBBIStateTableRow8, fNextState) + sizeof(int8_t)*numCols;
  1379. } else {
  1380. rowSize = offsetof(RBBIStateTableRow16, fNextState) + sizeof(int16_t)*numCols;
  1381. }
  1382. size += numRows * rowSize;
  1383. return size;
  1384. }
  1385. bool RBBITableBuilder::use8BitsForSafeTable() const {
  1386. return fSafeTable->size() <= kMaxStateFor8BitsTable;
  1387. }
  1388. //-----------------------------------------------------------------------------
  1389. //
  1390. // exportSafeTable() export the state transition table in the format required
  1391. // by the runtime engine. getTableSize() bytes of memory
  1392. // must be available at the output address "where".
  1393. //
  1394. //-----------------------------------------------------------------------------
  1395. void RBBITableBuilder::exportSafeTable(void *where) {
  1396. RBBIStateTable *table = (RBBIStateTable *)where;
  1397. uint32_t state;
  1398. int col;
  1399. if (U_FAILURE(*fStatus) || fSafeTable == nullptr) {
  1400. return;
  1401. }
  1402. int32_t catCount = fRB->fSetBuilder->getNumCharCategories();
  1403. if (catCount > 0x7fff ||
  1404. fSafeTable->size() > 0x7fff) {
  1405. *fStatus = U_BRK_INTERNAL_ERROR;
  1406. return;
  1407. }
  1408. table->fNumStates = fSafeTable->size();
  1409. table->fFlags = 0;
  1410. if (use8BitsForSafeTable()) {
  1411. table->fRowLen = offsetof(RBBIStateTableRow8, fNextState) + sizeof(uint8_t) * catCount;
  1412. table->fFlags |= RBBI_8BITS_ROWS;
  1413. } else {
  1414. table->fRowLen = offsetof(RBBIStateTableRow16, fNextState) + sizeof(int16_t) * catCount;
  1415. }
  1416. for (state=0; state<table->fNumStates; state++) {
  1417. UnicodeString *rowString = (UnicodeString *)fSafeTable->elementAt(state);
  1418. RBBIStateTableRow *row = (RBBIStateTableRow *)(table->fTableData + state*table->fRowLen);
  1419. if (use8BitsForSafeTable()) {
  1420. RBBIStateTableRow8 *r8 = (RBBIStateTableRow8*)row;
  1421. r8->fAccepting = 0;
  1422. r8->fLookAhead = 0;
  1423. r8->fTagsIdx = 0;
  1424. for (col=0; col<catCount; col++) {
  1425. U_ASSERT(rowString->charAt(col) <= kMaxStateFor8BitsTable);
  1426. r8->fNextState[col] = static_cast<uint8_t>(rowString->charAt(col));
  1427. }
  1428. } else {
  1429. row->r16.fAccepting = 0;
  1430. row->r16.fLookAhead = 0;
  1431. row->r16.fTagsIdx = 0;
  1432. for (col=0; col<catCount; col++) {
  1433. row->r16.fNextState[col] = rowString->charAt(col);
  1434. }
  1435. }
  1436. }
  1437. }
  1438. //-----------------------------------------------------------------------------
  1439. //
  1440. // printSet Debug function. Print the contents of a UVector
  1441. //
  1442. //-----------------------------------------------------------------------------
  1443. #ifdef RBBI_DEBUG
  1444. void RBBITableBuilder::printSet(UVector *s) {
  1445. int32_t i;
  1446. for (i=0; i<s->size(); i++) {
  1447. const RBBINode *v = static_cast<const RBBINode *>(s->elementAt(i));
  1448. RBBIDebugPrintf("%5d", v==nullptr? -1 : v->fSerialNum);
  1449. }
  1450. RBBIDebugPrintf("\n");
  1451. }
  1452. #endif
  1453. //-----------------------------------------------------------------------------
  1454. //
  1455. // printStates Debug Function. Dump the fully constructed state transition table.
  1456. //
  1457. //-----------------------------------------------------------------------------
  1458. #ifdef RBBI_DEBUG
  1459. void RBBITableBuilder::printStates() {
  1460. int c; // input "character"
  1461. int n; // state number
  1462. RBBIDebugPrintf("state | i n p u t s y m b o l s \n");
  1463. RBBIDebugPrintf(" | Acc LA Tag");
  1464. for (c=0; c<fRB->fSetBuilder->getNumCharCategories(); c++) {
  1465. RBBIDebugPrintf(" %3d", c);
  1466. }
  1467. RBBIDebugPrintf("\n");
  1468. RBBIDebugPrintf(" |---------------");
  1469. for (c=0; c<fRB->fSetBuilder->getNumCharCategories(); c++) {
  1470. RBBIDebugPrintf("----");
  1471. }
  1472. RBBIDebugPrintf("\n");
  1473. for (n=0; n<fDStates->size(); n++) {
  1474. RBBIStateDescriptor *sd = (RBBIStateDescriptor *)fDStates->elementAt(n);
  1475. RBBIDebugPrintf(" %3d | " , n);
  1476. RBBIDebugPrintf("%3d %3d %5d ", sd->fAccepting, sd->fLookAhead, sd->fTagsIdx);
  1477. for (c=0; c<fRB->fSetBuilder->getNumCharCategories(); c++) {
  1478. RBBIDebugPrintf(" %3d", sd->fDtran->elementAti(c));
  1479. }
  1480. RBBIDebugPrintf("\n");
  1481. }
  1482. RBBIDebugPrintf("\n\n");
  1483. }
  1484. #endif
  1485. //-----------------------------------------------------------------------------
  1486. //
  1487. // printSafeTable Debug Function. Dump the fully constructed safe table.
  1488. //
  1489. //-----------------------------------------------------------------------------
  1490. #ifdef RBBI_DEBUG
  1491. void RBBITableBuilder::printReverseTable() {
  1492. int c; // input "character"
  1493. int n; // state number
  1494. RBBIDebugPrintf(" Safe Reverse Table \n");
  1495. if (fSafeTable == nullptr) {
  1496. RBBIDebugPrintf(" --- nullptr ---\n");
  1497. return;
  1498. }
  1499. RBBIDebugPrintf("state | i n p u t s y m b o l s \n");
  1500. RBBIDebugPrintf(" | Acc LA Tag");
  1501. for (c=0; c<fRB->fSetBuilder->getNumCharCategories(); c++) {
  1502. RBBIDebugPrintf(" %2d", c);
  1503. }
  1504. RBBIDebugPrintf("\n");
  1505. RBBIDebugPrintf(" |---------------");
  1506. for (c=0; c<fRB->fSetBuilder->getNumCharCategories(); c++) {
  1507. RBBIDebugPrintf("---");
  1508. }
  1509. RBBIDebugPrintf("\n");
  1510. for (n=0; n<fSafeTable->size(); n++) {
  1511. UnicodeString *rowString = (UnicodeString *)fSafeTable->elementAt(n);
  1512. RBBIDebugPrintf(" %3d | " , n);
  1513. RBBIDebugPrintf("%3d %3d %5d ", 0, 0, 0); // Accepting, LookAhead, Tags
  1514. for (c=0; c<fRB->fSetBuilder->getNumCharCategories(); c++) {
  1515. RBBIDebugPrintf(" %2d", rowString->charAt(c));
  1516. }
  1517. RBBIDebugPrintf("\n");
  1518. }
  1519. RBBIDebugPrintf("\n\n");
  1520. }
  1521. #endif
  1522. //-----------------------------------------------------------------------------
  1523. //
  1524. // printRuleStatusTable Debug Function. Dump the common rule status table
  1525. //
  1526. //-----------------------------------------------------------------------------
  1527. #ifdef RBBI_DEBUG
  1528. void RBBITableBuilder::printRuleStatusTable() {
  1529. int32_t thisRecord = 0;
  1530. int32_t nextRecord = 0;
  1531. int i;
  1532. UVector *tbl = fRB->fRuleStatusVals;
  1533. RBBIDebugPrintf("index | tags \n");
  1534. RBBIDebugPrintf("-------------------\n");
  1535. while (nextRecord < tbl->size()) {
  1536. thisRecord = nextRecord;
  1537. nextRecord = thisRecord + tbl->elementAti(thisRecord) + 1;
  1538. RBBIDebugPrintf("%4d ", thisRecord);
  1539. for (i=thisRecord+1; i<nextRecord; i++) {
  1540. RBBIDebugPrintf(" %5d", tbl->elementAti(i));
  1541. }
  1542. RBBIDebugPrintf("\n");
  1543. }
  1544. RBBIDebugPrintf("\n\n");
  1545. }
  1546. #endif
  1547. //-----------------------------------------------------------------------------
  1548. //
  1549. // RBBIStateDescriptor Methods. This is a very struct-like class
  1550. // Most access is directly to the fields.
  1551. //
  1552. //-----------------------------------------------------------------------------
  1553. RBBIStateDescriptor::RBBIStateDescriptor(int lastInputSymbol, UErrorCode *fStatus) {
  1554. fMarked = false;
  1555. fAccepting = 0;
  1556. fLookAhead = 0;
  1557. fTagsIdx = 0;
  1558. fTagVals = nullptr;
  1559. fPositions = nullptr;
  1560. fDtran = nullptr;
  1561. fDtran = new UVector32(lastInputSymbol+1, *fStatus);
  1562. if (U_FAILURE(*fStatus)) {
  1563. return;
  1564. }
  1565. if (fDtran == nullptr) {
  1566. *fStatus = U_MEMORY_ALLOCATION_ERROR;
  1567. return;
  1568. }
  1569. fDtran->setSize(lastInputSymbol+1); // fDtran needs to be pre-sized.
  1570. // It is indexed by input symbols, and will
  1571. // hold the next state number for each
  1572. // symbol.
  1573. }
  1574. RBBIStateDescriptor::~RBBIStateDescriptor() {
  1575. delete fPositions;
  1576. delete fDtran;
  1577. delete fTagVals;
  1578. fPositions = nullptr;
  1579. fDtran = nullptr;
  1580. fTagVals = nullptr;
  1581. }
  1582. U_NAMESPACE_END
  1583. #endif /* #if !UCONFIG_NO_BREAK_ITERATION */