yaccclos.pas 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. {
  2. Yacc closure and first set construction algorithms. See Aho/Sethi/Ullman,
  3. 1986, Sections 4.4 and 4.7, for further explanation.
  4. Copyright (c) 1990-92 Albert Graef <[email protected]>
  5. Copyright (C) 1996 Berend de Boer <[email protected]>
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. $Revision: 1.2 $
  18. $Modtime: 96-07-31 14:09 $
  19. $History: YACCCLOS.PAS $
  20. *
  21. * ***************** Version 2 *****************
  22. * User: Berend Date: 96-10-10 Time: 21:16
  23. * Updated in $/Lex and Yacc/tply
  24. * Updated for protected mode, windows and Delphi 1.X and 2.X.
  25. }
  26. unit YaccClos;
  27. interface
  28. procedure closures;
  29. (* compute the closure sets *)
  30. procedure first_sets;
  31. (* compute first sets and nullable flags *)
  32. implementation
  33. uses YaccBase, YaccTabl;
  34. procedure closures;
  35. (* The closure set of a nonterminal X is the set of all nonterminals Y
  36. s.t. Y appears as the first symbol in a rightmost derivation from the
  37. nonterminal X (i.e. X =>+ Y ... in a rightmost derivation). We can
  38. easily compute closure sets as follows:
  39. - Initialize the closure set for any nonterminal X to contain all
  40. nonterminals Y for which there is a rule X : Y ...
  41. - Now repeatedly pass over the already constructed sets, and for
  42. any nonterminal Y which has already been added to the closure set
  43. of some nonterminal X, also include the closure elements of Y in
  44. the closure set of X.
  45. The algorithm terminates as soon as no additional symbols have been
  46. added during the previous pass. *)
  47. var sym, i, count, prev_count : Integer;
  48. act_syms : IntSet;
  49. begin
  50. (* initialize closure sets: *)
  51. prev_count := 0;
  52. count := 0;
  53. for sym := 1 to n_nts do
  54. begin
  55. closure_table^[sym] := newEmptyIntSet;
  56. with rule_offs^[sym] do
  57. for i := rule_lo to rule_hi do
  58. with rule_table^[rule_no^[i]]^ do
  59. if (rhs_len>0) and (rhs_sym[1]<0) then
  60. include(closure_table^[sym]^, rhs_sym[1]);
  61. inc(count, size(closure_table^[sym]^));
  62. end;
  63. (* repeated passes until no more symbols have been added during the last
  64. pass: *)
  65. while prev_count<count do
  66. begin
  67. prev_count := count;
  68. count := 0;
  69. for sym := 1 to n_nts do
  70. begin
  71. act_syms := closure_table^[sym]^;
  72. for i := 1 to size(act_syms) do
  73. setunion(closure_table^[sym]^, closure_table^[-act_syms[i]]^);
  74. inc(count, size(closure_table^[sym]^));
  75. end;
  76. end;
  77. end(*closures*);
  78. procedure first_sets;
  79. (* The first set of a nonterminal X is the set of all literal symbols
  80. y s.t. X =>+ y ... in some derivation of the nonterminal X. In
  81. addition, X is nullable if the empty string can be derived from X.
  82. Using the first set construction algorithm of Aho/Sethi/Ullman,
  83. Section 4.4, the first sets and nullable flags are computed as
  84. follows:
  85. For any production X -> y1 ... yn, where the yi are grammar symbols,
  86. add the symbols in the first set of y1 (y1 itself if it is a literal)
  87. to the first set of X; if y1 is a nullable nonterminal, then proceed
  88. with y2, etc., until either all yi have been considered or yi is non-
  89. nullable (or a literal symbol). If all of the yi are nullable (in
  90. particular, if n=0), then also set nullable[X] to true.
  91. This procedure is repeated until no more symbols have been added to any
  92. first set and none of the nullable flags have been changed during the
  93. previous pass. *)
  94. var i, j, l, sym : Integer;
  95. n, null, done : Boolean;
  96. begin
  97. (* initialize tables: *)
  98. for sym := 1 to n_nts do
  99. begin
  100. nullable^[sym] := false;
  101. first_set_table^[sym] := newEmptyIntSet;
  102. end;
  103. (* repeated passes until no more symbols added and no nullable flags
  104. modified: *)
  105. repeat
  106. done := true;
  107. for i := 1 to n_rules do
  108. with rule_table^[i]^ do
  109. begin
  110. l := size(first_set_table^[-lhs_sym]^);
  111. n := nullable^[-lhs_sym];
  112. null := true;
  113. j := 1;
  114. while (j<=rhs_len) and null do
  115. begin
  116. if rhs_sym[j]<0 then
  117. begin
  118. setunion( first_set_table^[-lhs_sym]^,
  119. first_set_table^[-rhs_sym[j]]^ );
  120. null := nullable^[-rhs_sym[j]];
  121. end
  122. else
  123. begin
  124. include( first_set_table^[-lhs_sym]^,
  125. rhs_sym[j] );
  126. null := false;
  127. end;
  128. inc(j);
  129. end;
  130. if null then nullable^[-lhs_sym] := true;
  131. if (l<size(first_set_table^[-lhs_sym]^)) or
  132. (n<>nullable^[-lhs_sym]) then
  133. done := false;
  134. end;
  135. until done;
  136. end(*first_sets*);
  137. end(*YaccClosure*).