lr0.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138
  1. /*++
  2. Copyright (c) 2016 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. lr0.c
  9. Abstract:
  10. This module implements support for generating an LR(0) grammar from a
  11. description of productions.
  12. Author:
  13. Evan Green 9-Apr-2016
  14. Environment:
  15. Build
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "yygenp.h"
  21. #include <assert.h>
  22. #include <string.h>
  23. //
  24. // ---------------------------------------------------------------- Definitions
  25. //
  26. //
  27. // ------------------------------------------------------ Data Type Definitions
  28. //
  29. /*++
  30. Structure Description:
  31. This structure contains the working state for the LR(0) state generator.
  32. Members:
  33. StateSet - Stores the hash table of states, based on the item index of
  34. their first right hand side.
  35. ShiftSet - Stores the set of states to shift to for each shift symbol.
  36. ShiftSymbol - Stores the array of possible shift symbols out of the
  37. current state.
  38. ReduceSet - Stores the set of reductions being built for the current state.
  39. KernelBase - Stores an array of arrays of item indices, indexed by shift
  40. symbol. For the currently operated on state, if symbol I were shifted,
  41. what new item sets would be in the kernel. The kernel is the part of
  42. a state added by the grammar (or previous state), rather than the
  43. closure.
  44. KernelEnd - Stores an array indicating the end of the kernel base arrays,
  45. again indexed by shift symbol.
  46. KernelItems - Stores a big flattened array of all the kernel item sets.
  47. This is the storage area for kernel base.
  48. LastState - Stores a pointer to the last LR(0) state processed.
  49. CurrentState - Stores a pointer to the current LR(0) state being operated
  50. on.
  51. ShiftCount - Stores the number of shifts.
  52. --*/
  53. typedef struct _YYGEN_STATE_CONTEXT {
  54. PYYGEN_STATE *StateSet;
  55. PYY_STATE_INDEX ShiftSet;
  56. PYY_VALUE ShiftSymbol;
  57. PYY_RULE_INDEX ReduceSet;
  58. PYY_ITEM_INDEX *KernelBase;
  59. PYY_ITEM_INDEX *KernelEnd;
  60. PYY_ITEM_INDEX KernelItems;
  61. PYYGEN_STATE LastState;
  62. PYYGEN_STATE CurrentState;
  63. YY_VALUE ShiftCount;
  64. } YYGEN_STATE_CONTEXT, *PYYGEN_STATE_CONTEXT;
  65. //
  66. // ----------------------------------------------- Internal Function Prototypes
  67. //
  68. YY_STATUS
  69. YypGenerateDerives (
  70. PYYGEN_CONTEXT Context
  71. );
  72. YY_STATUS
  73. YypGenerateNullable (
  74. PYYGEN_CONTEXT Context
  75. );
  76. YY_STATUS
  77. YypGenerateStates (
  78. PYYGEN_CONTEXT Context
  79. );
  80. YY_STATUS
  81. YypInitializeStateContext (
  82. PYYGEN_CONTEXT Context,
  83. PYYGEN_STATE_CONTEXT StateContext
  84. );
  85. VOID
  86. YypDestroyStateContext (
  87. PYYGEN_CONTEXT Context,
  88. PYYGEN_STATE_CONTEXT StateContext
  89. );
  90. YY_STATUS
  91. YypGenerateFirstDerives (
  92. PYYGEN_CONTEXT Context
  93. );
  94. PULONG
  95. YypGenerateEpsilonFreeFirstSet (
  96. PYYGEN_CONTEXT Context
  97. );
  98. VOID
  99. YypGenerateReflexiveTransitiveClosure (
  100. PULONG Bitmap,
  101. ULONG BitCount
  102. );
  103. VOID
  104. YypGenerateTransitiveClosure (
  105. PULONG Bitmap,
  106. ULONG BitCount
  107. );
  108. YY_STATUS
  109. YypInitializeStates (
  110. PYYGEN_CONTEXT Context,
  111. PYYGEN_STATE_CONTEXT StateContext
  112. );
  113. YY_STATUS
  114. YypSaveReductions (
  115. PYYGEN_CONTEXT Context,
  116. PYYGEN_STATE_CONTEXT StateContext
  117. );
  118. VOID
  119. YypAdvanceItemSets (
  120. PYYGEN_CONTEXT Context,
  121. PYYGEN_STATE_CONTEXT StateContext
  122. );
  123. VOID
  124. YypAddNewStates (
  125. PYYGEN_CONTEXT Context,
  126. PYYGEN_STATE_CONTEXT StateContext
  127. );
  128. YY_STATE_INDEX
  129. YypGetState (
  130. PYYGEN_CONTEXT Context,
  131. PYYGEN_STATE_CONTEXT StateContext,
  132. YY_VALUE Symbol
  133. );
  134. PYYGEN_STATE
  135. YypCreateState (
  136. PYYGEN_CONTEXT Context,
  137. PYYGEN_STATE_CONTEXT StateContext,
  138. YY_VALUE Symbol
  139. );
  140. YY_STATUS
  141. YypSaveShifts (
  142. PYYGEN_CONTEXT Context,
  143. PYYGEN_STATE_CONTEXT StateContext
  144. );
  145. VOID
  146. YypPrintItems (
  147. PYYGEN_CONTEXT Context
  148. );
  149. VOID
  150. YypPrintDerives (
  151. PYYGEN_CONTEXT Context
  152. );
  153. VOID
  154. YypPrintEpsilonFreeFirsts (
  155. PYYGEN_CONTEXT Context,
  156. PULONG EpsilonFreeFirsts
  157. );
  158. VOID
  159. YypPrintFirstDerives (
  160. PYYGEN_CONTEXT Context
  161. );
  162. VOID
  163. YypPrintClosure (
  164. PYYGEN_CONTEXT Context,
  165. YY_VALUE ItemsCount
  166. );
  167. //
  168. // -------------------------------------------------------------------- Globals
  169. //
  170. //
  171. // ------------------------------------------------------------------ Functions
  172. //
  173. YY_STATUS
  174. YypGenerateLr0Grammar (
  175. PYYGEN_CONTEXT Context
  176. )
  177. /*++
  178. Routine Description:
  179. This routine generates an LR(0) grammar based on the description.
  180. Arguments:
  181. Context - Supplies a pointer to the generator context.
  182. Return Value:
  183. YY status.
  184. --*/
  185. {
  186. YY_STATUS YyStatus;
  187. YyStatus = YypGenerateDerives(Context);
  188. if (YyStatus != YyStatusSuccess) {
  189. goto GenerateLr0GrammarEnd;
  190. }
  191. YyStatus = YypGenerateNullable(Context);
  192. if (YyStatus != YyStatusSuccess) {
  193. goto GenerateLr0GrammarEnd;
  194. }
  195. YyStatus = YypGenerateStates(Context);
  196. if (YyStatus != YyStatusSuccess) {
  197. goto GenerateLr0GrammarEnd;
  198. }
  199. GenerateLr0GrammarEnd:
  200. return YyStatus;
  201. }
  202. VOID
  203. YypEstablishClosure (
  204. PYYGEN_CONTEXT Context,
  205. PYYGEN_STATE State
  206. )
  207. /*++
  208. Routine Description:
  209. This routine creates a closure on the itemset of the current state.
  210. Arguments:
  211. Context - Supplies a pointer to the generator context.
  212. State - Supplies a pointer to the state to create the closure of.
  213. Return Value:
  214. None.
  215. --*/
  216. {
  217. ULONG BitIndex;
  218. PULONG CurrentRuleSet;
  219. ULONG CurrentWord;
  220. PULONG FirstDerives;
  221. YY_ITEM_INDEX ItemIndex;
  222. PYY_ITEM_INDEX ItemsPointer;
  223. PYY_ITEM_INDEX Nucleus;
  224. ULONG NucleusCount;
  225. PYY_ITEM_INDEX NucleusEnd;
  226. YY_RULE_INDEX RuleNumber;
  227. PULONG RuleSetEnd;
  228. ULONG RuleSetSize;
  229. YY_VALUE StartSymbol;
  230. YY_VALUE Symbol;
  231. Nucleus = State->Items;
  232. NucleusCount = State->ItemsCount;
  233. NucleusEnd = Nucleus + NucleusCount;
  234. RuleSetSize = YYGEN_BITMAP_WORD_COUNT(Context->RuleCount);
  235. RuleSetEnd = Context->RuleSet + RuleSetSize;
  236. StartSymbol = Context->StartSymbol;
  237. CurrentRuleSet = Context->RuleSet;
  238. while (CurrentRuleSet < RuleSetEnd) {
  239. *CurrentRuleSet = 0;
  240. CurrentRuleSet += 1;
  241. }
  242. //
  243. // Loop through all the right hand sides. OR into the ruleset all of the
  244. // first derives from the first element if it's a non-terminal.
  245. //
  246. ItemsPointer = Nucleus;
  247. while (ItemsPointer < NucleusEnd) {
  248. Symbol = Context->Items[*ItemsPointer];
  249. if (Symbol >= Context->TokenCount) {
  250. FirstDerives = Context->FirstDerives +
  251. ((Symbol - StartSymbol) * RuleSetSize);
  252. CurrentRuleSet = Context->RuleSet;
  253. while (CurrentRuleSet < RuleSetEnd) {
  254. *CurrentRuleSet |= *FirstDerives;
  255. CurrentRuleSet += 1;
  256. FirstDerives += 1;
  257. }
  258. }
  259. ItemsPointer += 1;
  260. }
  261. //
  262. // Merge the itemsets from the rules indicated by the ruleset into the
  263. // nucleus, keeping them in global item array order and avoiding duplicates.
  264. //
  265. RuleNumber = 0;
  266. Context->ItemSetEnd = Context->ItemSet;
  267. ItemsPointer = Nucleus;
  268. CurrentRuleSet = Context->RuleSet;
  269. while (CurrentRuleSet < RuleSetEnd) {
  270. CurrentWord = *CurrentRuleSet;
  271. if (CurrentWord != 0) {
  272. for (BitIndex = 0; BitIndex < YYGEN_BITS_PER_WORD; BitIndex += 1) {
  273. if ((CurrentWord & (1 << BitIndex)) != 0) {
  274. ItemIndex = Context->Rules[RuleNumber + BitIndex].RightSide;
  275. while ((ItemsPointer < NucleusEnd) &&
  276. (*ItemsPointer < ItemIndex)) {
  277. *(Context->ItemSetEnd) = *ItemsPointer;
  278. Context->ItemSetEnd += 1;
  279. ItemsPointer += 1;
  280. }
  281. *(Context->ItemSetEnd) = ItemIndex;
  282. Context->ItemSetEnd += 1;
  283. while ((ItemsPointer < NucleusEnd) &&
  284. (*ItemsPointer == ItemIndex)) {
  285. ItemsPointer += 1;
  286. }
  287. }
  288. }
  289. }
  290. RuleNumber += YYGEN_BITS_PER_WORD;
  291. CurrentRuleSet += 1;
  292. }
  293. while (ItemsPointer < NucleusEnd) {
  294. *(Context->ItemSetEnd) = *ItemsPointer;
  295. Context->ItemSetEnd += 1;
  296. ItemsPointer += 1;
  297. }
  298. if ((Context->Flags & YYGEN_FLAG_DEBUG) != 0) {
  299. YypPrintClosure(Context, State->ItemsCount);
  300. }
  301. return;
  302. }
  303. //
  304. // --------------------------------------------------------- Internal Functions
  305. //
  306. YY_STATUS
  307. YypGenerateDerives (
  308. PYYGEN_CONTEXT Context
  309. )
  310. /*++
  311. Routine Description:
  312. This routine generates the derives array, which is an array of unique rules
  313. and points to runs of rules.
  314. Arguments:
  315. Context - Supplies a pointer to the generator context.
  316. Return Value:
  317. YY status.
  318. --*/
  319. {
  320. PYY_VALUE Components;
  321. PYYGEN_RULE CurrentRule;
  322. PYY_RULE_INDEX Derives;
  323. ULONG Flags;
  324. YY_ITEM_INDEX ItemIndex;
  325. PYY_VALUE Items;
  326. YY_VALUE LastTerminal;
  327. YY_VALUE LeftSide;
  328. YY_RULE_INDEX RuleIndex;
  329. PYYGEN_RULE Rules;
  330. YY_STATUS YyStatus;
  331. YyStatus = YyStatusNoMemory;
  332. Derives = YypAllocate(Context->SymbolCount * sizeof(YY_RULE_INDEX));
  333. if (Derives == NULL) {
  334. goto GenerateDerivesEnd;
  335. }
  336. Context->Derives = Derives;
  337. //
  338. // There's an extra rule on the end to terminate the last run of
  339. // rules while iterating.
  340. //
  341. Rules = YypAllocate(sizeof(YYGEN_RULE) * (Context->RuleCount + 1));
  342. if (Rules == NULL) {
  343. YyStatus = YyStatusNoMemory;
  344. goto GenerateDerivesEnd;
  345. }
  346. Context->Rules = Rules;
  347. Items = YypAllocate(sizeof(YY_VALUE) * Context->ItemCount);
  348. if (Items == NULL) {
  349. YyStatus = YyStatusNoMemory;
  350. goto GenerateDerivesEnd;
  351. }
  352. Context->Items = Items;
  353. //
  354. // The first item corresponds to rule 1 and it's empty.
  355. //
  356. Items[0] = -1;
  357. //
  358. // The next three items correspond to the right hand side of the start
  359. // rule, which is to produce the production marked start and then EOF.
  360. //
  361. Items[1] = Context->StartSymbol;
  362. Context->StartSymbol = Context->TokenCount;
  363. Items[2] = 0;
  364. Items[3] = -2;
  365. ItemIndex = 4;
  366. //
  367. // The first rule is invalid since it cannot be negated.
  368. // The second rule is empty.
  369. // The third rule is the start rule.
  370. //
  371. CurrentRule = Rules + 2;
  372. CurrentRule->LeftSide = Context->StartSymbol;
  373. CurrentRule->RightSide = 1;
  374. Derives[Context->StartSymbol] = 2;
  375. CurrentRule += 1;
  376. RuleIndex = 3;
  377. //
  378. // Loop over converting productions to derives + rules.
  379. //
  380. for (LeftSide = Context->StartSymbol + 1;
  381. LeftSide < Context->SymbolCount;
  382. LeftSide += 1) {
  383. Components = Context->Elements[LeftSide].Components;
  384. Derives[LeftSide] = RuleIndex;
  385. assert((Components != NULL) && (*Components >= 0));
  386. while (*Components != 0) {
  387. CurrentRule->LeftSide = LeftSide;
  388. CurrentRule->RightSide = ItemIndex;
  389. LastTerminal = -1;
  390. while (*Components > 0) {
  391. Items[ItemIndex] = *Components;
  392. //
  393. // Keep track of the last terminal specified in the rule.
  394. //
  395. if (*Components < Context->TokenCount) {
  396. LastTerminal = *Components;
  397. }
  398. Components += 1;
  399. ItemIndex += 1;
  400. }
  401. Items[ItemIndex] = -RuleIndex;
  402. ItemIndex += 1;
  403. //
  404. // The precedence for the rule is specified in the terminator. -1
  405. // corresponds to precedence 0 (none). If no precedence or
  406. // associativity is describe for the rule, then it is taken from
  407. // the last terminal in the rule.
  408. //
  409. assert(*Components != 0);
  410. CurrentRule->Precedence = -(*Components) - 1;
  411. if ((CurrentRule->Precedence == 0) && (LastTerminal > 0)) {
  412. CurrentRule->Precedence =
  413. Context->Elements[LastTerminal].Precedence;
  414. }
  415. Flags = Context->Elements[LeftSide].Flags;
  416. if (Flags == 0) {
  417. Flags = Context->Elements[LastTerminal].Flags;
  418. }
  419. if (Flags != 0) {
  420. if ((Flags & YY_ELEMENT_LEFT_ASSOCIATIVE) != 0) {
  421. CurrentRule->Associativity = YyLeftAssociative;
  422. } else if ((Flags & YY_ELEMENT_RIGHT_ASSOCIATIVE) != 0) {
  423. CurrentRule->Associativity = YyRightAssociative;
  424. } else if ((Flags & YY_ELEMENT_NON_ASSOCIATIVE) != 0) {
  425. CurrentRule->Associativity = YyNonAssociative;
  426. }
  427. }
  428. Components += 1;
  429. CurrentRule += 1;
  430. RuleIndex += 1;
  431. }
  432. }
  433. assert(Rules + Context->RuleCount == CurrentRule);
  434. CurrentRule->LeftSide = 0;
  435. CurrentRule->RightSide = ItemIndex;
  436. if ((Context->Flags & YYGEN_FLAG_DEBUG) != 0) {
  437. YypPrintItems(Context);
  438. YypPrintDerives(Context);
  439. }
  440. YyStatus = YyStatusSuccess;
  441. GenerateDerivesEnd:
  442. return YyStatus;
  443. }
  444. YY_STATUS
  445. YypGenerateNullable (
  446. PYYGEN_CONTEXT Context
  447. )
  448. /*++
  449. Routine Description:
  450. This routine generates the array of booleans indicating which rules are
  451. empty or are made up of other rules that are empty.
  452. Arguments:
  453. Context - Supplies a pointer to the generator context.
  454. Return Value:
  455. YY status.
  456. --*/
  457. {
  458. BOOL Empty;
  459. BOOL FoundOne;
  460. YY_ITEM_INDEX ItemIndex;
  461. YY_VALUE LeftSide;
  462. PBOOL Nullable;
  463. YY_RULE_INDEX RuleIndex;
  464. YY_ITEM_INDEX Search;
  465. Nullable = YypAllocate(Context->SymbolCount * sizeof(BOOL));
  466. if (Nullable == NULL) {
  467. return YyStatusNoMemory;
  468. }
  469. //
  470. // The idea is to find which productions are empty, then go back and mark
  471. // any productions that are just made up of those productions as empty also,
  472. // and so on, until no new empty ones are found.
  473. //
  474. do {
  475. FoundOne = FALSE;
  476. for (ItemIndex = 1; ItemIndex < Context->ItemCount; ItemIndex += 1) {
  477. Empty = TRUE;
  478. //
  479. // Loop over each element in the rule. If it consists of something
  480. // that's not nullable (including a token), then it's also not
  481. // nullable.
  482. //
  483. Search = Context->Items[ItemIndex];
  484. while (Search >= 0) {
  485. if (Nullable[Search] == FALSE) {
  486. Empty = FALSE;
  487. }
  488. ItemIndex += 1;
  489. Search = Context->Items[ItemIndex];
  490. }
  491. //
  492. // If it's empty or is only made up of other things that are
  493. // empty, mark it as nullable. This means everything will have
  494. // to be checked again.
  495. //
  496. if (Empty != FALSE) {
  497. RuleIndex = -Search;
  498. LeftSide = Context->Rules[RuleIndex].LeftSide;
  499. if (Nullable[LeftSide] == FALSE) {
  500. Nullable[LeftSide] = TRUE;
  501. FoundOne = TRUE;
  502. }
  503. }
  504. }
  505. } while (FoundOne != FALSE);
  506. if ((Context->Flags & YYGEN_FLAG_DEBUG) != 0) {
  507. for (ItemIndex = 0; ItemIndex < Context->SymbolCount; ItemIndex += 1) {
  508. if (Nullable[ItemIndex] != FALSE) {
  509. printf("%s is nullable\n", Context->Elements[ItemIndex].Name);
  510. } else {
  511. printf("%s is not nullable\n",
  512. Context->Elements[ItemIndex].Name);
  513. }
  514. }
  515. }
  516. Context->Nullable = Nullable;
  517. return YyStatusSuccess;
  518. }
  519. YY_STATUS
  520. YypGenerateStates (
  521. PYYGEN_CONTEXT Context
  522. )
  523. /*++
  524. Routine Description:
  525. This routine generates the LR(0) grammar states.
  526. Arguments:
  527. Context - Supplies a pointer to the generator context.
  528. Return Value:
  529. YY status.
  530. --*/
  531. {
  532. UINTN AllocationSize;
  533. YYGEN_STATE_CONTEXT StateContext;
  534. YY_STATUS YyStatus;
  535. memset(&StateContext, 0, sizeof(YYGEN_STATE_CONTEXT));
  536. YyStatus = YypInitializeStateContext(Context, &StateContext);
  537. if (YyStatus != YyStatusSuccess) {
  538. goto GenerateStatesEnd;
  539. }
  540. Context->ItemSet = YypAllocate(Context->ItemCount * sizeof(YY_VALUE));
  541. if (Context->ItemSet == NULL) {
  542. YyStatus = YyStatusNoMemory;
  543. goto GenerateStatesEnd;
  544. }
  545. AllocationSize = YYGEN_BITMAP_WORD_COUNT(Context->RuleCount) *
  546. sizeof(ULONG);
  547. Context->RuleSet = YypAllocate(AllocationSize);
  548. if (Context->RuleSet == NULL) {
  549. YyStatus = YyStatusNoMemory;
  550. goto GenerateStatesEnd;
  551. }
  552. YyStatus = YypGenerateFirstDerives(Context);
  553. if (YyStatus != YyStatusSuccess) {
  554. goto GenerateStatesEnd;
  555. }
  556. YyStatus = YypInitializeStates(Context, &StateContext);
  557. if (YyStatus != YyStatusSuccess) {
  558. goto GenerateStatesEnd;
  559. }
  560. while (StateContext.CurrentState != NULL) {
  561. if ((Context->Flags & YYGEN_FLAG_DEBUG) != 0) {
  562. printf("State %d:\n", StateContext.CurrentState->Number);
  563. }
  564. YypEstablishClosure(Context, StateContext.CurrentState);
  565. YypSaveReductions(Context, &StateContext);
  566. YypAdvanceItemSets(Context, &StateContext);
  567. YypAddNewStates(Context, &StateContext);
  568. if (StateContext.ShiftCount != 0) {
  569. YypSaveShifts(Context, &StateContext);
  570. }
  571. StateContext.CurrentState = StateContext.CurrentState->Next;
  572. }
  573. YyStatus = YyStatusSuccess;
  574. GenerateStatesEnd:
  575. YypDestroyStateContext(Context, &StateContext);
  576. return YyStatus;
  577. }
  578. YY_STATUS
  579. YypInitializeStateContext (
  580. PYYGEN_CONTEXT Context,
  581. PYYGEN_STATE_CONTEXT StateContext
  582. )
  583. /*++
  584. Routine Description:
  585. This routine allocates arrays needed for LR(0) state generation.
  586. Arguments:
  587. Context - Supplies a pointer to the generator context.
  588. StateContext - Supplies a pointer to the zeroed out state context.
  589. Return Value:
  590. YY status.
  591. --*/
  592. {
  593. YY_VALUE Count;
  594. PYY_VALUE End;
  595. PYY_VALUE Item;
  596. YY_VALUE Symbol;
  597. PYY_VALUE SymbolCounts;
  598. YY_STATUS YyStatus;
  599. YyStatus = YyStatusNoMemory;
  600. SymbolCounts = YypAllocate(Context->SymbolCount * sizeof(YY_VALUE));
  601. if (SymbolCounts == NULL) {
  602. goto InitializeStateContextEnd;
  603. }
  604. //
  605. // Count the number of times a symbol is referenced, and the total number
  606. // of symbols in all the rules.
  607. //
  608. End = Context->Items + Context->ItemCount;
  609. Count = 0;
  610. Item = Context->Items;
  611. while (Item < End) {
  612. Symbol = *Item;
  613. if (Symbol >= 0) {
  614. Count += 1;
  615. SymbolCounts[Symbol] += 1;
  616. }
  617. Item += 1;
  618. }
  619. //
  620. // Allocate the kernel base and kernel item arrays.
  621. //
  622. StateContext->KernelBase =
  623. YypAllocate(Context->SymbolCount * sizeof(PYY_ITEM_INDEX));
  624. if (StateContext->KernelBase == NULL) {
  625. goto InitializeStateContextEnd;
  626. }
  627. StateContext->KernelEnd =
  628. YypAllocate(Context->SymbolCount * sizeof(PYY_ITEM_INDEX));
  629. if (StateContext->KernelEnd == NULL) {
  630. goto InitializeStateContextEnd;
  631. }
  632. StateContext->KernelItems = YypAllocate(Count * sizeof(YY_ITEM_INDEX));
  633. if (StateContext->KernelItems == NULL) {
  634. goto InitializeStateContextEnd;
  635. }
  636. //
  637. // Initialize the indices for ther kernel base array, knowing how large
  638. // each kernel base array will be but not initializing it yet.
  639. //
  640. Count = 0;
  641. for (Symbol = 0; Symbol < Context->SymbolCount; Symbol += 1) {
  642. StateContext->KernelBase[Symbol] = StateContext->KernelItems + Count;
  643. Count += SymbolCounts[Symbol];
  644. }
  645. StateContext->ShiftSymbol = SymbolCounts;
  646. SymbolCounts = NULL;
  647. StateContext->ShiftSet =
  648. YypAllocate(Context->SymbolCount * sizeof(YY_STATE_INDEX));
  649. if (StateContext->ShiftSet == NULL) {
  650. goto InitializeStateContextEnd;
  651. }
  652. StateContext->ReduceSet =
  653. YypAllocate((Context->SymbolCount + 1) * sizeof(YY_RULE_INDEX));
  654. if (StateContext->ReduceSet == NULL) {
  655. goto InitializeStateContextEnd;
  656. }
  657. StateContext->StateSet =
  658. YypAllocate(Context->ItemCount * sizeof(PYYGEN_STATE));
  659. if (StateContext->StateSet == NULL) {
  660. goto InitializeStateContextEnd;
  661. }
  662. YyStatus = YyStatusSuccess;
  663. InitializeStateContextEnd:
  664. if (SymbolCounts != NULL) {
  665. YypFree(SymbolCounts);
  666. }
  667. return YyStatus;
  668. }
  669. VOID
  670. YypDestroyStateContext (
  671. PYYGEN_CONTEXT Context,
  672. PYYGEN_STATE_CONTEXT StateContext
  673. )
  674. /*++
  675. Routine Description:
  676. This routine frees memory allocated in the given state context.
  677. Arguments:
  678. Context - Supplies a pointer to the application context.
  679. StateContext - Supplies a pointer to the state context.
  680. Return Value:
  681. None.
  682. --*/
  683. {
  684. if (StateContext->StateSet != NULL) {
  685. YypFree(StateContext->StateSet);
  686. }
  687. if (StateContext->ShiftSet != NULL) {
  688. YypFree(StateContext->ShiftSet);
  689. }
  690. if (StateContext->ReduceSet != NULL) {
  691. YypFree(StateContext->ReduceSet);
  692. }
  693. if (StateContext->ShiftSymbol != NULL) {
  694. YypFree(StateContext->ShiftSymbol);
  695. }
  696. if (StateContext->KernelBase != NULL) {
  697. YypFree(StateContext->KernelBase);
  698. }
  699. if (StateContext->KernelEnd != NULL) {
  700. YypFree(StateContext->KernelEnd);
  701. }
  702. if (StateContext->KernelItems != NULL) {
  703. YypFree(StateContext->KernelItems);
  704. }
  705. return;
  706. }
  707. YY_STATUS
  708. YypGenerateFirstDerives (
  709. PYYGEN_CONTEXT Context
  710. )
  711. /*++
  712. Routine Description:
  713. This routine creates the array of FIRST bitmaps, indicating which rules are
  714. involved in the FIRST set of each non-terminal. The FIRST set is the set
  715. of terminals that can appear first in a given itemset.
  716. Arguments:
  717. Context - Supplies a pointer to the generator context.
  718. Return Value:
  719. YY status.
  720. --*/
  721. {
  722. ULONG BitIndex;
  723. ULONG CurrentWord;
  724. PULONG EffRow;
  725. PULONG EpsilonFreeFirsts;
  726. PULONG FirstRow;
  727. YY_VALUE LeftSide;
  728. ULONG NonTerminalSetSize;
  729. YY_VALUE RowIndex;
  730. PYYGEN_RULE Rule;
  731. YY_RULE_INDEX RuleIndex;
  732. ULONG RuleSetSize;
  733. YY_VALUE StartSymbol;
  734. YY_VALUE SymbolIndex;
  735. YY_STATUS YyStatus;
  736. EpsilonFreeFirsts = NULL;
  737. RuleSetSize = YYGEN_BITMAP_WORD_COUNT(Context->RuleCount);
  738. NonTerminalSetSize = YYGEN_BITMAP_WORD_COUNT(Context->NonTerminalCount);
  739. StartSymbol = Context->StartSymbol;
  740. YyStatus = YyStatusNoMemory;
  741. Context->FirstDerives =
  742. YypAllocate(Context->NonTerminalCount * (RuleSetSize * sizeof(ULONG)));
  743. if (Context->FirstDerives == NULL) {
  744. goto GenerateFirstSetEnd;
  745. }
  746. //
  747. // Get the closure of first non-terminals for each non-terminal.
  748. //
  749. EpsilonFreeFirsts = YypGenerateEpsilonFreeFirstSet(Context);
  750. if (EpsilonFreeFirsts == NULL) {
  751. goto GenerateFirstSetEnd;
  752. }
  753. //
  754. // Loop through each row (non-terminal) of the first set.
  755. //
  756. FirstRow = Context->FirstDerives;
  757. for (RowIndex = StartSymbol;
  758. RowIndex < Context->SymbolCount;
  759. RowIndex += 1) {
  760. //
  761. // Get the equivalent row in the EFF bitmap.
  762. //
  763. EffRow = EpsilonFreeFirsts +
  764. ((RowIndex - StartSymbol) * NonTerminalSetSize);
  765. BitIndex = 0;
  766. CurrentWord = *EffRow;
  767. //
  768. // Loop over every bit in the bitmap.
  769. //
  770. for (SymbolIndex = StartSymbol;
  771. SymbolIndex < Context->SymbolCount;
  772. SymbolIndex += 1) {
  773. //
  774. // If the bit is set in the EFF bitmap, then set the bits for all
  775. // of that non-terminal's rules.
  776. //
  777. if ((CurrentWord & (1 << BitIndex)) != 0) {
  778. RuleIndex = Context->Derives[SymbolIndex];
  779. assert(RuleIndex >= 0);
  780. Rule = &(Context->Rules[RuleIndex]);
  781. LeftSide = Rule->LeftSide;
  782. do {
  783. YYGEN_BITMAP_SET(FirstRow, RuleIndex);
  784. Rule += 1;
  785. RuleIndex += 1;
  786. } while (Rule->LeftSide == LeftSide);
  787. }
  788. BitIndex += 1;
  789. if (BitIndex == YYGEN_BITS_PER_WORD) {
  790. BitIndex = 0;
  791. EffRow += 1;
  792. CurrentWord = *EffRow;
  793. }
  794. }
  795. FirstRow += RuleSetSize;
  796. }
  797. if ((Context->Flags & YYGEN_FLAG_DEBUG) != 0) {
  798. YypPrintFirstDerives(Context);
  799. }
  800. YyStatus = YyStatusSuccess;
  801. GenerateFirstSetEnd:
  802. if (EpsilonFreeFirsts != NULL) {
  803. YypFree(EpsilonFreeFirsts);
  804. }
  805. return YyStatus;
  806. }
  807. PULONG
  808. YypGenerateEpsilonFreeFirstSet (
  809. PYYGEN_CONTEXT Context
  810. )
  811. /*++
  812. Routine Description:
  813. This routine creates the grid of bits that is the Epsilon Free First set.
  814. This is for every non-terminal (row), the set of terminals that appear
  815. first in that item set. The epsilon free part means that the non-terminals
  816. that consist of the empty set are not included.
  817. Arguments:
  818. Context - Supplies a pointer to the generator context.
  819. Return Value:
  820. Returns a pointer to the 2 dimensional bitmap containing the Epsilon Free
  821. First sets.
  822. NULL on allocation failure.
  823. --*/
  824. {
  825. UINTN AllocationSize;
  826. PULONG EpsilonFreeFirsts;
  827. YY_VALUE LeftSide;
  828. PULONG Row;
  829. ULONG RowSize;
  830. PYYGEN_RULE Rule;
  831. YY_RULE_INDEX RuleIndex;
  832. YY_VALUE Symbol;
  833. YY_VALUE SymbolIndex;
  834. RowSize = YYGEN_BITMAP_WORD_COUNT(Context->NonTerminalCount);
  835. AllocationSize = Context->NonTerminalCount * RowSize * sizeof(ULONG);
  836. EpsilonFreeFirsts = YypAllocate(AllocationSize);
  837. if (EpsilonFreeFirsts == NULL) {
  838. return NULL;
  839. }
  840. Row = EpsilonFreeFirsts;
  841. //
  842. // Loop through all the productions.
  843. //
  844. for (SymbolIndex = Context->StartSymbol;
  845. SymbolIndex < Context->SymbolCount;
  846. SymbolIndex += 1) {
  847. //
  848. // Loop through each rule in this production.
  849. //
  850. RuleIndex = Context->Derives[SymbolIndex];
  851. Rule = Context->Rules + RuleIndex;
  852. LeftSide = Rule->LeftSide;
  853. do {
  854. //
  855. // If the first symbol in the right hand side is a non-terminal,
  856. // add it to the bitmap for this row.
  857. //
  858. Symbol = Context->Items[Rule->RightSide];
  859. if (Symbol >= Context->TokenCount) {
  860. Symbol -= Context->StartSymbol;
  861. YYGEN_BITMAP_SET(Row, Symbol);
  862. }
  863. Rule += 1;
  864. } while (Rule->LeftSide == LeftSide);
  865. Row += RowSize;
  866. }
  867. YypGenerateReflexiveTransitiveClosure(EpsilonFreeFirsts,
  868. Context->NonTerminalCount);
  869. if ((Context->Flags & YYGEN_FLAG_DEBUG) != 0) {
  870. YypPrintEpsilonFreeFirsts(Context, EpsilonFreeFirsts);
  871. }
  872. return EpsilonFreeFirsts;
  873. }
  874. VOID
  875. YypGenerateReflexiveTransitiveClosure (
  876. PULONG Bitmap,
  877. ULONG BitCount
  878. )
  879. /*++
  880. Routine Description:
  881. This routine generates the reflexive transitive closure of the given bitmap.
  882. This is just the transitive closure of the bitmap, but with each row's bit
  883. for itself also set.
  884. Arguments:
  885. Bitmap - Supplies a pointer to the bitmap. The reflexive transitive closure
  886. will be returned in this bitmap.
  887. BitCount - Supplies the number of bits per row (and column).
  888. Return Value:
  889. None.
  890. --*/
  891. {
  892. ULONG BitIndex;
  893. PULONG End;
  894. PULONG Row;
  895. ULONG RowSize;
  896. YypGenerateTransitiveClosure(Bitmap, BitCount);
  897. RowSize = YYGEN_BITMAP_WORD_COUNT(BitCount);
  898. End = Bitmap + (BitCount * RowSize);
  899. Row = Bitmap;
  900. BitIndex = 0;
  901. //
  902. // Mark the diagonal down the grid of bits to make the closure reflexive.
  903. //
  904. while (Row < End) {
  905. *Row |= 1 << BitIndex;
  906. BitIndex += 1;
  907. if (BitIndex == YYGEN_BITS_PER_WORD) {
  908. BitIndex = 0;
  909. Row += 1;
  910. }
  911. Row += RowSize;
  912. }
  913. return;
  914. }
  915. VOID
  916. YypGenerateTransitiveClosure (
  917. PULONG Bitmap,
  918. ULONG BitCount
  919. )
  920. /*++
  921. Routine Description:
  922. This routine generates the transitive closure of the given bitmap using
  923. Warshall's algorithm.
  924. Arguments:
  925. Bitmap - Supplies a pointer to the bitmap. The transitive closure will be
  926. returned in this bitmap.
  927. BitCount - Supplies the number of bits per row (and column).
  928. Return Value:
  929. None.
  930. --*/
  931. {
  932. ULONG BitIndex;
  933. PULONG Copy;
  934. PULONG CurrentColumn;
  935. PULONG CurrentWord;
  936. PULONG End;
  937. PULONG RowEnd;
  938. PULONG RowI;
  939. PULONG RowJ;
  940. ULONG RowSize;
  941. //
  942. // Warshall's algorithm for the transitive closure is basically this for
  943. // a grid of R[row, column]:
  944. // for i in 0..n:
  945. // for j in 0..n:
  946. // for k in 0..n:
  947. // R[j, k] |= R[j, i] && R[i, k];
  948. //
  949. RowSize = YYGEN_BITMAP_WORD_COUNT(BitCount);
  950. End = Bitmap + (BitCount * RowSize);
  951. CurrentWord = Bitmap;
  952. BitIndex = 0;
  953. RowI = Bitmap;
  954. //
  955. // Loop through one dimension of the bitmap in i. The current word and bit
  956. // index increment through the bits in that row.
  957. //
  958. while (RowI < End) {
  959. CurrentColumn = CurrentWord;
  960. RowJ = Bitmap;
  961. //
  962. // Loop j over every row in the bitmap.
  963. //
  964. while (RowJ < End) {
  965. //
  966. // Check to see if R[j, i] is set, and OR row I into row J if so.
  967. //
  968. if ((*CurrentColumn & (1 << BitIndex)) != 0) {
  969. Copy = RowI;
  970. RowEnd = RowJ + RowSize;
  971. while (RowJ < RowEnd) {
  972. *RowJ |= *Copy;
  973. RowJ += 1;
  974. Copy += 1;
  975. }
  976. } else {
  977. RowJ += RowSize;
  978. }
  979. CurrentColumn += RowSize;
  980. }
  981. BitIndex += 1;
  982. if (BitIndex == YYGEN_BITS_PER_WORD) {
  983. BitIndex = 0;
  984. CurrentWord += 1;
  985. }
  986. RowI += RowSize;
  987. }
  988. return;
  989. }
  990. YY_STATUS
  991. YypInitializeStates (
  992. PYYGEN_CONTEXT Context,
  993. PYYGEN_STATE_CONTEXT StateContext
  994. )
  995. /*++
  996. Routine Description:
  997. This routine sets up the initial states of the LR(0) state machine
  998. generator.
  999. Arguments:
  1000. Context - Supplies a pointer to the generator context.
  1001. StateContext - Supplies a pointer to the zeroed out state context.
  1002. Return Value:
  1003. YY status.
  1004. --*/
  1005. {
  1006. YY_VALUE LeftSide;
  1007. PYYGEN_RULE Rule;
  1008. YY_RULE_INDEX RuleCount;
  1009. YY_RULE_INDEX StartDerives;
  1010. PYYGEN_STATE State;
  1011. StartDerives = Context->Derives[Context->StartSymbol];
  1012. assert(StartDerives >= 0);
  1013. Rule = &(Context->Rules[StartDerives]);
  1014. LeftSide = Rule->LeftSide;
  1015. RuleCount = 0;
  1016. do {
  1017. Rule += 1;
  1018. RuleCount += 1;
  1019. } while (Rule->LeftSide == LeftSide);
  1020. State = YypAllocate(sizeof(YYGEN_STATE) + (RuleCount * sizeof(YY_VALUE)));
  1021. if (State == NULL) {
  1022. return YyStatusNoMemory;
  1023. }
  1024. State->ItemsCount = RuleCount;
  1025. State->Items = (PYY_VALUE)(State + 1);
  1026. Rule = &(Context->Rules[StartDerives]);
  1027. RuleCount = 0;
  1028. do {
  1029. State->Items[RuleCount] = Rule->RightSide;
  1030. Rule += 1;
  1031. RuleCount += 1;
  1032. } while (Rule->LeftSide == LeftSide);
  1033. Context->FirstState = State;
  1034. Context->StateCount = 1;
  1035. StateContext->LastState = State;
  1036. StateContext->CurrentState = State;
  1037. return YyStatusSuccess;
  1038. }
  1039. YY_STATUS
  1040. YypSaveReductions (
  1041. PYYGEN_CONTEXT Context,
  1042. PYYGEN_STATE_CONTEXT StateContext
  1043. )
  1044. /*++
  1045. Routine Description:
  1046. This routine examines the current itemsets and converts any empty ones
  1047. into reductions for the current state.
  1048. Arguments:
  1049. Context - Supplies a pointer to the generator context.
  1050. StateContext - Supplies a pointer to the zeroed out state context.
  1051. Return Value:
  1052. YY status.
  1053. --*/
  1054. {
  1055. UINTN AllocationSize;
  1056. PYY_RULE_INDEX Destination;
  1057. PYY_RULE_INDEX End;
  1058. YY_VALUE Item;
  1059. PYY_ITEM_INDEX ItemSet;
  1060. YY_VALUE ReductionCount;
  1061. PYYGEN_REDUCTIONS Reductions;
  1062. PYY_RULE_INDEX Source;
  1063. //
  1064. // Loop through all the itemsets for this state. If any are currently at
  1065. // the end, that's a reduction.
  1066. //
  1067. ReductionCount = 0;
  1068. ItemSet = Context->ItemSet;
  1069. while (ItemSet < Context->ItemSetEnd) {
  1070. Item = Context->Items[*ItemSet];
  1071. if (Item < 0) {
  1072. StateContext->ReduceSet[ReductionCount] = (YY_RULE_INDEX)-Item;
  1073. ReductionCount += 1;
  1074. }
  1075. ItemSet += 1;
  1076. }
  1077. if (ReductionCount == 0) {
  1078. return YyStatusSuccess;
  1079. }
  1080. AllocationSize = sizeof(YYGEN_REDUCTIONS) +
  1081. (ReductionCount * sizeof(YY_RULE_INDEX));
  1082. Reductions = YypAllocate(AllocationSize);
  1083. if (Reductions == NULL) {
  1084. return YyStatusNoMemory;
  1085. }
  1086. Reductions->Number = StateContext->CurrentState->Number;
  1087. Reductions->Count = ReductionCount;
  1088. Reductions->Rules = (PYY_RULE_INDEX)(Reductions + 1);
  1089. Source = StateContext->ReduceSet;
  1090. End = Source + ReductionCount;
  1091. Destination = Reductions->Rules;
  1092. while (Source < End) {
  1093. *Destination = *Source;
  1094. Destination += 1;
  1095. Source += 1;
  1096. }
  1097. //
  1098. // Add it to the end of the list.
  1099. //
  1100. if (Context->LastReduction != NULL) {
  1101. Context->LastReduction->Next = Reductions;
  1102. Context->LastReduction = Reductions;
  1103. } else {
  1104. Context->FirstReduction = Reductions;
  1105. Context->LastReduction = Reductions;
  1106. }
  1107. return YyStatusSuccess;
  1108. }
  1109. VOID
  1110. YypAdvanceItemSets (
  1111. PYYGEN_CONTEXT Context,
  1112. PYYGEN_STATE_CONTEXT StateContext
  1113. )
  1114. /*++
  1115. Routine Description:
  1116. This routine creates the set of possible shift symbols and for each symbol
  1117. determines the new item sets (kernel) in that next state.
  1118. Arguments:
  1119. Context - Supplies a pointer to the generator context.
  1120. StateContext - Supplies a pointer to the zeroed out state context.
  1121. Return Value:
  1122. YY status.
  1123. --*/
  1124. {
  1125. PYY_ITEM_INDEX CurrentKernel;
  1126. YY_ITEM_INDEX ItemIndex;
  1127. PYY_ITEM_INDEX ItemSet;
  1128. YY_VALUE ShiftCount;
  1129. YY_VALUE Symbol;
  1130. for (Symbol = 0; Symbol < Context->SymbolCount; Symbol += 1) {
  1131. StateContext->KernelEnd[Symbol] = NULL;
  1132. }
  1133. //
  1134. // Loop across all the right hand sides for this state.
  1135. //
  1136. ShiftCount = 0;
  1137. ItemSet = Context->ItemSet;
  1138. while (ItemSet < Context->ItemSetEnd) {
  1139. ItemIndex = *ItemSet;
  1140. ItemSet += 1;
  1141. //
  1142. // If the first symbol in this right hand side is not the end and is
  1143. // not EOF, then add it as a next item set for this symbol.
  1144. //
  1145. Symbol = Context->Items[ItemIndex];
  1146. if (Symbol > 0) {
  1147. CurrentKernel = StateContext->KernelEnd[Symbol];
  1148. //
  1149. // If this symbol has never been added before, then it's a new
  1150. // shift possibility out of the current state.
  1151. //
  1152. if (CurrentKernel == NULL) {
  1153. StateContext->ShiftSymbol[ShiftCount] = Symbol;
  1154. ShiftCount += 1;
  1155. CurrentKernel = StateContext->KernelBase[Symbol];
  1156. }
  1157. *CurrentKernel = ItemIndex + 1;
  1158. CurrentKernel += 1;
  1159. StateContext->KernelEnd[Symbol] = CurrentKernel;
  1160. }
  1161. }
  1162. StateContext->ShiftCount = ShiftCount;
  1163. return;
  1164. }
  1165. VOID
  1166. YypAddNewStates (
  1167. PYYGEN_CONTEXT Context,
  1168. PYYGEN_STATE_CONTEXT StateContext
  1169. )
  1170. /*++
  1171. Routine Description:
  1172. This routine adds the new states spun out from advancing the item sets on
  1173. the current state.
  1174. Arguments:
  1175. Context - Supplies a pointer to the generator context.
  1176. StateContext - Supplies a pointer to the zeroed out state context.
  1177. Return Value:
  1178. YY status.
  1179. --*/
  1180. {
  1181. YY_VALUE Search;
  1182. YY_VALUE ShiftIndex;
  1183. PYY_VALUE ShiftSymbol;
  1184. YY_VALUE Symbol;
  1185. ShiftSymbol = StateContext->ShiftSymbol;
  1186. //
  1187. // Sort the shift symbols.
  1188. //
  1189. for (ShiftIndex = 1;
  1190. ShiftIndex < StateContext->ShiftCount;
  1191. ShiftIndex += 1) {
  1192. Symbol = ShiftSymbol[ShiftIndex];
  1193. Search = ShiftIndex;
  1194. while ((Search > 0) && (ShiftSymbol[Search - 1] > Symbol)) {
  1195. ShiftSymbol[Search] = ShiftSymbol[Search - 1];
  1196. Search -= 1;
  1197. }
  1198. ShiftSymbol[Search] = Symbol;
  1199. }
  1200. //
  1201. // Find or add states for all new shift possibilities.
  1202. //
  1203. for (ShiftIndex = 0;
  1204. ShiftIndex < StateContext->ShiftCount;
  1205. ShiftIndex += 1) {
  1206. Symbol = ShiftSymbol[ShiftIndex];
  1207. StateContext->ShiftSet[ShiftIndex] =
  1208. YypGetState(Context, StateContext, Symbol);
  1209. if ((Context->Flags & YYGEN_FLAG_DEBUG) != 0) {
  1210. printf("State %d -> %d via %s\n",
  1211. StateContext->CurrentState->Number,
  1212. StateContext->ShiftSet[ShiftIndex],
  1213. Context->Elements[Symbol].Name);
  1214. }
  1215. }
  1216. return;
  1217. }
  1218. YY_STATE_INDEX
  1219. YypGetState (
  1220. PYYGEN_CONTEXT Context,
  1221. PYYGEN_STATE_CONTEXT StateContext,
  1222. YY_VALUE Symbol
  1223. )
  1224. /*++
  1225. Routine Description:
  1226. This routine finds or creates a state based on the incoming shift symbol
  1227. and the item sets in that state.
  1228. Arguments:
  1229. Context - Supplies a pointer to the generator context.
  1230. StateContext - Supplies a pointer to the zeroed out state context.
  1231. Symbol - Supplies a pointer to the shift symbol to get or create the
  1232. state for.
  1233. Return Value:
  1234. returns the state number for the new state.
  1235. --*/
  1236. {
  1237. PYY_ITEM_INDEX CurrentKernel;
  1238. BOOL Found;
  1239. ULONG ItemSetCount;
  1240. PYY_ITEM_INDEX KernelEnd;
  1241. YY_ITEM_INDEX Key;
  1242. PYYGEN_STATE State;
  1243. PYY_ITEM_INDEX StateItemSet;
  1244. CurrentKernel = StateContext->KernelBase[Symbol];
  1245. KernelEnd = StateContext->KernelEnd[Symbol];
  1246. assert(KernelEnd != NULL);
  1247. ItemSetCount = KernelEnd - CurrentKernel;
  1248. assert(ItemSetCount != 0);
  1249. //
  1250. // The hash table of states is keyed off of the item index of the first
  1251. // item set in the state.
  1252. //
  1253. Key = *CurrentKernel;
  1254. State = StateContext->StateSet[Key];
  1255. if (State != NULL) {
  1256. Found = FALSE;
  1257. do {
  1258. //
  1259. // Perform a quick check against the item count. If it matches, do
  1260. // a deeper check to see if the states contain the same item sets.
  1261. //
  1262. if (State->ItemsCount == ItemSetCount) {
  1263. Found = TRUE;
  1264. CurrentKernel = StateContext->KernelBase[Symbol];
  1265. StateItemSet = State->Items;
  1266. while (CurrentKernel < KernelEnd) {
  1267. if (*CurrentKernel != *StateItemSet) {
  1268. Found = FALSE;
  1269. break;
  1270. }
  1271. CurrentKernel += 1;
  1272. StateItemSet += 1;
  1273. }
  1274. }
  1275. //
  1276. // If this state wasn't it, get the next state in the hash bucket
  1277. // by following the link. If there are no more links, then add
  1278. // this as a new state.
  1279. //
  1280. if (Found == FALSE) {
  1281. if (State->Link != NULL) {
  1282. State = State->Link;
  1283. } else {
  1284. State = YypCreateState(Context, StateContext, Symbol);
  1285. if (State == NULL) {
  1286. return -1;
  1287. }
  1288. State->Link = State;
  1289. Found = TRUE;
  1290. }
  1291. }
  1292. } while (Found == FALSE);
  1293. } else {
  1294. State = YypCreateState(Context, StateContext, Symbol);
  1295. if (State == NULL) {
  1296. return -1;
  1297. }
  1298. StateContext->StateSet[Key] = State;
  1299. }
  1300. return State->Number;
  1301. }
  1302. PYYGEN_STATE
  1303. YypCreateState (
  1304. PYYGEN_CONTEXT Context,
  1305. PYYGEN_STATE_CONTEXT StateContext,
  1306. YY_VALUE Symbol
  1307. )
  1308. /*++
  1309. Routine Description:
  1310. This routine creates a state for the current item set.
  1311. Arguments:
  1312. Context - Supplies a pointer to the generator context.
  1313. StateContext - Supplies a pointer to the zeroed out state context.
  1314. Symbol - Supplies a pointer to the shift symbol to create the state for.
  1315. Return Value:
  1316. returns a pointer to the newly created state on success.
  1317. NULL on allocation failure.
  1318. --*/
  1319. {
  1320. ULONG Count;
  1321. PYY_ITEM_INDEX Destination;
  1322. PYY_ITEM_INDEX End;
  1323. PYY_ITEM_INDEX ItemSet;
  1324. PYYGEN_STATE State;
  1325. if (Context->StateCount >= YY_MAX_STATES) {
  1326. return NULL;
  1327. }
  1328. ItemSet = StateContext->KernelBase[Symbol];
  1329. End = StateContext->KernelEnd[Symbol];
  1330. Count = End - ItemSet;
  1331. State = YypAllocate(sizeof(YYGEN_STATE) + (Count * sizeof(YY_ITEM_INDEX)));
  1332. if (State == NULL) {
  1333. return NULL;
  1334. }
  1335. State->Items = (PYY_ITEM_INDEX)(State + 1);
  1336. State->AccessingSymbol = Symbol;
  1337. State->Number = Context->StateCount;
  1338. Context->StateCount += 1;
  1339. State->ItemsCount = Count;
  1340. Destination = State->Items;
  1341. while (ItemSet < End) {
  1342. *Destination = *ItemSet;
  1343. ItemSet += 1;
  1344. Destination += 1;
  1345. }
  1346. StateContext->LastState->Next = State;
  1347. StateContext->LastState = State;
  1348. return State;
  1349. }
  1350. YY_STATUS
  1351. YypSaveShifts (
  1352. PYYGEN_CONTEXT Context,
  1353. PYYGEN_STATE_CONTEXT StateContext
  1354. )
  1355. /*++
  1356. Routine Description:
  1357. This routine saves the shift symbols for the current state.
  1358. Arguments:
  1359. Context - Supplies a pointer to the generator context.
  1360. StateContext - Supplies a pointer to the zeroed out state context.
  1361. Return Value:
  1362. YY Status code.
  1363. --*/
  1364. {
  1365. ULONG AllocationSize;
  1366. PYY_STATE_INDEX Destination;
  1367. PYY_STATE_INDEX End;
  1368. PYYGEN_SHIFTS Shifts;
  1369. PYY_STATE_INDEX Source;
  1370. AllocationSize = sizeof(YYGEN_SHIFTS) +
  1371. (StateContext->ShiftCount * sizeof(YY_VALUE));
  1372. Shifts = YypAllocate(AllocationSize);
  1373. if (Shifts == NULL) {
  1374. return YyStatusNoMemory;
  1375. }
  1376. Shifts->States = (PYY_STATE_INDEX)(Shifts + 1);
  1377. Shifts->Number = StateContext->CurrentState->Number;
  1378. Shifts->Count = StateContext->ShiftCount;
  1379. Source = StateContext->ShiftSet;
  1380. End = Source + StateContext->ShiftCount;
  1381. Destination = Shifts->States;
  1382. while (Source < End) {
  1383. *Destination = *Source;
  1384. Destination += 1;
  1385. Source += 1;
  1386. }
  1387. if (Context->LastShift != NULL) {
  1388. Context->LastShift->Next = Shifts;
  1389. } else {
  1390. Context->FirstShift = Shifts;
  1391. }
  1392. Context->LastShift = Shifts;
  1393. return YyStatusSuccess;
  1394. }
  1395. VOID
  1396. YypPrintItems (
  1397. PYYGEN_CONTEXT Context
  1398. )
  1399. /*++
  1400. Routine Description:
  1401. This routine prints the items array.
  1402. Arguments:
  1403. Context - Supplies a pointer to the generator context.
  1404. Return Value:
  1405. None.
  1406. --*/
  1407. {
  1408. YY_ITEM_INDEX Index;
  1409. YY_VALUE Value;
  1410. printf("\nItems:\n");
  1411. for (Index = 0; Index < Context->ItemCount; Index += 1) {
  1412. Value = Context->Items[Index];
  1413. if (Value >= 0) {
  1414. printf(" %d: %s\n", Index, Context->Elements[Value].Name);
  1415. } else {
  1416. printf(" %d: Rule %d (%s)\n",
  1417. Index,
  1418. -Value,
  1419. Context->Elements[Context->Rules[-Value].LeftSide].Name);
  1420. }
  1421. }
  1422. return;
  1423. }
  1424. VOID
  1425. YypPrintDerives (
  1426. PYYGEN_CONTEXT Context
  1427. )
  1428. /*++
  1429. Routine Description:
  1430. This routine prints the derives to standard out for debugging purposes.
  1431. Arguments:
  1432. Context - Supplies a pointer to the generator context.
  1433. Return Value:
  1434. None.
  1435. --*/
  1436. {
  1437. YY_VALUE Index;
  1438. YY_VALUE LeftSide;
  1439. PYYGEN_RULE Rule;
  1440. YY_RULE_INDEX RuleIndex;
  1441. printf("\nDerives:\n");
  1442. for (Index = Context->StartSymbol;
  1443. Index < Context->SymbolCount;
  1444. Index += 1) {
  1445. printf("%s derives ", Context->Elements[Index].Name);
  1446. RuleIndex = Context->Derives[Index];
  1447. Rule = &(Context->Rules[RuleIndex]);
  1448. LeftSide = Rule->LeftSide;
  1449. while (Rule->LeftSide == LeftSide) {
  1450. printf(" %d", RuleIndex);
  1451. RuleIndex += 1;
  1452. Rule += 1;
  1453. }
  1454. printf("\n");
  1455. }
  1456. printf("\n");
  1457. return;
  1458. }
  1459. VOID
  1460. YypPrintEpsilonFreeFirsts (
  1461. PYYGEN_CONTEXT Context,
  1462. PULONG EpsilonFreeFirsts
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. This routine prints the set of epsilon-free FIRSTs.
  1467. Arguments:
  1468. Context - Supplies a pointer to the generator context.
  1469. EpsilonFreeFirsts - Supplies a pointer to the array of bitmaps that are the
  1470. Epsilon-Free firsts.
  1471. Return Value:
  1472. None.
  1473. --*/
  1474. {
  1475. ULONG Bit;
  1476. YY_VALUE BitIndex;
  1477. YY_VALUE Index;
  1478. PULONG Row;
  1479. ULONG RowSize;
  1480. ULONG Word;
  1481. RowSize = YYGEN_BITMAP_WORD_COUNT(Context->NonTerminalCount);
  1482. printf("\nEpsilon Free Firsts:\n");
  1483. for (Index = Context->StartSymbol;
  1484. Index < Context->SymbolCount;
  1485. Index += 1) {
  1486. printf("\n%s", Context->Elements[Index].Name);
  1487. Row = EpsilonFreeFirsts + ((Index - Context->StartSymbol) * RowSize);
  1488. Word = *Row;
  1489. Bit = 0;
  1490. for (BitIndex = 0;
  1491. BitIndex < Context->NonTerminalCount;
  1492. BitIndex += 1) {
  1493. if ((Word & (1 << Bit)) != 0) {
  1494. printf(" %s",
  1495. Context->Elements[Context->StartSymbol + BitIndex].Name);
  1496. }
  1497. Bit += 1;
  1498. if (Bit == YYGEN_BITS_PER_WORD) {
  1499. Bit = 0;
  1500. Row += 1;
  1501. Word = *Row;
  1502. }
  1503. }
  1504. }
  1505. return;
  1506. }
  1507. VOID
  1508. YypPrintFirstDerives (
  1509. PYYGEN_CONTEXT Context
  1510. )
  1511. /*++
  1512. Routine Description:
  1513. This routine prints the set of first derives.
  1514. Arguments:
  1515. Context - Supplies a pointer to the generator context.
  1516. Return Value:
  1517. None.
  1518. --*/
  1519. {
  1520. ULONG Bit;
  1521. YY_VALUE Index;
  1522. PULONG Row;
  1523. ULONG RowSize;
  1524. YY_RULE_INDEX RuleIndex;
  1525. YY_VALUE StartSymbol;
  1526. ULONG Word;
  1527. RowSize = YYGEN_BITMAP_WORD_COUNT(Context->RuleCount);
  1528. StartSymbol = Context->StartSymbol;
  1529. printf("\n\nFirst Derives:\n");
  1530. for (Index = StartSymbol; Index < Context->SymbolCount; Index += 1) {
  1531. printf("\n %s derives\n", Context->Elements[Index].Name);
  1532. Row = Context->FirstDerives + ((Index - StartSymbol) * RowSize);
  1533. Bit = 0;
  1534. Word = *Row;
  1535. for (RuleIndex = 0; RuleIndex <= Context->RuleCount; RuleIndex += 1) {
  1536. if ((Word & (1 << Bit)) != 0) {
  1537. printf(" %d\n", RuleIndex);
  1538. }
  1539. Bit += 1;
  1540. if (Bit == YYGEN_BITS_PER_WORD) {
  1541. Bit = 0;
  1542. Row += 1;
  1543. Word = *Row;
  1544. }
  1545. }
  1546. }
  1547. return;
  1548. }
  1549. VOID
  1550. YypPrintClosure (
  1551. PYYGEN_CONTEXT Context,
  1552. YY_VALUE ItemsCount
  1553. )
  1554. /*++
  1555. Routine Description:
  1556. This routine prints the set of first derives.
  1557. Arguments:
  1558. Context - Supplies a pointer to the generator context.
  1559. ItemsCount - Supplies the number of item sets in the state.
  1560. Return Value:
  1561. None.
  1562. --*/
  1563. {
  1564. PYY_ITEM_INDEX ItemSet;
  1565. printf("\nn = %d\n", ItemsCount);
  1566. ItemSet = Context->ItemSet;
  1567. while (ItemSet < Context->ItemSetEnd) {
  1568. printf(" %d\n", *ItemSet);
  1569. ItemSet += 1;
  1570. }
  1571. return;
  1572. }