pyacc.y 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. /* YACC.Y: Yacc grammar for Yacc main program. 2-17-91, 4-30-91 AG
  2. To bootstrap Yacc, use Yacc iself to compile this grammar, then
  3. run tpc on the generated program.
  4. Note:
  5. This is not entirely the `official' syntax introduced by Johnson, but it
  6. should be compatible with UNIX Yacc (except for the differences specified
  7. in the program header, below), as described in the UNIX manual, including
  8. the language elements entitled as "old features supported but not
  9. encouraged."
  10. Bugs:
  11. - Processes $$'s, $i's, %} and } inside of comments in Turbo Pascal code
  12. (instead of ignoring them).
  13. Shift/reduce conflicts:
  14. This grammar will produce a number of shift/reduce conflicts caused by
  15. the error productions, since it does not specify unambigiously whether
  16. errors are to be handled in global structures (definitions and rules)
  17. or by enclosed syntactic constructs (e.g. symbols). Yacc will resolve
  18. these conflicts in favour of shift, which is o.k. (it means that
  19. errors will be caught in the innermost constructs with error handling,
  20. thus reducing the amount of skipped symbols in resynchronization).
  21. Error handling is done using the general method of Schreiner/Friedman
  22. (see Schreiner/Friedman, "Introduction to compiler construction with
  23. UNIX," 1985).
  24. */
  25. %{
  26. (*
  27. TP Yacc - Yet Another Compiler Compiler for Turbo Pascal
  28. Copyright (C) 1990-92 Albert Graef <[email protected]>
  29. Copyright (C) 1996 Berend de Boer <[email protected]>
  30. This program is free software; you can redistribute it and/or modify
  31. it under the terms of the GNU General Public License as published by
  32. the Free Software Foundation; either version 2 of the License, or
  33. (at your option) any later version.
  34. This program is distributed in the hope that it will be useful,
  35. but WITHOUT ANY WARRANTY; without even the implied warranty of
  36. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  37. GNU General Public License for more details.
  38. You should have received a copy of the GNU General Public License
  39. along with this program; if not, write to the Free Software
  40. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  41. $Revision: 1.5 $
  42. $Modtime: 96-08-01 11:24 $
  43. Last changes:
  44. Version 3.0 as of April 91
  45. Version 3.0a as of May 92 (bug fixes in precedence and type information
  46. updates)
  47. $History: YACC.PAS $
  48. *
  49. * ***************** Version 2 *****************
  50. * User: Berend Date: 96-10-10 Time: 21:16
  51. * Updated in $/Lex and Yacc/tply
  52. * Updated for protected mode, windows and Delphi 1.X and 2.X.
  53. ------------------------- Synopsis ------------------------
  54. Synopsis yacc [options] yacc-file[.y] [output-file[.pas]]
  55. Options
  56. -v "Verbose:" Yacc generates a readable description of the generated
  57. parser, written to yacc-file with new extension .lst.
  58. -d "Debug:" Yacc generates parser with debugging output.
  59. Description
  60. This is a reimplementation of the popular UNIX compiler generator
  61. Yacc for MS-DOS and Turbo Pascal.
  62. Differences from UNIX Yacc:
  63. - Produces output code for Turbo Pascal, rather than for C.
  64. - Does not support %union definitions. Instead, a value type is declared
  65. by specifying the type identifier *itself* as the tag of a %token
  66. or %type definition. Yacc will automatically generate an appropriate
  67. yylval variable of a variant record type (YYSType) which is capable of
  68. holding values of any of the types used in %token and %type.
  69. Type checking is *very* strict. If you use type definitions, then
  70. any symbol referred to in an action *must* have a type introduced
  71. in a type definition. Either the symbol must have been assigned a
  72. type in the definitions section, or the $<type-identifier> notation
  73. must be used. The syntax of the %type definition has been changed
  74. slightly to allow definitions of the form
  75. %type <type-identifier>
  76. (omitting the nonterminals) which may be used to declare types which
  77. are not assigned to any grammar symbol, but are used with the
  78. $<...> construct.
  79. - The parse tables constructed by this Yacc version are slightly greater
  80. than those constructed by UNIX Yacc, since a reduce action will only be
  81. chosen as the default action if it is the *only* action in the state.
  82. In difference, UNIX Yacc chooses a reduce action as the default action
  83. whenever it is the only *reduce* action of the state (even if there are
  84. other shift actions).
  85. This solves a bug in UNIX Yacc that makes the generated parser start
  86. error recovery too late with certain types of error productions (see
  87. also Schreiner/Friedman, "Introduction to compiler construction with
  88. UNIX," 1985). Also, errors will be caught sooner in most cases where
  89. standard Yacc would carry out an additional (default) reduction before
  90. detecting the error.
  91. ------------------------- Synopsis ------------------------
  92. *)
  93. {$X+}
  94. {$I-}
  95. program Yacc;
  96. uses
  97. {$IFDEF Debug}
  98. {$IFDEF DPMI}
  99. { YaccChk, removed as obsolete,
  100. YaccChk source not available anymore PM }
  101. {$ENDIF}
  102. {$ENDIF}
  103. YaccLib, YaccBase, YaccMsgs, YaccSem, YaccTabl, YaccPars, SysUtils;
  104. %}
  105. /* Lexical part of the Yacc language: */
  106. %token
  107. ID /* identifiers: {letter}{letter_or_digit}* */
  108. C_ID /* identifier which forms left side of rule, i.e. is
  109. followed by a colon */
  110. LITERAL /* single character literal */
  111. LITID /* multiple character literal */
  112. NUMBER /* nonnegative integers: {digit}+ */
  113. PTOKEN PLEFT PRIGHT PNONASSOC PTYPE PSTART PPREC
  114. /* reserved words: PTOKEN=%token, etc. */
  115. PP /* source sections separator %% */
  116. LCURL /* curly braces: %{ and %} */
  117. RCURL
  118. ',' ':' ';' '|' '{' '}' '<' '>' '='
  119. /* literals */
  120. ILLEGAL /* illegal input character */
  121. %start grammar
  122. %%
  123. /* Lexical entities, those that may give rise to syntax errors are augmented
  124. with error productions, and important symbols call yyerrok. */
  125. id : ID
  126. c_id : C_ID
  127. literal : LITERAL
  128. litid : LITID
  129. number : NUMBER
  130. ptoken : PTOKEN { yyerrok; }
  131. pleft : PLEFT { yyerrok; }
  132. pright : PRIGHT { yyerrok; }
  133. pnonassoc : PNONASSOC { yyerrok; }
  134. ptype : PTYPE { yyerrok; }
  135. pstart : PSTART { yyerrok; }
  136. pprec : PPREC
  137. pp : PP { yyerrok; }
  138. lcurl : LCURL
  139. rcurl : RCURL
  140. | error { error(rcurl_expected); }
  141. comma : ','
  142. colon : ':' { yyerrok; }
  143. semicolon : ';' { yyerrok; }
  144. bar : '|' { yyerrok; }
  145. lbrace : '{'
  146. rbrace : '}'
  147. | error { error(rbrace_expected); }
  148. langle : '<'
  149. rangle : '>'
  150. | error { error(rangle_expected); }
  151. eq : '='
  152. /* Syntax and semantic routines: */
  153. grammar : defs pp
  154. { sort_types;
  155. definitions;
  156. next_section; }
  157. rules
  158. { next_section;
  159. generate_parser;
  160. next_section; }
  161. aux_procs
  162. ;
  163. aux_procs : /* empty: aux_procs is optional */
  164. | pp { copy_rest_of_file; }
  165. ;
  166. defs : /* empty */
  167. | defs def { yyerrok; }
  168. | defs error { error(error_in_def); }
  169. ;
  170. def : pstart id
  171. { startnt := ntsym($2); }
  172. | pstart error
  173. { error(ident_expected); }
  174. | lcurl { copy_code; } rcurl
  175. | ptoken
  176. { act_prec := 0; }
  177. tag token_list
  178. | pleft
  179. { act_prec := new_prec_level(left); }
  180. tag token_list
  181. | pright
  182. { act_prec := new_prec_level(right); }
  183. tag token_list
  184. | pnonassoc
  185. { act_prec := new_prec_level(nonassoc); }
  186. tag token_list
  187. | ptype tag nonterm_list
  188. | ptype tag
  189. ;
  190. tag : /* empty: type tag is optional */
  191. { act_type := 0; }
  192. | langle id rangle
  193. { act_type := $2; add_type($2); }
  194. ;
  195. token_list : token_num
  196. | token_list token_num
  197. { yyerrok; }
  198. | token_list comma token_num
  199. { yyerrok; }
  200. | error
  201. { error(ident_expected); }
  202. | token_list error
  203. { error(error_in_def); }
  204. | token_list comma error
  205. { error(ident_expected); }
  206. ;
  207. token_num : literal
  208. { if act_type<>0 then
  209. sym_type^[$1] := act_type;
  210. if act_prec<>0 then
  211. sym_prec^[$1] := act_prec; }
  212. | litid
  213. { litsym($1, 0);
  214. if act_type<>0 then
  215. sym_type^[litsym($1, 0)] := act_type;
  216. if act_prec<>0 then
  217. sym_prec^[litsym($1, 0)] := act_prec; }
  218. | id
  219. { litsym($1, 0);
  220. if act_type<>0 then
  221. sym_type^[litsym($1, 0)] := act_type;
  222. if act_prec<>0 then
  223. sym_prec^[litsym($1, 0)] := act_prec; }
  224. | litid number
  225. { litsym($1, 0);
  226. if act_type<>0 then
  227. sym_type^[litsym($1, $2)] := act_type;
  228. if act_prec<>0 then
  229. sym_prec^[litsym($1, 0)] := act_prec; }
  230. | id number
  231. { litsym($1, 0);
  232. if act_type<>0 then
  233. sym_type^[litsym($1, $2)] := act_type;
  234. if act_prec<>0 then
  235. sym_prec^[litsym($1, 0)] := act_prec; }
  236. ;
  237. nonterm_list : nonterm
  238. | nonterm_list nonterm
  239. { yyerrok; }
  240. | nonterm_list comma nonterm
  241. { yyerrok; }
  242. | error
  243. { error(ident_expected); }
  244. | nonterm_list error
  245. { error(error_in_def); }
  246. | nonterm_list comma error
  247. { error(ident_expected); }
  248. ;
  249. nonterm : id
  250. { if act_type<>0 then
  251. sym_type^[ntsym($1)] := act_type; }
  252. ;
  253. rules : { next_section; }
  254. rule1
  255. | lcurl { copy_code; } rcurl
  256. { next_section; }
  257. rule1
  258. /* rules section may be prefixed
  259. with `local' Turbo Pascal
  260. declarations */
  261. | rules rule
  262. { yyerrok; }
  263. | error
  264. { error(error_in_rule); }
  265. | rules error
  266. { error(error_in_rule); }
  267. ;
  268. rule1 : c_id
  269. { start_rule(ntsym($1)); }
  270. colon
  271. { start_body; }
  272. body prec
  273. { end_body; }
  274. ;
  275. rule : rule1
  276. | bar
  277. { start_body; }
  278. body prec
  279. { end_body; }
  280. ;
  281. body : /* empty */
  282. | body literal
  283. { add_symbol($2); yyerrok; }
  284. | body litid
  285. { add_symbol(sym($2)); yyerrok; }
  286. | body id
  287. { add_symbol(sym($2)); yyerrok; }
  288. | body action
  289. { add_action; yyerrok; }
  290. | body error
  291. { error(error_in_rule); }
  292. ;
  293. action : lbrace { copy_action; } rbrace
  294. | eq { copy_single_action; }
  295. /* old language feature; code must be
  296. single statement ending with `;' */
  297. ;
  298. prec : /* empty */
  299. | pprec literal
  300. { add_rule_prec($2); }
  301. opt_action
  302. | pprec litid
  303. { add_rule_prec(litsym($2, 0)); }
  304. opt_action
  305. | pprec id
  306. { add_rule_prec(litsym($2, 0)); }
  307. opt_action
  308. | prec semicolon
  309. ;
  310. opt_action : /* empty */
  311. | action
  312. { add_action; }
  313. ;
  314. %%
  315. (* Lexical analyzer (implemented in Turbo Pascal for maximum efficiency): *)
  316. function yylex : integer;
  317. function end_of_input : boolean;
  318. begin
  319. end_of_input := (cno>length(line)) and eof(yyin)
  320. end(*end_of_input*);
  321. procedure scan;
  322. (* scan for nonempty character, skip comments *)
  323. procedure scan_comment;
  324. var p : integer;
  325. begin
  326. p := pos('*/', copy(line, cno, length(line)));
  327. if p>0 then
  328. cno := cno+succ(p)
  329. else
  330. begin
  331. while (p=0) and not eof(yyin) do
  332. begin
  333. readln(yyin, line);
  334. inc(lno);
  335. p := pos('*/', line)
  336. end;
  337. if p=0 then
  338. begin
  339. cno := succ(length(line));
  340. error(open_comment_at_eof);
  341. end
  342. else
  343. cno := succ(succ(p))
  344. end
  345. end(*scan_comment*);
  346. begin
  347. while not end_of_input do
  348. if cno<=length(line) then
  349. case line[cno] of
  350. ' ', tab : inc(cno);
  351. '/' :
  352. if (cno<length(line)) and (line[succ(cno)]='*') then
  353. begin
  354. inc(cno, 2);
  355. scan_comment
  356. end
  357. else
  358. exit
  359. else
  360. exit
  361. end
  362. else
  363. begin
  364. readln(yyin, line);
  365. inc(lno); cno := 1;
  366. end
  367. end(*scan*);
  368. function scan_ident : integer;
  369. (* scan an identifier *)
  370. var
  371. idstr : String;
  372. begin
  373. idstr := line[cno];
  374. inc(cno);
  375. while (cno<=length(line)) and (
  376. ('A'<=upCase(line[cno])) and (upCase(line[cno])<='Z') or
  377. ('0'<=line[cno]) and (line[cno]<='9') or
  378. (line[cno]='_') or
  379. (line[cno]='.') ) do
  380. begin
  381. idstr := idstr+line[cno];
  382. inc(cno)
  383. end;
  384. yylval := get_key(idstr);
  385. scan;
  386. if not end_of_input and (line[cno]=':') then
  387. scan_ident := C_ID
  388. else
  389. scan_ident := ID
  390. end(*scan_ident*);
  391. function scan_literal: integer;
  392. (* scan a literal, i.e. string *)
  393. var
  394. idstr : String;
  395. oct_val : Byte;
  396. begin
  397. idstr := line[cno];
  398. inc(cno);
  399. while (cno<=length(line)) and (line[cno]<>idstr[1]) do
  400. if line[cno]='\' then
  401. if cno<length(line) then
  402. begin
  403. inc(cno);
  404. case line[cno] of
  405. 'n' :
  406. begin
  407. idstr := idstr+nl;
  408. inc(cno)
  409. end;
  410. 'r' :
  411. begin
  412. idstr := idstr+cr;
  413. inc(cno)
  414. end;
  415. 't' :
  416. begin
  417. idstr := idstr+tab;
  418. inc(cno)
  419. end;
  420. 'b' :
  421. begin
  422. idstr := idstr+bs;
  423. inc(cno)
  424. end;
  425. 'f' :
  426. begin
  427. idstr := idstr+ff;
  428. inc(cno)
  429. end;
  430. '0'..'7' :
  431. begin
  432. oct_val := ord(line[cno])-ord('0');
  433. inc(cno);
  434. while (cno<=length(line)) and
  435. ('0'<=line[cno]) and
  436. (line[cno]<='7') do
  437. begin
  438. oct_val := oct_val*8+ord(line[cno])-ord('0');
  439. inc(cno)
  440. end;
  441. idstr := idstr+chr(oct_val)
  442. end
  443. else
  444. begin
  445. idstr := idstr+line[cno];
  446. inc(cno)
  447. end
  448. end
  449. end
  450. else
  451. inc(cno)
  452. else
  453. begin
  454. idstr := idstr+line[cno];
  455. inc(cno)
  456. end;
  457. if cno>length(line) then
  458. error(missing_string_terminator)
  459. else
  460. inc(cno);
  461. if length(idstr)=2 then
  462. begin
  463. yylval := ord(idstr[2]);
  464. scan_literal := LITERAL;
  465. end
  466. else if length(idstr)>1 then
  467. begin
  468. yylval := get_key(''''+copy(idstr, 2, pred(length(idstr)))+'''');
  469. scan_literal := LITID;
  470. end
  471. else
  472. scan_literal := ILLEGAL;
  473. end(*scan_literal*);
  474. function scan_num : integer;
  475. (* scan an unsigned integer *)
  476. var
  477. numstr : String;
  478. code : integer;
  479. begin
  480. numstr := line[cno];
  481. inc(cno);
  482. while (cno<=length(line)) and
  483. ('0'<=line[cno]) and (line[cno]<='9') do
  484. begin
  485. numstr := numstr+line[cno];
  486. inc(cno)
  487. end;
  488. val(numstr, yylval, code);
  489. if code=0 then
  490. scan_num := NUMBER
  491. else
  492. scan_num := ILLEGAL;
  493. end(*scan_num*);
  494. function scan_keyword : integer;
  495. (* scan %xy *)
  496. function lookup(key : String; var tok : integer) : boolean;
  497. (* table of Yacc keywords (unstropped): *)
  498. const
  499. no_of_entries = 11;
  500. max_entry_length = 8;
  501. keys : array [1..no_of_entries] of String[max_entry_length] = (
  502. '0', '2', 'binary', 'left', 'nonassoc', 'prec', 'right',
  503. 'start', 'term', 'token', 'type');
  504. toks : array [1..no_of_entries] of integer = (
  505. PTOKEN, PNONASSOC, PNONASSOC, PLEFT, PNONASSOC, PPREC, PRIGHT,
  506. PSTART, PTOKEN, PTOKEN, PTYPE);
  507. var m, n, k : integer;
  508. begin
  509. (* binary search: *)
  510. m := 1; n := no_of_entries;
  511. lookup := true;
  512. while m<=n do
  513. begin
  514. k := m+(n-m) div 2;
  515. if key=keys[k] then
  516. begin
  517. tok := toks[k];
  518. exit
  519. end
  520. else if key>keys[k] then
  521. m := k+1
  522. else
  523. n := k-1
  524. end;
  525. lookup := false
  526. end(*lookup*);
  527. var
  528. keywstr : String;
  529. tok : integer;
  530. begin
  531. inc(cno);
  532. if cno<=length(line) then
  533. case line[cno] of
  534. '<' :
  535. begin
  536. scan_keyword := PLEFT;
  537. inc(cno)
  538. end;
  539. '>' :
  540. begin
  541. scan_keyword := PRIGHT;
  542. inc(cno)
  543. end;
  544. '=' :
  545. begin
  546. scan_keyword := PPREC;
  547. inc(cno)
  548. end;
  549. '%', '\' :
  550. begin
  551. scan_keyword := PP;
  552. inc(cno)
  553. end;
  554. '{' :
  555. begin
  556. scan_keyword := LCURL;
  557. inc(cno)
  558. end;
  559. '}' :
  560. begin
  561. scan_keyword := RCURL;
  562. inc(cno)
  563. end;
  564. 'A'..'Z', 'a'..'z', '0'..'9' :
  565. begin
  566. keywstr := line[cno];
  567. inc(cno);
  568. while (cno<=length(line)) and (
  569. ('A'<=upCase(line[cno])) and (upCase(line[cno])<='Z') or
  570. ('0'<=line[cno]) and (line[cno]<='Z') ) do
  571. begin
  572. keywstr := keywstr+line[cno];
  573. inc(cno)
  574. end;
  575. if lookup(keywstr, tok) then
  576. scan_keyword := tok
  577. else
  578. scan_keyword := ILLEGAL
  579. end;
  580. else scan_keyword := ILLEGAL
  581. end
  582. else
  583. scan_keyword := ILLEGAL;
  584. end(*scan_keyword*);
  585. function scan_char : integer;
  586. (* scan any single character *)
  587. begin
  588. scan_char := ord(line[cno]);
  589. inc(cno)
  590. end(*scan_char*);
  591. var lno0, cno0 : integer;
  592. begin
  593. tokleng := 0;
  594. scan;
  595. lno0 := lno; cno0 := cno;
  596. if end_of_input then
  597. yylex := 0
  598. else
  599. case line[cno] of
  600. 'A'..'Z', 'a'..'z', '_' : yylex := scan_ident;
  601. '''', '"' : yylex := scan_literal;
  602. '0'..'9' : yylex := scan_num;
  603. '%', '\' : yylex := scan_keyword;
  604. '=' :
  605. if (cno<length(line)) and (line[succ(cno)]='{') then
  606. begin
  607. inc(cno);
  608. yylex := scan_char
  609. end
  610. else
  611. yylex := scan_char;
  612. else yylex := scan_char;
  613. end;
  614. if lno=lno0 then
  615. tokleng := cno-cno0
  616. end(*yylex*);
  617. (* Main program: *)
  618. var i : Integer;
  619. begin
  620. {$ifdef Unix}
  621. codfilepath1:=path(paramstr(0));
  622. if (codfilepath1<>'') then
  623. codfilepath1:=codfilepath1+'../lib/fpc/lexyacc/'
  624. else
  625. codfilepath1:='/usr/local/lib/fpc/lexyacc/';
  626. codfilepath2:='/usr/lib/fpc/lexyacc/';
  627. {$else}
  628. codfilepath1:=path(paramstr(0));
  629. codfilepath2:='';
  630. {$endif}
  631. (* sign-on: *)
  632. writeln(sign_on);
  633. (* parse command line: *)
  634. if paramCount=0 then
  635. begin
  636. writeln(usage);
  637. writeln(options);
  638. halt(0);
  639. end;
  640. yfilename := '';
  641. pasfilename := '';
  642. for i := 1 to paramCount do
  643. if copy(paramStr(i), 1, 1)='-' then
  644. if upper(paramStr(i))='-V' then
  645. verbose := true
  646. else if upper(paramStr(i))='-D' then
  647. debug := true
  648. else
  649. begin
  650. writeln(invalid_option, paramStr(i));
  651. halt(1);
  652. end
  653. else if yfilename='' then
  654. yfilename := addExt(paramStr(i), 'y')
  655. else if pasfilename='' then
  656. pasfilename := addExt(paramStr(i), 'pas')
  657. else
  658. begin
  659. writeln(illegal_no_args);
  660. halt(1);
  661. end;
  662. if yfilename='' then
  663. begin
  664. writeln(illegal_no_args);
  665. halt(1);
  666. end;
  667. if pasfilename='' then pasfilename := root(yfilename)+'.pas';
  668. lstfilename := root(yfilename)+'.lst';
  669. (* open files: *)
  670. assign(yyin, yfilename);
  671. assign(yyout, pasfilename);
  672. assign(yylst, lstfilename);
  673. reset(yyin); if ioresult<>0 then fatal(cannot_open_file+yfilename);
  674. rewrite(yyout); if ioresult<>0 then fatal(cannot_open_file+pasfilename);
  675. rewrite(yylst); if ioresult<>0 then fatal(cannot_open_file+lstfilename);
  676. (* search code template *)
  677. codfilename := 'yyparse.cod';
  678. assign(yycod, codfilename);
  679. reset(yycod);
  680. if ioresult<>0 then
  681. begin
  682. codfilename := IncludeTrailingPathDelimiter(GetEnvironmentVariable('FPCDIR'))+'lexyacc'+DirectorySeparator+'yyparse.cod';
  683. assign(yycod, codfilename);
  684. reset(yycod);
  685. if ioresult<>0 then
  686. begin
  687. codfilename := codfilepath1+'yyparse.cod';
  688. assign(yycod, codfilename);
  689. reset(yycod);
  690. if (codfilepath2<>'') and (ioresult<>0) then
  691. begin
  692. codfilename := codfilepath2+'yyparse.cod';
  693. assign(yycod, codfilename);
  694. reset(yycod);
  695. if ioresult<>0 then
  696. fatal(cannot_open_file+codfilename);
  697. end;
  698. end;
  699. end;
  700. (* parse source grammar: *)
  701. write('parse ... ');
  702. lno := 0; cno := 1; line := '';
  703. next_section;
  704. if debug then writeln(yyout, '{$define yydebug}');
  705. if yyparse=0 then
  706. { done }
  707. else if yychar=0 then
  708. error(unexpected_eof)
  709. else
  710. error(syntax_error);
  711. if errors=0 then writeln('DONE');
  712. (* close files: *)
  713. close(yyin); close(yyout); close(yylst); close(yycod);
  714. (* print statistics: *)
  715. if errors>0 then
  716. writeln( lno, ' lines, ',
  717. errors, ' errors found.' )
  718. else
  719. begin
  720. writeln( lno, ' lines, ',
  721. n_rules-1, '/', max_rules-1, ' rules, ',
  722. n_states, '/', max_states, ' s, ',
  723. n_items, '/', max_items, ' i, ',
  724. n_trans, '/', max_trans, ' t, ',
  725. n_redns, '/', max_redns, ' r.');
  726. if shift_reduce>0 then
  727. writeln(shift_reduce, ' shift/reduce conflicts.');
  728. if reduce_reduce>0 then
  729. writeln(reduce_reduce, ' reduce/reduce conflicts.');
  730. if never_reduced>0 then
  731. writeln(never_reduced, ' rules never reduced.');
  732. end;
  733. if warnings>0 then writeln(warnings, ' warnings.');
  734. (* terminate: *)
  735. if errors>0 then
  736. begin
  737. erase(yyout);
  738. if ioresult<>0 then ;
  739. end;
  740. if file_size(lstfilename)=0 then
  741. erase(yylst)
  742. else
  743. writeln('(see ', lstfilename, ' for more information)');
  744. halt(errors);
  745. end(*Yacc*).