yaccpars.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. {
  2. Yacc parse table construction.
  3. Copyright (c) 1990-92 Albert Graef <[email protected]>
  4. Copyright (C) 1996 Berend de Boer <[email protected]>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. $Revision: 1.2 $
  17. $Modtime: 96-07-31 14:09 $
  18. $History: YACCPARS.PAS $
  19. *
  20. * ***************** Version 2 *****************
  21. * User: Berend Date: 96-10-10 Time: 21:16
  22. * Updated in $/Lex and Yacc/tply
  23. * Updated for protected mode, windows and Delphi 1.X and 2.X.
  24. }
  25. unit YaccPars;
  26. interface
  27. procedure parse_table;
  28. (* Constructs the parse table from the information in the state,
  29. transition and reduction table, and writes parse and rule table
  30. information to the output file.
  31. Rules never reduced are detected, and parsing conflicts resolved
  32. according to the usual disambiguting rules:
  33. - by default, shift/reduce conflicts are resolved in favour of
  34. shift, and reduce/reduce conflicts are resolved in favour of
  35. the rule appearing first in the grammar
  36. - in the presence of precedence information, shift/reduce conflicts
  37. are resolved as follows:
  38. - if the rule has higher precedence than the input symbol,
  39. reduce
  40. - if the input symbol has higher precedence than the rule,
  41. shift
  42. - if rule and input symbol have the same precedence, use
  43. associativity to resolve the conflict: if the symbol is
  44. left-associative, reduce; if right-associative, shift;
  45. if nonassociative, error.
  46. The default action for any state is error, unless the state
  47. only has a single reduce action, and no shift (or nonassoc-induced
  48. error) actions, in which case the default action is the reduction.
  49. An accept action is generated for the shift-endmarker action.
  50. If the verbose option is enabled, the parse_table routine also writes
  51. a readable listing of the generated parser to the .LST file, including
  52. descriptions of parse conflicts and rules never reduced.
  53. Parse table actions are encoded as follows:
  54. - positive: next state (shift or goto action)
  55. - negative: rule to reduce (reduce action)
  56. - 0: error (in default action table) or accept (in shift/reduce
  57. action table)
  58. The tables are written out as a collection of typed array constants:
  59. type YYARec = record { action record }
  60. sym, act : Integer; { symbol and action }
  61. end;
  62. YYRRec = record { rule record }
  63. len, sym : Integer; { length and lhs symbol }
  64. end;
  65. const
  66. yynacts = ...; { number of parse table (shift and reduce) actions }
  67. yyngotos = ...; { number of goto actions }
  68. yynstates = ...; { number of states }
  69. yynrules = ...; { number of rules }
  70. yya : array [1..yynacts] of YYARec = ...;
  71. { shift and reduce actions }
  72. yyg : array [1..yyngotos] of YYARec = ...;
  73. { goto actions }
  74. yyd : array [0..yynstates-1] of Integer = ...;
  75. { default actions }
  76. yyal, yyah,
  77. yygl, yygh : array [0..yynstates-1] of Integer = ...;
  78. { offsets into action and goto table }
  79. yyr : array [1..yynrules] of YYRRec = ...;
  80. *)
  81. var shift_reduce, reduce_reduce, never_reduced : Integer;
  82. (* number of parsing conflicts and unreduced rules detected during
  83. parse table generation *)
  84. implementation
  85. uses YaccBase, YaccTabl;
  86. var reduced : array [1..max_rules] of Boolean;
  87. var yynacts, yyngotos, yynstates : Integer;
  88. yyd : array [0..max_states-1] of Integer;
  89. yyal, yyah, yygl, yygh : array [0..max_states-1] of Integer;
  90. function ruleStr ( i : Integer ) : String;
  91. (* returns print representation of rule number i *)
  92. var str : String; j : Integer;
  93. begin
  94. with rule_table^[i]^ do
  95. begin
  96. str := pname(lhs_sym)+' :';
  97. for j := 1 to rhs_len do
  98. str := str+' '+pname(rhs_sym[j]);
  99. end;
  100. ruleStr := str;
  101. end(*ruleStr*);
  102. function itemStr ( var item_set : ItemSet; i : Integer ) : String;
  103. (* returns print representation of item number i in item_set *)
  104. var str : String; j : Integer;
  105. begin
  106. with item_set, item[i], rule_table^[rule_no]^ do
  107. begin
  108. str := pname(lhs_sym)+' :';
  109. for j := 1 to pos_no-1 do
  110. str := str+' '+pname(rhs_sym[j]);
  111. str := str+' _';
  112. for j := pos_no to rhs_len do
  113. str := str+' '+pname(rhs_sym[j]);
  114. end;
  115. itemStr := str;
  116. end(*itemStr*);
  117. procedure build;
  118. (* build the parse table, resolve conflicts *)
  119. var
  120. i, j, k, s,
  121. n_errors,
  122. n_shifts,
  123. n_gotos,
  124. n_reductions,
  125. n_conflicts : Integer;
  126. item_set : ItemSet;
  127. begin
  128. (* initialize: *)
  129. shift_reduce := 0; reduce_reduce := 0; never_reduced := 0;
  130. for i := 1 to n_rules do reduced[i] := false;
  131. (* traverse the state table: *)
  132. for s := 0 to n_states-1 do with state_table^[s] do
  133. begin
  134. if verbose then
  135. begin
  136. writeln(yylst);
  137. writeln(yylst, 'state ', s, ':');
  138. end;
  139. (* Check shift and reduce actions, resolve conflicts.
  140. The number of error actions generated by nonassoc's is counted
  141. in n_errors, the number of conflicts reported in n_conflicts.
  142. Shift actions ruled out by disambiguating rules are flagged by
  143. setting the corresponding next_state to -1. *)
  144. n_errors := 0; n_conflicts := 0;
  145. for i := trans_lo to trans_hi do with trans_table^[i] do
  146. if sym>=0 then
  147. for j := redns_lo to redns_hi do with redn_table^[j] do
  148. if member(sym, symset^) then
  149. if (sym_prec^[sym]>0) and (rule_prec^[rule_no]>0) then
  150. (* resolve conflict using precedence: *)
  151. if rule_prec^[rule_no]=sym_prec^[sym] then
  152. case prec_table^[sym_prec^[sym]] of
  153. left : (* reduce *)
  154. next_state := -1;
  155. right : (* shift *)
  156. exclude(symset^, sym);
  157. nonassoc : (* error *)
  158. begin
  159. inc(n_errors);
  160. next_state := -1;
  161. exclude(symset^, sym);
  162. end;
  163. end
  164. else if rule_prec^[rule_no]>sym_prec^[sym] then
  165. (* reduce *)
  166. next_state := -1
  167. else
  168. (* shift *)
  169. exclude(symset^, sym)
  170. else
  171. (* shift/reduce conflict: *)
  172. begin
  173. if verbose then
  174. begin
  175. if n_conflicts=0 then
  176. begin
  177. writeln(yylst);
  178. writeln(yylst, tab, '*** conflicts:');
  179. writeln(yylst);
  180. end;
  181. writeln(yylst, tab,
  182. 'shift ', next_state, ', ',
  183. 'reduce ', rule_no-1, ' on ',
  184. pname(sym));
  185. end;
  186. inc(n_conflicts); inc(shift_reduce);
  187. exclude(symset^, sym);
  188. end;
  189. for i := redns_lo to redns_hi do
  190. for j := i+1 to redns_hi do with redn_table^[j] do
  191. begin
  192. for k := 1 to size(symset^) do
  193. if member(symset^[k], redn_table^[i].symset^) then
  194. (* reduce/reduce conflict: *)
  195. begin
  196. if verbose then
  197. begin
  198. if n_conflicts=0 then
  199. begin
  200. writeln(yylst);
  201. writeln(yylst, tab, '*** conflicts:');
  202. writeln(yylst);
  203. end;
  204. writeln(yylst, tab,
  205. 'reduce ',
  206. redn_table^[i].rule_no-1, ', ',
  207. 'reduce ', rule_no-1, ' on ',
  208. pname(symset^[k]));
  209. end;
  210. inc(n_conflicts); inc(reduce_reduce);
  211. end;
  212. setminus(symset^, redn_table^[i].symset^);
  213. end;
  214. (* Count goto, shift and reduce actions to generate. *)
  215. n_gotos := 0; n_shifts := 0; n_reductions := 0;
  216. for i := trans_lo to trans_hi do with trans_table^[i] do
  217. if next_state<>-1 then
  218. if sym<0 then
  219. inc(n_gotos)
  220. else
  221. inc(n_shifts);
  222. for i := redns_lo to redns_hi do with redn_table^[i] do
  223. if size(symset^)>0 then
  224. inc(n_reductions);
  225. (* Determine default action. *)
  226. if (n_shifts+n_errors=0) and (n_reductions=1) then
  227. (* default action is the reduction *)
  228. with redn_table^[redns_lo] do
  229. yyd[s] := -(rule_no-1)
  230. else
  231. (* default action is error *)
  232. yyd[s] := 0;
  233. (* Flag reduced rules. *)
  234. for i := redns_lo to redns_hi do
  235. with redn_table^[i] do
  236. reduced[rule_no] := true;
  237. if verbose then
  238. begin
  239. (* List kernel items. *)
  240. writeln(yylst);
  241. get_item_set(s, item_set);
  242. closure(item_set);
  243. sort_item_set(item_set);
  244. with item_set do
  245. begin
  246. for i := 1 to n_items do
  247. with item[i], rule_table^[rule_no]^ do
  248. if (rule_no=1) or (pos_no>1) or (rhs_len=0) then
  249. if pos_no>rhs_len then
  250. writeln(yylst, tab,
  251. itemStr(item_set, i), tab,
  252. '(', rule_no-1, ')')
  253. else
  254. writeln(yylst, tab, itemStr(item_set, i));
  255. end;
  256. (* List parse actions. *)
  257. (* shift, reduce and default actions: *)
  258. if (n_shifts+n_errors=0) and (n_reductions=1) then
  259. (* default action is the reduction *)
  260. with redn_table^[redns_lo] do
  261. begin
  262. writeln(yylst);
  263. writeln(yylst, tab, '.', tab, 'reduce ', rule_no-1 );
  264. end
  265. else
  266. (* default action is error *)
  267. begin
  268. writeln(yylst);
  269. for i := trans_lo to trans_hi do with trans_table^[i] do
  270. if next_state<>-1 then
  271. if sym=0 then
  272. (* accept action *)
  273. writeln(yylst, tab, pname(sym), tab, 'accept')
  274. else if sym>0 then
  275. (* shift action *)
  276. writeln(yylst, tab,
  277. pname(sym), tab, 'shift ', next_state);
  278. for i := redns_lo to redns_hi do
  279. with redn_table^[i] do
  280. for j := 1 to size(symset^) do
  281. (* reduce action *)
  282. writeln(yylst, tab,
  283. pname(symset^[j]), tab, 'reduce ',
  284. rule_no-1);
  285. (* error action *)
  286. writeln(yylst, tab, '.', tab, 'error');
  287. end;
  288. (* goto actions: *)
  289. if n_gotos>0 then
  290. begin
  291. writeln(yylst);
  292. for i := trans_lo to trans_hi do with trans_table^[i] do
  293. if sym<0 then
  294. writeln(yylst, tab,
  295. pname(sym), tab, 'goto ', next_state);
  296. end;
  297. end;
  298. end;
  299. for i := 2 to n_rules do
  300. if not reduced[i] then inc(never_reduced);
  301. if verbose then
  302. begin
  303. writeln(yylst);
  304. if shift_reduce>0 then
  305. writeln(yylst, shift_reduce, ' shift/reduce conflicts.');
  306. if reduce_reduce>0 then
  307. writeln(yylst, reduce_reduce, ' reduce/reduce conflicts.');
  308. if never_reduced>0 then
  309. writeln(yylst, never_reduced, ' rules never reduced.');
  310. end;
  311. (* report rules never reduced: *)
  312. if (never_reduced>0) and verbose then
  313. begin
  314. writeln(yylst);
  315. writeln(yylst, '*** rules never reduced:');
  316. for i := 2 to n_rules do if not reduced[i] then
  317. begin
  318. writeln(yylst);
  319. writeln(yylst, ruleStr(i), tab, '(', i-1, ')');
  320. end;
  321. end;
  322. end(*build*);
  323. procedure counters;
  324. (* initialize counters and offsets *)
  325. var s, i : Integer;
  326. begin
  327. yynstates := n_states; yynacts := 0; yyngotos := 0;
  328. for s := 0 to n_states-1 do with state_table^[s] do
  329. begin
  330. yyal[s] := yynacts+1; yygl[s] := yyngotos+1;
  331. if yyd[s]=0 then
  332. begin
  333. for i := trans_lo to trans_hi do with trans_table^[i] do
  334. if (sym>=0) and (next_state<>-1) then
  335. inc(yynacts);
  336. for i := redns_lo to redns_hi do with redn_table^[i] do
  337. inc(yynacts, size(symset^));
  338. end;
  339. for i := trans_lo to trans_hi do with trans_table^[i] do
  340. if sym<0 then
  341. inc(yyngotos);
  342. yyah[s] := yynacts; yygh[s] := yyngotos;
  343. end;
  344. end(*counters*);
  345. procedure tables;
  346. (* write tables to output file *)
  347. var s, i, j, count : Integer;
  348. begin
  349. writeln(yyout);
  350. writeln(yyout, 'type YYARec = record');
  351. writeln(yyout, ' sym, act : Integer;');
  352. writeln(yyout, ' end;');
  353. writeln(yyout, ' YYRRec = record');
  354. writeln(yyout, ' len, sym : Integer;');
  355. writeln(yyout, ' end;');
  356. writeln(yyout);
  357. writeln(yyout, 'const');
  358. (* counters: *)
  359. writeln(yyout);
  360. writeln(yyout, 'yynacts = ', yynacts, ';');
  361. writeln(yyout, 'yyngotos = ', yyngotos, ';');
  362. writeln(yyout, 'yynstates = ', yynstates, ';');
  363. writeln(yyout, 'yynrules = ', n_rules-1, ';');
  364. (* shift/reduce table: *)
  365. writeln(yyout);
  366. writeln(yyout, 'yya : array [1..yynacts] of YYARec = (');
  367. count := 0;
  368. for s := 0 to n_states-1 do with state_table^[s] do
  369. begin
  370. writeln(yyout, '{ ', s, ': }');
  371. if yyd[s]=0 then
  372. begin
  373. for i := trans_lo to trans_hi do with trans_table^[i] do
  374. if (next_state<>-1) and (sym>=0) then
  375. begin
  376. inc(count);
  377. if sym=0 then
  378. write(yyout, ' ( sym: 0; act: 0 )')
  379. else
  380. write(yyout, ' ( sym: ', sym, '; act: ',
  381. next_state, ' )');
  382. if count<yynacts then write(yyout, ',');
  383. writeln(yyout);
  384. end;
  385. for i := redns_lo to redns_hi do with redn_table^[i] do
  386. for j := 1 to size(symset^) do
  387. begin
  388. inc(count);
  389. write(yyout, ' ( sym: ', symset^[j], '; act: ',
  390. -(rule_no-1), ' )');
  391. if count<yynacts then write(yyout, ',');
  392. writeln(yyout);
  393. end;
  394. end;
  395. end;
  396. writeln(yyout, ');');
  397. (* goto table: *)
  398. writeln(yyout);
  399. writeln(yyout, 'yyg : array [1..yyngotos] of YYARec = (');
  400. count := 0;
  401. for s := 0 to n_states-1 do with state_table^[s] do
  402. begin
  403. writeln(yyout, '{ ', s, ': }');
  404. for i := trans_lo to trans_hi do with trans_table^[i] do
  405. if sym<0 then
  406. begin
  407. inc(count);
  408. write(yyout, ' ( sym: ', sym, '; act: ', next_state, ' )');
  409. if count<yyngotos then write(yyout, ',');
  410. writeln(yyout);
  411. end;
  412. end;
  413. writeln(yyout, ');');
  414. (* default action table: *)
  415. writeln(yyout);
  416. writeln(yyout, 'yyd : array [0..yynstates-1] of Integer = (');
  417. for s := 0 to n_states-1 do
  418. begin
  419. write(yyout, '{ ', s, ': } ', yyd[s]);
  420. if s<n_states-1 then write(yyout, ',');
  421. writeln(yyout);
  422. end;
  423. writeln(yyout, ');');
  424. (* offset tables: *)
  425. writeln(yyout);
  426. writeln(yyout, 'yyal : array [0..yynstates-1] of Integer = (');
  427. for s := 0 to n_states-1 do
  428. begin
  429. write(yyout, '{ ', s, ': } ', yyal[s]);
  430. if s<n_states-1 then write(yyout, ',');
  431. writeln(yyout);
  432. end;
  433. writeln(yyout, ');');
  434. writeln(yyout);
  435. writeln(yyout, 'yyah : array [0..yynstates-1] of Integer = (');
  436. for s := 0 to n_states-1 do
  437. begin
  438. write(yyout, '{ ', s, ': } ', yyah[s]);
  439. if s<n_states-1 then write(yyout, ',');
  440. writeln(yyout);
  441. end;
  442. writeln(yyout, ');');
  443. writeln(yyout);
  444. writeln(yyout, 'yygl : array [0..yynstates-1] of Integer = (');
  445. for s := 0 to n_states-1 do
  446. begin
  447. write(yyout, '{ ', s, ': } ', yygl[s]);
  448. if s<n_states-1 then write(yyout, ',');
  449. writeln(yyout);
  450. end;
  451. writeln(yyout, ');');
  452. writeln(yyout);
  453. writeln(yyout, 'yygh : array [0..yynstates-1] of Integer = (');
  454. for s := 0 to n_states-1 do
  455. begin
  456. write(yyout, '{ ', s, ': } ', yygh[s]);
  457. if s<n_states-1 then write(yyout, ',');
  458. writeln(yyout);
  459. end;
  460. writeln(yyout, ');');
  461. (* rule table: *)
  462. writeln(yyout);
  463. writeln(yyout, 'yyr : array [1..yynrules] of YYRRec = (');
  464. for i := 2 to n_rules do with rule_table^[i]^ do
  465. begin
  466. write(yyout, '{ ', i-1, ': } ', '( len: ', rhs_len,
  467. '; sym: ', lhs_sym, ' )');
  468. if i<n_rules then write(yyout, ',');
  469. writeln(yyout);
  470. end;
  471. writeln(yyout, ');');
  472. writeln(yyout);
  473. end(*tables*);
  474. procedure parse_table;
  475. begin
  476. build; counters; tables;
  477. end(*parse_table*);
  478. end(*YaccParseTable*).