verbose.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  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. verbose.c
  9. Abstract:
  10. This module implements verbose and debug output for the YY parser generator.
  11. Author:
  12. Evan Green 24-Apr-2016
  13. Environment:
  14. Build
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "yygenp.h"
  20. #include <stdio.h>
  21. #include <string.h>
  22. //
  23. // --------------------------------------------------------------------- Macros
  24. //
  25. #define YYGEN_PLURALIZE(_Value) (((_Value) == 1) ? "" : "s")
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // ------------------------------------------------------ Data Type Definitions
  31. //
  32. //
  33. // ----------------------------------------------- Internal Function Prototypes
  34. //
  35. VOID
  36. YypGraphState (
  37. PYYGEN_CONTEXT Context,
  38. FILE *File,
  39. YY_STATE_INDEX StateIndex
  40. );
  41. VOID
  42. YypGraphLookaheads (
  43. PYYGEN_CONTEXT Context,
  44. FILE *File,
  45. YY_RULE_INDEX RuleIndex,
  46. PYY_VALUE LookaheadIndex
  47. );
  48. VOID
  49. YypPrintGrammar (
  50. PYYGEN_CONTEXT Context,
  51. FILE *File
  52. );
  53. VOID
  54. YypPrintState (
  55. PYYGEN_CONTEXT Context,
  56. FILE *File,
  57. PYY_RULE_INDEX NullRules,
  58. YY_STATE_INDEX StateIndex
  59. );
  60. VOID
  61. YypPrintUnusedRules (
  62. PYYGEN_CONTEXT Context,
  63. FILE *File
  64. );
  65. VOID
  66. YypPrintConflicts (
  67. PYYGEN_CONTEXT Context,
  68. FILE *File
  69. );
  70. VOID
  71. YypPrintConflictsForState (
  72. PYYGEN_CONTEXT Context,
  73. FILE *File,
  74. YY_STATE_INDEX StateIndex
  75. );
  76. VOID
  77. YypPrintStateItemSets (
  78. PYYGEN_CONTEXT Context,
  79. FILE *File,
  80. YY_STATE_INDEX StateIndex
  81. );
  82. VOID
  83. YypPrintStateNulls (
  84. PYYGEN_CONTEXT Context,
  85. FILE *File,
  86. PYY_RULE_INDEX NullRules,
  87. YY_STATE_INDEX StateIndex
  88. );
  89. VOID
  90. YypPrintActions (
  91. PYYGEN_CONTEXT Context,
  92. FILE *File,
  93. YY_STATE_INDEX StateIndex
  94. );
  95. VOID
  96. YypPrintShifts (
  97. PYYGEN_CONTEXT Context,
  98. FILE *File,
  99. PYYGEN_ACTION Action
  100. );
  101. VOID
  102. YypPrintReductions (
  103. PYYGEN_CONTEXT Context,
  104. FILE *File,
  105. PYYGEN_ACTION Action,
  106. YY_RULE_INDEX DefaultReduction
  107. );
  108. VOID
  109. YypPrintGotos (
  110. PYYGEN_CONTEXT Context,
  111. FILE *File,
  112. YY_STATE_INDEX StateIndex
  113. );
  114. //
  115. // -------------------------------------------------------------------- Globals
  116. //
  117. //
  118. // ------------------------------------------------------------------ Functions
  119. //
  120. VOID
  121. YyPrintGraph (
  122. PYYGEN_CONTEXT Context,
  123. FILE *File
  124. )
  125. /*++
  126. Routine Description:
  127. This routine prints the state graph for the given parsed grammar.
  128. Arguments:
  129. Context - Supplies a pointer to the initialized grammar context.
  130. File - Supplies the file handle to output to.
  131. Return Value:
  132. None.
  133. --*/
  134. {
  135. YY_VALUE ShiftIndex;
  136. PYYGEN_SHIFTS Shifts;
  137. YY_STATE_INDEX ShiftState;
  138. YY_STATE_INDEX StateIndex;
  139. YY_VALUE Symbol;
  140. for (StateIndex = 0; StateIndex < Context->StateCount; StateIndex += 1) {
  141. YypEstablishClosure(Context, Context->StateTable[StateIndex]);
  142. YypGraphState(Context, File, StateIndex);
  143. }
  144. fprintf(File, "\n\n");
  145. for (StateIndex = 0; StateIndex < Context->StateCount; StateIndex += 1) {
  146. Shifts = Context->ShiftTable[StateIndex];
  147. if (Shifts != NULL) {
  148. for (ShiftIndex = 0; ShiftIndex < Shifts->Count; ShiftIndex += 1) {
  149. ShiftState = Shifts->States[ShiftIndex];
  150. Symbol = Context->AccessingSymbol[ShiftState];
  151. fprintf(File,
  152. "\tq%d -> q%d [label=\"%s\"];\n",
  153. StateIndex,
  154. ShiftState,
  155. Context->Elements[Symbol].Name);
  156. }
  157. }
  158. }
  159. fprintf(File, "}\n");
  160. return;
  161. }
  162. VOID
  163. YyPrintParserState (
  164. PYYGEN_CONTEXT Context,
  165. FILE *File
  166. )
  167. /*++
  168. Routine Description:
  169. This routine prints a human readable description of the parser states.
  170. Arguments:
  171. Context - Supplies a pointer to the initialized grammar context.
  172. File - Supplies the file handle to output to.
  173. Return Value:
  174. None.
  175. --*/
  176. {
  177. PYY_RULE_INDEX NullRules;
  178. YY_STATE_INDEX StateIndex;
  179. NullRules = YypAllocate(Context->RuleCount * sizeof(YY_RULE_INDEX));
  180. if (NullRules == NULL) {
  181. goto DumpParserStateEnd;
  182. }
  183. YypPrintGrammar(Context, File);
  184. fprintf(File, "\n\n");
  185. for (StateIndex = 0; StateIndex < Context->StateCount; StateIndex += 1) {
  186. YypPrintState(Context, File, NullRules, StateIndex);
  187. }
  188. if (Context->UnusedRules != 0) {
  189. YypPrintUnusedRules(Context, File);
  190. }
  191. if ((Context->ShiftReduceConflictCount != 0) ||
  192. (Context->ReduceReduceConflictCount != 0)) {
  193. YypPrintConflicts(Context, File);
  194. }
  195. fprintf(File,
  196. "\n\n%d terminals, %d nonterminals\n",
  197. Context->TokenCount,
  198. Context->NonTerminalCount);
  199. fprintf(File,
  200. "%d grammar rules, %d states\n",
  201. Context->RuleCount - 2,
  202. Context->StateCount);
  203. DumpParserStateEnd:
  204. if (NullRules != NULL) {
  205. YypFree(NullRules);
  206. }
  207. return;
  208. }
  209. //
  210. // --------------------------------------------------------- Internal Functions
  211. //
  212. VOID
  213. YypGraphState (
  214. PYYGEN_CONTEXT Context,
  215. FILE *File,
  216. YY_STATE_INDEX StateIndex
  217. )
  218. /*++
  219. Routine Description:
  220. This routine prints the graph for a particular state.
  221. Arguments:
  222. Context - Supplies a pointer to the initialized grammar context.
  223. File - Supplies the file handle to output to.
  224. StateIndex - Supplies the state to graph. The context's item set array
  225. should be properly set up for this state.
  226. Return Value:
  227. None.
  228. --*/
  229. {
  230. PYY_VALUE Items;
  231. PYY_ITEM_INDEX ItemSet;
  232. PYY_VALUE ItemsStart;
  233. YY_VALUE LookaheadIndex;
  234. YY_RULE_INDEX RuleIndex;
  235. YY_VALUE Symbol;
  236. LookaheadIndex = Context->Lookaheads[StateIndex];
  237. fprintf(File, "\n\tq%d [label=\"%d:\\l", StateIndex, StateIndex);
  238. ItemSet = Context->ItemSet;
  239. while (ItemSet < Context->ItemSetEnd) {
  240. Items = Context->Items + *ItemSet;
  241. ItemsStart = Items;
  242. while (*Items >= 0) {
  243. Items += 1;
  244. }
  245. RuleIndex = -(*Items);
  246. Symbol = Context->Rules[RuleIndex].LeftSide;
  247. fprintf(File, " %s -> ", Context->Elements[Symbol].Name);
  248. Items = Context->Items + Context->Rules[RuleIndex].RightSide;
  249. while (Items < ItemsStart) {
  250. fprintf(File, "%s ", Context->Elements[*Items].Name);
  251. Items += 1;
  252. }
  253. fputc('.', File);
  254. while (*Items >= 0) {
  255. fprintf(File, " %s", Context->Elements[*Items].Name);
  256. Items += 1;
  257. }
  258. if (*ItemsStart < 0) {
  259. YypGraphLookaheads(Context, File, RuleIndex, &LookaheadIndex);
  260. }
  261. fprintf(File, "\\l");
  262. ItemSet += 1;
  263. }
  264. fprintf(File, "\"]'");
  265. return;
  266. }
  267. VOID
  268. YypGraphLookaheads (
  269. PYYGEN_CONTEXT Context,
  270. FILE *File,
  271. YY_RULE_INDEX RuleIndex,
  272. PYY_VALUE LookaheadIndex
  273. )
  274. /*++
  275. Routine Description:
  276. This routine prints the lookahead tokens for a particular rule.
  277. Arguments:
  278. Context - Supplies a pointer to the initialized grammar context.
  279. File - Supplies the file handle to output to.
  280. RuleIndex - Supplies the rule whose lookaheads should be graphed.
  281. LookaheadIndex - Supplies a pointer to the index into the lookahead array.
  282. This may be updated.
  283. Return Value:
  284. None.
  285. --*/
  286. {
  287. PULONG Row;
  288. YY_VALUE Token;
  289. ULONG TokenSetSize;
  290. TokenSetSize = YYGEN_BITMAP_WORD_COUNT(Context->TokenCount);
  291. if (RuleIndex == Context->LookaheadRule[*LookaheadIndex]) {
  292. Row = Context->LookaheadSets + (*LookaheadIndex * TokenSetSize);
  293. fprintf(File, " { ");
  294. for (Token = Context->TokenCount - 1; Token >= 0; Token -= 1) {
  295. if (YYGEN_BITMAP_IS_SET(Row, Token)) {
  296. fprintf(File, "%s ", Context->Elements[Token].Name);
  297. }
  298. }
  299. fprintf(File, " } ");
  300. *LookaheadIndex += 1;
  301. }
  302. return;
  303. }
  304. VOID
  305. YypPrintGrammar (
  306. PYYGEN_CONTEXT Context,
  307. FILE *File
  308. )
  309. /*++
  310. Routine Description:
  311. This routine prints the set of numbered rules.
  312. Arguments:
  313. Context - Supplies a pointer to the initialized grammar context.
  314. File - Supplies the file handle to output to.
  315. Return Value:
  316. None.
  317. --*/
  318. {
  319. PYY_VALUE Item;
  320. YY_VALUE LeftSide;
  321. PSTR Name;
  322. PYYGEN_RULE Rule;
  323. YY_RULE_INDEX RuleIndex;
  324. INT Spacing;
  325. Spacing = 0;
  326. LeftSide = -1;
  327. for (RuleIndex = 2; RuleIndex < Context->RuleCount; RuleIndex += 1) {
  328. Rule = &(Context->Rules[RuleIndex]);
  329. if (Rule->LeftSide != LeftSide) {
  330. if (RuleIndex != 2) {
  331. fprintf(File, "\n");
  332. }
  333. Name = Context->Elements[Rule->LeftSide].Name;
  334. fprintf(File, "%4d %s :", RuleIndex - 2, Name);
  335. Spacing = strlen(Name) + 1;
  336. } else {
  337. fprintf(File, "%4d %*s|", RuleIndex - 2, Spacing, "");
  338. }
  339. Item = Context->Items + Rule->RightSide;
  340. while (*Item >= 0) {
  341. fprintf(File, " %s", Context->Elements[*Item].Name);
  342. Item += 1;
  343. }
  344. fprintf(File, "\n");
  345. LeftSide = Rule->LeftSide;
  346. }
  347. return;
  348. }
  349. VOID
  350. YypPrintState (
  351. PYYGEN_CONTEXT Context,
  352. FILE *File,
  353. PYY_RULE_INDEX NullRules,
  354. YY_STATE_INDEX StateIndex
  355. )
  356. /*++
  357. Routine Description:
  358. This routine prints a human readable description of a particular parser
  359. state.
  360. Arguments:
  361. Context - Supplies a pointer to the initialized grammar context.
  362. File - Supplies the file handle to output to.
  363. NullRules - Supplies a pointer to a null rules array.
  364. StateIndex - Supplies the index of the state to print.
  365. Return Value:
  366. None.
  367. --*/
  368. {
  369. if (StateIndex != 0) {
  370. fprintf(File, "\n\n");
  371. }
  372. if ((Context->ShiftReduceConflicts[StateIndex] != 0) ||
  373. (Context->ReduceReduceConflicts[StateIndex] != 0)) {
  374. YypPrintConflictsForState(Context, File, StateIndex);
  375. }
  376. fprintf(File, "state %d\n", StateIndex);
  377. YypPrintStateItemSets(Context, File, StateIndex);
  378. YypPrintStateNulls(Context, File, NullRules, StateIndex);
  379. YypPrintActions(Context, File, StateIndex);
  380. return;
  381. }
  382. VOID
  383. YypPrintUnusedRules (
  384. PYYGEN_CONTEXT Context,
  385. FILE *File
  386. )
  387. /*++
  388. Routine Description:
  389. This routine prints a human readable description of the unreduced parser
  390. rules.
  391. Arguments:
  392. Context - Supplies a pointer to the initialized grammar context.
  393. File - Supplies the file handle to output to.
  394. Return Value:
  395. None.
  396. --*/
  397. {
  398. PYY_VALUE Items;
  399. PYYGEN_RULE Rule;
  400. YY_RULE_INDEX RuleIndex;
  401. fprintf(File, "\n\nRules never reduced:\n");
  402. for (RuleIndex = 3; RuleIndex < Context->RuleCount; RuleIndex += 1) {
  403. Rule = &(Context->Rules[RuleIndex]);
  404. if (Rule->Used == FALSE) {
  405. fprintf(File, "\t%s : ", Context->Elements[Rule->LeftSide].Name);
  406. Items = Context->Items + Rule->RightSide;
  407. while (*Items >= 0) {
  408. fprintf(File, " %s", Context->Elements[*Items].Name);
  409. Items += 1;
  410. }
  411. fprintf(File, " (%d)\n", RuleIndex - 1);
  412. }
  413. }
  414. return;
  415. }
  416. VOID
  417. YypPrintConflicts (
  418. PYYGEN_CONTEXT Context,
  419. FILE *File
  420. )
  421. /*++
  422. Routine Description:
  423. This routine prints a human readable description of the parser conflicts
  424. that could not be resolved via precedence or associativity rules.
  425. Arguments:
  426. Context - Supplies a pointer to the initialized grammar context.
  427. File - Supplies the file handle to output to.
  428. Return Value:
  429. None.
  430. --*/
  431. {
  432. ULONG ReduceConflicts;
  433. ULONG ShiftConflicts;
  434. YY_STATE_INDEX StateIndex;
  435. fprintf(File, "\n\n");
  436. for (StateIndex = 0; StateIndex < Context->StateCount; StateIndex += 1) {
  437. ShiftConflicts = Context->ShiftReduceConflicts[StateIndex];
  438. ReduceConflicts = Context->ReduceReduceConflicts[StateIndex];
  439. if ((ShiftConflicts != 0) || (ReduceConflicts != 0)) {
  440. fprintf(File, "State %d contains ", StateIndex);
  441. if (ShiftConflicts != 0) {
  442. fprintf(File,
  443. "%d shift/reduce conflict%s",
  444. ShiftConflicts,
  445. YYGEN_PLURALIZE(ShiftConflicts));
  446. if (ReduceConflicts != 0) {
  447. fprintf(File, ", ");
  448. }
  449. }
  450. if (ReduceConflicts != 0) {
  451. fprintf(File,
  452. "%d reduce/reduce conflict%s",
  453. ReduceConflicts,
  454. YYGEN_PLURALIZE(ReduceConflicts));
  455. }
  456. fprintf(File, ".\n");
  457. }
  458. }
  459. return;
  460. }
  461. VOID
  462. YypPrintConflictsForState (
  463. PYYGEN_CONTEXT Context,
  464. FILE *File,
  465. YY_STATE_INDEX StateIndex
  466. )
  467. /*++
  468. Routine Description:
  469. This routine prints a human readable description of the parser conflicts
  470. for a particular state.
  471. Arguments:
  472. Context - Supplies a pointer to the initialized grammar context.
  473. File - Supplies the file handle to output to.
  474. StateIndex - Supplies the state index to print conflicts for.
  475. Return Value:
  476. None.
  477. --*/
  478. {
  479. PYYGEN_ACTION Action;
  480. PSTR ActionName;
  481. YY_ACTION_CODE Code;
  482. YY_ACTION_INDEX Number;
  483. YY_VALUE Symbol;
  484. Code = YyActionInvalid;
  485. Action = Context->Parser[StateIndex];
  486. Number = -1;
  487. Symbol = -1;
  488. while (Action != NULL) {
  489. if (Action->Suppression == YySuppressedQuietly) {
  490. Action = Action->Next;
  491. continue;
  492. }
  493. if (Action->Symbol != Symbol) {
  494. Symbol = Action->Symbol;
  495. Number = Action->Number;
  496. Code = Action->Code;
  497. if (Code == YyActionReduce) {
  498. Number -= 2;
  499. }
  500. } else if (Action->Suppression == YySuppressedNoisily) {
  501. if ((StateIndex == Context->FinalState) && (Symbol == 0)) {
  502. fprintf(File,
  503. "%d: shift/reduce conflict (accept, reduce %d) on "
  504. "$end\n",
  505. StateIndex,
  506. Action->Number - 2);
  507. } else {
  508. ActionName = "shift";
  509. if (Code == YyActionReduce) {
  510. ActionName = "reduce";
  511. }
  512. fprintf(File,
  513. "%d: %s/reduce conflict (%s %d, reduce %d) on %s\n",
  514. StateIndex,
  515. ActionName,
  516. ActionName,
  517. Number,
  518. Action->Number - 2,
  519. Context->Elements[Symbol].Name);
  520. }
  521. }
  522. Action = Action->Next;
  523. }
  524. return;
  525. }
  526. VOID
  527. YypPrintStateItemSets (
  528. PYYGEN_CONTEXT Context,
  529. FILE *File,
  530. YY_STATE_INDEX StateIndex
  531. )
  532. /*++
  533. Routine Description:
  534. This routine prints the item sets in a particular state.
  535. Arguments:
  536. Context - Supplies a pointer to the initialized grammar context.
  537. File - Supplies the file handle to output to.
  538. StateIndex - Supplies the state index to print.
  539. Return Value:
  540. None.
  541. --*/
  542. {
  543. PYY_VALUE Current;
  544. PYY_ELEMENT Elements;
  545. PYY_VALUE Items;
  546. YY_ITEM_INDEX ItemsCount;
  547. YY_ITEM_INDEX ItemSetIndex;
  548. PYYGEN_RULE Rule;
  549. YY_RULE_INDEX RuleIndex;
  550. PYYGEN_STATE State;
  551. Elements = Context->Elements;
  552. State = Context->StateTable[StateIndex];
  553. ItemsCount = State->ItemsCount;
  554. for (ItemSetIndex = 0; ItemSetIndex < ItemsCount; ItemSetIndex += 1) {
  555. Items = Context->Items + State->Items[ItemSetIndex];
  556. Current = Items;
  557. while (*Current >= 0) {
  558. Current += 1;
  559. }
  560. RuleIndex = -(*Current);
  561. Rule = &(Context->Rules[RuleIndex]);
  562. fprintf(File, "\t%s : ", Elements[Rule->LeftSide].Name);
  563. Current = Context->Items + Rule->RightSide;
  564. while (*Current >= 0) {
  565. if (Current == Items) {
  566. fprintf(File, ". ");
  567. }
  568. fprintf(File, "%s ", Elements[*Current].Name);
  569. Current += 1;
  570. }
  571. if (Current == Items) {
  572. fprintf(File, ". ");
  573. }
  574. fprintf(File, "(%d)\n", RuleIndex - 2);
  575. }
  576. return;
  577. }
  578. VOID
  579. YypPrintStateNulls (
  580. PYYGEN_CONTEXT Context,
  581. FILE *File,
  582. PYY_RULE_INDEX NullRules,
  583. YY_STATE_INDEX StateIndex
  584. )
  585. /*++
  586. Routine Description:
  587. This routine prints the item set states for empty rules.
  588. Arguments:
  589. Context - Supplies a pointer to the initialized grammar context.
  590. File - Supplies the file handle to output to.
  591. NullRules - Supplies a pointer to an array indexed by rule of whether or
  592. not a rule is null.
  593. StateIndex - Supplies the state index.
  594. Return Value:
  595. None.
  596. --*/
  597. {
  598. PYYGEN_ACTION Action;
  599. YY_RULE_INDEX ActionIndex;
  600. YY_VALUE NullCount;
  601. YY_VALUE NullIndex;
  602. PYYGEN_RULE Rule;
  603. YY_RULE_INDEX RuleIndex;
  604. NullCount = 0;
  605. Action = Context->Parser[StateIndex];
  606. while (Action != NULL) {
  607. if ((Action->Code == YyActionReduce) &&
  608. (Action->Suppression != YySuppressedQuietly)) {
  609. ActionIndex = Action->Number;
  610. if (Context->Rules[ActionIndex].RightSide ==
  611. Context->Rules[ActionIndex + 1].RightSide) {
  612. RuleIndex = 0;
  613. while ((RuleIndex < NullCount) &&
  614. (ActionIndex > NullRules[RuleIndex])) {
  615. RuleIndex += 1;
  616. }
  617. if (RuleIndex == NullCount) {
  618. NullCount += 1;
  619. NullRules[RuleIndex] = ActionIndex;
  620. } else if (ActionIndex != NullRules[RuleIndex]) {
  621. NullCount += 1;
  622. for (NullIndex = NullCount - 1;
  623. NullIndex > RuleIndex;
  624. NullIndex -= 1) {
  625. NullRules[NullIndex] = NullRules[NullIndex - 1];
  626. }
  627. NullRules[RuleIndex] = ActionIndex;
  628. }
  629. }
  630. }
  631. Action = Action->Next;
  632. }
  633. for (NullIndex = 0; NullIndex < NullCount; NullIndex += 1) {
  634. RuleIndex = NullRules[NullIndex];
  635. Rule = &(Context->Rules[RuleIndex]);
  636. fprintf(File,
  637. "\t%s : . (%d)\n",
  638. Context->Elements[Rule->LeftSide].Name,
  639. RuleIndex - 2);
  640. }
  641. fprintf(File, "\n");
  642. return;
  643. }
  644. VOID
  645. YypPrintActions (
  646. PYYGEN_CONTEXT Context,
  647. FILE *File,
  648. YY_STATE_INDEX StateIndex
  649. )
  650. /*++
  651. Routine Description:
  652. This routine prints actions out of a particular state.
  653. Arguments:
  654. Context - Supplies a pointer to the initialized grammar context.
  655. File - Supplies the file handle to output to.
  656. StateIndex - Supplies the state index.
  657. Return Value:
  658. None.
  659. --*/
  660. {
  661. PYYGEN_ACTION Action;
  662. PYYGEN_SHIFTS Shifts;
  663. YY_VALUE Symbol;
  664. if (StateIndex == Context->FinalState) {
  665. fprintf(File, "\t$end accept\n");
  666. }
  667. Action = Context->Parser[StateIndex];
  668. if (Action != NULL) {
  669. YypPrintShifts(Context, File, Action);
  670. YypPrintReductions(Context,
  671. File,
  672. Action,
  673. Context->DefaultReductions[StateIndex]);
  674. }
  675. Shifts = Context->ShiftTable[StateIndex];
  676. if ((Shifts != NULL) && (Shifts->Count != 0)) {
  677. Symbol = Context->AccessingSymbol[Shifts->States[Shifts->Count - 1]];
  678. if (Symbol >= Context->TokenCount) {
  679. YypPrintGotos(Context, File, StateIndex);
  680. }
  681. }
  682. return;
  683. }
  684. VOID
  685. YypPrintShifts (
  686. PYYGEN_CONTEXT Context,
  687. FILE *File,
  688. PYYGEN_ACTION Action
  689. )
  690. /*++
  691. Routine Description:
  692. This routine prints the given shift actions.
  693. Arguments:
  694. Context - Supplies a pointer to the initialized grammar context.
  695. File - Supplies the file handle to output to.
  696. Action - Supplies a pointer to the head of the action list to print shifts
  697. for.
  698. Return Value:
  699. None.
  700. --*/
  701. {
  702. while (Action != NULL) {
  703. if ((Action->Code == YyActionShift) &&
  704. (Action->Suppression == YyNotSuppressed)) {
  705. fprintf(File,
  706. "\t%s shift %d\n",
  707. Context->Elements[Action->Symbol].Name,
  708. Action->Number);
  709. }
  710. Action = Action->Next;
  711. }
  712. return;
  713. }
  714. VOID
  715. YypPrintReductions (
  716. PYYGEN_CONTEXT Context,
  717. FILE *File,
  718. PYYGEN_ACTION Action,
  719. YY_RULE_INDEX DefaultReduction
  720. )
  721. /*++
  722. Routine Description:
  723. This routine prints the given reduction actions.
  724. Arguments:
  725. Context - Supplies a pointer to the initialized grammar context.
  726. File - Supplies the file handle to output to.
  727. Action - Supplies a pointer to the head of the action list to print
  728. reductions for.
  729. DefaultReduction - Supplies the default rule to reduce by.
  730. Return Value:
  731. None.
  732. --*/
  733. {
  734. BOOL AnyReductions;
  735. YY_RULE_INDEX RuleIndex;
  736. AnyReductions = FALSE;
  737. while (Action != NULL) {
  738. if ((Action->Code == YyActionReduce) &&
  739. (Action->Suppression != YySuppressedQuietly)) {
  740. AnyReductions = TRUE;
  741. }
  742. if ((Action->Code == YyActionReduce) &&
  743. (Action->Number != DefaultReduction)) {
  744. RuleIndex = Action->Number - 2;
  745. if (Action->Suppression == YyNotSuppressed) {
  746. fprintf(File,
  747. "\t%s reduce %d\n",
  748. Context->Elements[Action->Symbol].Name,
  749. RuleIndex);
  750. }
  751. }
  752. Action = Action->Next;
  753. }
  754. if (DefaultReduction > 0) {
  755. fprintf(File, "\t. reduce %d\n", DefaultReduction - 2);
  756. }
  757. if (AnyReductions == FALSE) {
  758. fprintf(File, "\t. error\n");
  759. }
  760. return;
  761. }
  762. VOID
  763. YypPrintGotos (
  764. PYYGEN_CONTEXT Context,
  765. FILE *File,
  766. YY_STATE_INDEX StateIndex
  767. )
  768. /*++
  769. Routine Description:
  770. This routine prints the gotos for the given action.
  771. Arguments:
  772. Context - Supplies a pointer to the initialized grammar context.
  773. File - Supplies the file handle to output to.
  774. StateIndex - Supplies the state index to print gotos for.
  775. Return Value:
  776. None.
  777. --*/
  778. {
  779. YY_STATE_INDEX Destination;
  780. YY_VALUE ShiftIndex;
  781. PYYGEN_SHIFTS Shifts;
  782. PYY_STATE_INDEX States;
  783. YY_VALUE Symbol;
  784. fputc('\n', File);
  785. Shifts = Context->ShiftTable[StateIndex];
  786. States = Shifts->States;
  787. for (ShiftIndex = 0; ShiftIndex < Shifts->Count; ShiftIndex += 1) {
  788. Destination = States[ShiftIndex];
  789. Symbol = Context->AccessingSymbol[Destination];
  790. if (Symbol >= Context->TokenCount) {
  791. fprintf(File,
  792. "\t%s goto %d\n",
  793. Context->Elements[Symbol].Name,
  794. Destination);
  795. }
  796. }
  797. return;
  798. }