lexopt.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. {
  2. DFA optimization algorithm.
  3. This is an efficient (O(n log(n)) DFA optimization procedure based on the
  4. algorithm given in Aho/Sethi/Ullman, 1986, Section 3.9.
  5. Copyright (c) 1990-92 Albert Graef <[email protected]>
  6. Copyright (C) 1996 Berend de Boer <[email protected]>
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. $Revision: 1.2 $
  19. $Modtime: 96-08-01 6:29 $
  20. $History: LEXOPT.PAS $
  21. *
  22. * ***************** Version 2 *****************
  23. * User: Berend Date: 96-10-10 Time: 21:16
  24. * Updated in $/Lex and Yacc/tply
  25. * Updated for protected mode, windows and Delphi 1.X and 2.X.
  26. }
  27. unit LexOpt;
  28. interface
  29. procedure optimizeDFATable;
  30. (* optimize the state table *)
  31. implementation
  32. uses LexBase, LexTable;
  33. (* Partition table used in DFA optimization: *)
  34. (* obsolete
  35. const
  36. max_parts = max_states;*) (* number of partitions of equivalent states; at
  37. worst, each state may be in a partition by
  38. itself *)
  39. type
  40. PartTable = array [0..max_states-1] of IntSetPtr;
  41. (* state partitions (DFA optimization) *)
  42. StatePartTable = array [0..max_states-1] of Integer;
  43. (* partition number of states *)
  44. var
  45. (* partition table: *)
  46. n_parts : Integer;
  47. part_table : ^PartTable;
  48. state_part : ^StatePartTable;
  49. (* optimized state and transition table: *)
  50. n_opt_states : Integer;
  51. n_opt_trans : Integer;
  52. opt_state_table : ^StateTable;
  53. opt_trans_table : ^TransTable;
  54. function equivStates(i, j : Integer) : Boolean;
  55. (* checks whether states i and j are equivalent; two states are considered
  56. equivalent iff:
  57. - they cover the same marker positions (/ and endmarkers of rules)
  58. - they have transitions on the same symbols/characters, and corresponding
  59. transitions go to states in the same partition
  60. two different start states are never considered equivalent *)
  61. var ii, jj, k : Integer;
  62. mark_pos_i, mark_pos_j : IntSet;
  63. begin
  64. (* check for start states: *)
  65. if (i<=2*n_start_states+1) and (j<=2*n_start_states+1) and
  66. (i<>j) then
  67. begin
  68. equivStates := false;
  69. exit;
  70. end;
  71. (* check end positions: *)
  72. empty(mark_pos_i);
  73. with state_table^[i] do
  74. for k := 1 to size(state_pos^) do
  75. if pos_table^[state_pos^[k]].pos_type=mark_pos then
  76. include(mark_pos_i, state_pos^[k]);
  77. empty(mark_pos_j);
  78. with state_table^[j] do
  79. for k := 1 to size(state_pos^) do
  80. if pos_table^[state_pos^[k]].pos_type=mark_pos then
  81. include(mark_pos_j, state_pos^[k]);
  82. if not equal(mark_pos_i, mark_pos_j) then
  83. begin
  84. equivStates := false;
  85. exit
  86. end;
  87. (* check transitions: *)
  88. if n_state_trans(i)<>n_state_trans(j) then
  89. equivStates := false
  90. else
  91. begin
  92. ii := state_table^[i].trans_lo;
  93. jj := state_table^[j].trans_lo;
  94. for k := 0 to pred(n_state_trans(i)) do
  95. if (trans_table^[ii+k].cc^<>trans_table^[jj+k].cc^) then
  96. begin
  97. equivStates := false;
  98. exit
  99. end
  100. else if state_part^[trans_table^[ii+k].next_state]<>
  101. state_part^[trans_table^[jj+k].next_state] then
  102. begin
  103. equivStates := false;
  104. exit
  105. end;
  106. equivStates := true;
  107. end
  108. end(*equivStates*);
  109. procedure optimizeDFATable;
  110. var
  111. i, ii, j : Integer;
  112. act_part, new_part, n_new_parts : Integer;
  113. begin
  114. n_parts := 0;
  115. (* Initially, create one partition containing ALL states: *)
  116. n_parts := 1;
  117. part_table^[0] := newIntSet;
  118. for i := 0 to n_states-1 do
  119. begin
  120. include(part_table^[0]^, i);
  121. state_part^[i] := 0;
  122. end;
  123. (* Now, repeatedly pass over the created partitions, breaking up
  124. partitions if they contain nonequivalent states, until no more
  125. partitions have been added during the last pass: *)
  126. repeat
  127. n_new_parts := 0; act_part := 0;
  128. new_part := n_parts;
  129. part_table^[new_part] := newIntSet;
  130. while (n_parts<n_states) and (act_part<n_parts) do
  131. begin
  132. for i := 2 to size(part_table^[act_part]^) do
  133. if not equivStates(part_table^[act_part]^[1],
  134. part_table^[act_part]^[i]) then
  135. (* add to new partition: *)
  136. include(part_table^[new_part]^, part_table^[act_part]^[i]);
  137. if size(part_table^[new_part]^)<>0 then
  138. begin
  139. (* add new partition: *)
  140. inc(n_parts); inc(n_new_parts);
  141. (* remove new partition from old one: *)
  142. setminus(part_table^[act_part]^, part_table^[new_part]^);
  143. (* update partition assignments: *)
  144. for i := 1 to size(part_table^[new_part]^) do
  145. state_part^[part_table^[new_part]^[i]] := new_part;
  146. inc(new_part);
  147. part_table^[new_part] := newIntSet;
  148. end;
  149. inc(act_part);
  150. end;
  151. until n_new_parts=0;
  152. (* build the optimized state table: *)
  153. n_opt_states := n_parts;
  154. n_opt_trans := 0;
  155. for i := 0 to n_parts-1 do
  156. begin
  157. ii := part_table^[i]^[1];
  158. opt_state_table^[i] := state_table^[ii];
  159. with opt_state_table^[i] do
  160. begin
  161. trans_lo := n_opt_trans+1;
  162. trans_hi := n_opt_trans+1+state_table^[ii].trans_hi-
  163. state_table^[ii].trans_lo;
  164. for j := 2 to size(part_table^[i]^) do
  165. setunion(state_pos^, state_table^[
  166. part_table^[i]^[j]].state_pos^);
  167. end;
  168. for j := state_table^[ii].trans_lo to state_table^[ii].trans_hi do
  169. begin
  170. inc(n_opt_trans);
  171. opt_trans_table^[n_opt_trans] := trans_table^[j];
  172. with opt_trans_table^[n_opt_trans] do
  173. next_state := state_part^[next_state];
  174. end;
  175. end;
  176. (* update state table: *)
  177. n_states := n_opt_states;
  178. n_trans := n_opt_trans;
  179. state_table^ := opt_state_table^;
  180. trans_table^ := opt_trans_table^;
  181. end(*optimizeDFATable*);
  182. begin
  183. new(part_table);
  184. new(state_part);
  185. new(opt_state_table);
  186. new(opt_trans_table);
  187. end(*LexOpt*).