yaccsem.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. {
  2. Semantic routines for the Yacc parser.
  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-08-01 6:03 $
  18. $History: YACCSEM.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 YaccSem;
  26. interface
  27. var
  28. act_prec : Integer;
  29. (* active precedence level in token and precedence declarations (0 in
  30. %token declaration) *)
  31. act_type : Integer;
  32. (* active type tag in token, precedence and type declarations *)
  33. procedure yyerror ( msg : String );
  34. (* YaccLib.yyerror redefined to ignore 'syntax error' message; the parser
  35. does its own error handling *)
  36. function sym ( k : Integer ) : Integer;
  37. (* returns internal symbol number for the symbol k; if k is yet undefined,
  38. a new nonterminal or literal symbol is created, according to the
  39. appearance of symbol k (nonterminal if an ordinary identifier, literal
  40. otherwise) *)
  41. function ntsym ( k : Integer ) : Integer;
  42. (* like sym, but requires symbol k to be a nonterminal symbol; if it
  43. is already defined a literal, an error message is issued, and a dummy
  44. nonterminal symbol returned *)
  45. function litsym ( k : Integer; n : Integer ) : Integer;
  46. (* same for literal symbols; if n>0 it denotes the literal number to be
  47. assigned to the symbol; when a new literal identifier is defined, a
  48. corresponding constant definition is also written to the definition
  49. file *)
  50. procedure next_section;
  51. (* find next section mark (%%) in code template *)
  52. procedure definitions;
  53. (* if necessary, write out definition of the semantic value type YYSType *)
  54. procedure copy_code;
  55. (* copy Turbo Pascal code section ( %{ ... %} ) to output file *)
  56. procedure copy_action;
  57. (* copy an action to the output file *)
  58. procedure copy_single_action;
  59. (* like copy_action, but action must be single statement terminated
  60. with `;' *)
  61. procedure copy_rest_of_file;
  62. (* copies the rest of the source file to the output file *)
  63. procedure start_rule ( sym : Integer );
  64. (* start a new rule with lhs nonterminal symbol sym *)
  65. procedure start_body;
  66. (* start a new rule body (rhs) *)
  67. procedure end_body;
  68. (* end a rule body *)
  69. procedure add_symbol ( sym : Integer );
  70. (* add the denoted symbol to the current rule body *)
  71. procedure add_action;
  72. (* add an action to the current rule body *)
  73. procedure add_rule_prec ( sym : Integer );
  74. (* add the precedence of terminal symbol sym to the current rule *)
  75. procedure generate_parser;
  76. (* generate the parse table *)
  77. implementation
  78. uses YaccBase, YaccTabl, YaccClos, YaccLR0, YaccLook,
  79. YaccPars, YaccMsgs;
  80. procedure yyerror ( msg : String );
  81. begin
  82. if msg='syntax error' then
  83. (* ignore *)
  84. else
  85. fatal(msg)
  86. end(*yyerror*);
  87. function act_char : char;
  88. begin
  89. if cno>length(line) then
  90. if eof(yyin) then
  91. act_char := #0
  92. else
  93. act_char := nl
  94. else
  95. act_char := line[cno]
  96. end(*act_char*);
  97. function lookahead_char : char;
  98. begin
  99. if succ(cno)>length(line) then
  100. if eof(yyin) then
  101. lookahead_char := #0
  102. else
  103. lookahead_char := nl
  104. else
  105. lookahead_char := line[succ(cno)]
  106. end(*lookahead_char*);
  107. procedure next_char;
  108. begin
  109. if cno>length(line) then
  110. if eof(yyin) then
  111. { nop }
  112. else
  113. begin
  114. readln(yyin, line);
  115. inc(lno); cno := 1
  116. end
  117. else
  118. inc(cno)
  119. end(*next_char*);
  120. var
  121. (* Current rule: *)
  122. act_rule : RuleRec;
  123. (* Actions: *)
  124. n_act : Integer;
  125. p_act : Boolean;
  126. function sym ( k : Integer ) : Integer;
  127. var s : Integer;
  128. begin
  129. if is_def_key(k, s) then
  130. sym := s
  131. else if sym_table^[k].pname^[1]='''' then
  132. begin
  133. s := new_lit;
  134. def_key(k, s);
  135. sym := s;
  136. end
  137. else
  138. begin
  139. s := new_nt;
  140. def_key(k, s);
  141. sym := s;
  142. end
  143. end(*sym*);
  144. function ntsym ( k : Integer ) : Integer;
  145. var s : Integer;
  146. begin
  147. if is_def_key(k, s) then
  148. if s<0 then
  149. ntsym := s
  150. else
  151. begin
  152. error(nonterm_expected);
  153. ntsym := -1;
  154. end
  155. else if sym_table^[k].pname^[1]='''' then
  156. begin
  157. error(nonterm_expected);
  158. ntsym := -1;
  159. end
  160. else
  161. begin
  162. s := new_nt;
  163. def_key(k, s);
  164. ntsym := s;
  165. end
  166. end(*ntsym*);
  167. function litsym ( k : Integer; n : Integer ) : Integer;
  168. var s : Integer;
  169. begin
  170. if is_def_key(k, s) then
  171. if s>=0 then
  172. begin
  173. if n>0 then error(double_tokennum_def);
  174. litsym := s;
  175. end
  176. else
  177. begin
  178. error(literal_expected);
  179. litsym := 1;
  180. end
  181. else if sym_table^[k].pname^[1]='''' then
  182. begin
  183. if n>0 then
  184. begin
  185. add_lit(n);
  186. s := n;
  187. end
  188. else
  189. s := new_lit;
  190. def_key(k, s);
  191. litsym := s;
  192. end
  193. else
  194. begin
  195. if n>0 then
  196. begin
  197. add_lit(n);
  198. s := n;
  199. end
  200. else
  201. s := new_lit;
  202. def_key(k, s);
  203. writeln(yyout, 'const ', pname(s), ' = ', s, ';');
  204. litsym := s;
  205. end;
  206. end(*litsym*);
  207. procedure next_section;
  208. var line : String;
  209. begin
  210. while not eof(yycod) do
  211. begin
  212. readln(yycod, line);
  213. if line='%%' then exit;
  214. writeln(yyout, line);
  215. end;
  216. end(*next_section*);
  217. procedure definitions;
  218. var i : Integer;
  219. begin
  220. if n_types>0 then
  221. begin
  222. writeln(yyout);
  223. writeln(yyout, 'type YYSType = record case Integer of');
  224. for i := 1 to n_types do
  225. writeln(yyout, ' ':15, i:3, ' : ( ',
  226. 'yy', sym_table^[type_table^[i]].pname^, ' : ',
  227. sym_table^[type_table^[i]].pname^, ' );');
  228. writeln(yyout, ' ':15, 'end(*YYSType*);');
  229. end;
  230. end(*definitions*);
  231. procedure copy_code;
  232. var str_state : Boolean;
  233. begin
  234. str_state := false;
  235. while act_char<>#0 do
  236. if act_char=nl then
  237. begin
  238. writeln(yyout);
  239. next_char;
  240. end
  241. else if act_char='''' then
  242. begin
  243. write(yyout, '''');
  244. str_state := not str_state;
  245. next_char;
  246. end
  247. else if not str_state and (act_char='%') and (lookahead_char='}') then
  248. exit
  249. else
  250. begin
  251. write(yyout, act_char);
  252. next_char;
  253. end;
  254. end(*copy_code*);
  255. procedure scan_val;
  256. (* process a $ value in an action
  257. (not very pretty, but it does its job) *)
  258. var tag, numstr : String; i, code : Integer;
  259. begin
  260. tokleng := 0;
  261. next_char;
  262. if act_char='<' then
  263. begin
  264. (* process type tag: *)
  265. next_char;
  266. tag := '';
  267. while (act_char<>nl) and (act_char<>#0) and (act_char<>'>') do
  268. begin
  269. tag := tag+act_char;
  270. next_char;
  271. end;
  272. if act_char='>' then
  273. begin
  274. if not search_type(tag) then
  275. begin
  276. tokleng := length(tag);
  277. error(unknown_identifier);
  278. end;
  279. next_char;
  280. end
  281. else
  282. error(syntax_error);
  283. end
  284. else
  285. tag := '';
  286. tokleng := 0;
  287. if act_char='$' then
  288. begin
  289. (* left-hand side value: *)
  290. write(yyout, 'yyval');
  291. (* check for value type: *)
  292. if (tag='') and (n_types>0) then with act_rule do
  293. if sym_type^[lhs_sym]>0 then
  294. tag := sym_table^[sym_type^[lhs_sym]].pname^
  295. else
  296. begin
  297. tokleng := 1;
  298. error(type_error);
  299. end;
  300. if tag<>'' then write(yyout, '.yy', tag);
  301. next_char;
  302. end
  303. else
  304. begin
  305. (* right-hand side value: *)
  306. if act_char='-' then
  307. begin
  308. numstr := '-';
  309. next_char;
  310. end
  311. else
  312. numstr := '';
  313. while ('0'<=act_char) and (act_char<='9') do
  314. begin
  315. numstr := numstr+act_char;
  316. next_char;
  317. end;
  318. if numstr<>'' then
  319. begin
  320. val(numstr, i, code);
  321. if code=0 then
  322. if i<=act_rule.rhs_len then
  323. begin
  324. write(yyout, 'yyv[yysp-', act_rule.rhs_len-i, ']');
  325. (* check for value type: *)
  326. if (tag='') and (n_types>0) then with act_rule do
  327. if i<=0 then
  328. begin
  329. tokleng := length(numstr)+1;
  330. error(type_error);
  331. end
  332. else if sym_type^[rhs_sym[i]]>0 then
  333. tag := sym_table^[sym_type^[rhs_sym[i]]].pname^
  334. else
  335. begin
  336. tokleng := length(numstr)+1;
  337. error(type_error);
  338. end;
  339. if tag<>'' then write(yyout, '.yy', tag);
  340. end
  341. else
  342. begin
  343. tokleng := length(numstr);
  344. error(range_error);
  345. end
  346. else
  347. error(syntax_error)
  348. end
  349. else
  350. error(syntax_error)
  351. end
  352. end(*scan_val*);
  353. procedure copy_action;
  354. var str_state : Boolean;
  355. begin
  356. str_state := false;
  357. while act_char=' ' do next_char;
  358. write(yyout, ' ':9);
  359. while act_char<>#0 do
  360. if act_char=nl then
  361. begin
  362. writeln(yyout);
  363. next_char;
  364. while act_char=' ' do next_char;
  365. write(yyout, ' ':9);
  366. end
  367. else if act_char='''' then
  368. begin
  369. write(yyout, '''');
  370. str_state := not str_state;
  371. next_char;
  372. end
  373. else if not str_state and (act_char='}') then
  374. begin
  375. writeln(yyout);
  376. exit;
  377. end
  378. else if not str_state and (act_char='$') then
  379. scan_val
  380. else
  381. begin
  382. write(yyout, act_char);
  383. next_char;
  384. end;
  385. end(*copy_action*);
  386. procedure copy_single_action;
  387. var str_state : Boolean;
  388. begin
  389. str_state := false;
  390. while act_char=' ' do next_char;
  391. write(yyout, ' ':9);
  392. while act_char<>#0 do
  393. if act_char=nl then
  394. begin
  395. writeln(yyout);
  396. next_char;
  397. while act_char=' ' do next_char;
  398. write(yyout, ' ':9);
  399. end
  400. else if act_char='''' then
  401. begin
  402. write(yyout, '''');
  403. str_state := not str_state;
  404. next_char;
  405. end
  406. else if not str_state and (act_char=';') then
  407. begin
  408. writeln(yyout, ';');
  409. exit;
  410. end
  411. else if not str_state and (act_char='$') then
  412. scan_val
  413. else
  414. begin
  415. write(yyout, act_char);
  416. next_char;
  417. end;
  418. end(*copy_single_action*);
  419. procedure copy_rest_of_file;
  420. begin
  421. while act_char<>#0 do
  422. if act_char=nl then
  423. begin
  424. writeln(yyout);
  425. next_char;
  426. end
  427. else
  428. begin
  429. write(yyout, act_char);
  430. next_char;
  431. end;
  432. end(*copy_rest_of_file*);
  433. procedure start_rule ( sym : Integer );
  434. begin
  435. if n_rules=0 then
  436. begin
  437. (* fix start nonterminal of the grammar: *)
  438. if startnt=0 then startnt := sym;
  439. (* add augmented start production: *)
  440. with act_rule do
  441. begin
  442. lhs_sym := -1;
  443. rhs_len := 2;
  444. rhs_sym[1] := startnt;
  445. rhs_sym[2] := 0; (* end marker *)
  446. end;
  447. add_rule(newRuleRec(act_rule));
  448. end;
  449. act_rule.lhs_sym := sym;
  450. end(*start_rule*);
  451. procedure start_body;
  452. begin
  453. act_rule.rhs_len := 0;
  454. p_act := false;
  455. writeln(yyout, n_rules:4, ' : begin');
  456. end(*start_body*);
  457. procedure end_body;
  458. begin
  459. if not p_act and (act_rule.rhs_len>0) then
  460. (* add default action: *)
  461. writeln(yyout, ' ':9, 'yyval := yyv[yysp-',
  462. act_rule.rhs_len-1, '];');
  463. add_rule(newRuleRec(act_rule));
  464. writeln(yyout, ' ':7, 'end;');
  465. end(*end_body*);
  466. procedure add_rule_action;
  467. (* process an action inside a rule *)
  468. var k : Integer; r : RuleRec;
  469. begin
  470. writeln(yyout, ' ':7, 'end;');
  471. inc(n_act);
  472. k := get_key('$$'+intStr(n_act));
  473. with r do
  474. begin
  475. lhs_sym := new_nt;
  476. def_key(k, lhs_sym);
  477. rhs_len := 0;
  478. end;
  479. with act_rule do
  480. begin
  481. inc(rhs_len);
  482. if rhs_len>max_rule_len then fatal(rule_table_overflow);
  483. rhs_sym[rhs_len] := r.lhs_sym;
  484. end;
  485. add_rule(newRuleRec(r));
  486. rule_prec^[n_rules+1] := rule_prec^[n_rules];
  487. rule_prec^[n_rules] := 0;
  488. writeln(yyout, n_rules:4, ' : begin');
  489. end(*add_rule_action*);
  490. procedure add_symbol ( sym : Integer );
  491. begin
  492. if p_act then add_rule_action;
  493. p_act := false;
  494. with act_rule do
  495. begin
  496. inc(rhs_len);
  497. if rhs_len>max_rule_len then fatal(rule_table_overflow);
  498. rhs_sym[rhs_len] := sym;
  499. if sym>=0 then rule_prec^[n_rules+1] := sym_prec^[sym]
  500. end
  501. end(*add_symbol*);
  502. procedure add_action;
  503. begin
  504. if p_act then add_rule_action;
  505. p_act := true;
  506. end(*add_action*);
  507. procedure add_rule_prec ( sym : Integer );
  508. begin
  509. rule_prec^[n_rules+1] := sym_prec^[sym];
  510. end(*add_rule_prec*);
  511. procedure generate_parser;
  512. begin
  513. if startnt=0 then error(empty_grammar);
  514. if errors=0 then
  515. begin
  516. write('sort ... ');
  517. sort_rules; rule_offsets;
  518. write('closures ... ');
  519. closures;
  520. write('first sets ... ');
  521. first_sets;
  522. write('LR0 set ... ');
  523. LR0Set;
  524. write('lookaheads ... ');
  525. lookaheads;
  526. writeln;
  527. write('code generation ... ');
  528. parse_table;
  529. end;
  530. end(*generate_parser*);
  531. begin
  532. n_act := 0;
  533. end(*YaccSem*).