yaccbase.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. {
  2. This module collects the basic data types and operations used in the TP
  3. Yacc program, and other basic stuff that does not belong anywhere else:
  4. - Yacc input and output files and corresponding bookkeeping information
  5. used by the parser
  6. - symbolic character constants
  7. - dynamically allocated strings
  8. - integer sets
  9. - generic quicksort and hash table routines
  10. - utilities for list-generating
  11. - other tiny utilities
  12. Copyright (c) 1990-92 Albert Graef <[email protected]>
  13. Copyright (C) 1996 Berend de Boer <[email protected]>
  14. This program is free software; you can redistribute it and/or modify
  15. it under the terms of the GNU General Public License as published by
  16. the Free Software Foundation; either version 2 of the License, or
  17. (at your option) any later version.
  18. This program is distributed in the hope that it will be useful,
  19. but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. GNU General Public License for more details.
  22. You should have received a copy of the GNU General Public License
  23. along with this program; if not, write to the Free Software
  24. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. $Revision$
  26. $Modtime: 96-07-31 15:18 $
  27. $History: YACCBASE.PAS $
  28. *
  29. * ***************** Version 2 *****************
  30. * User: Berend Date: 96-10-10 Time: 21:16
  31. * Updated in $/Lex and Yacc/tply
  32. * Updated for protected mode, windows and Delphi 1.X and 2.X.
  33. }
  34. unit YaccBase;
  35. interface
  36. const
  37. (* symbolic character constants: *)
  38. bs = #8; (* backspace character *)
  39. tab = #9; (* tab character *)
  40. nl = #10; (* newline character *)
  41. cr = #13; (* carriage return *)
  42. ff = #12; (* form feed character *)
  43. var
  44. (* Filenames: *)
  45. yfilename : String;
  46. pasfilename : String;
  47. lstfilename : String;
  48. codfilename : String;
  49. codfilepath : String; { Under Linux,
  50. binary and conf file are never in 1 directory.}
  51. (* Yacc input, output, list and code template file: *)
  52. yyin, yyout, yylst, yycod : Text;
  53. (* the following values are initialized and updated by the parser: *)
  54. line : String; (* current input line *)
  55. lno, cno : Integer; (* current input position (line/column) *)
  56. tokleng : Integer; (* length of current token *)
  57. const
  58. {$IFDEF MsDos}
  59. max_elems = 50; (* maximum size of integer sets *)
  60. {$ELSE}
  61. max_elems = 75; (* maximum size of integer sets *)
  62. {$ENDIF}
  63. type
  64. (* String pointers: *)
  65. StrPtr = ^String;
  66. (* Sorted integer sets: *)
  67. IntSet = array [0..max_elems] of Integer;
  68. (* word 0 is size *)
  69. IntSetPtr = ^IntSet;
  70. (* Operations: *)
  71. (* Strings pointers: *)
  72. function newStr(str : String) : StrPtr;
  73. (* creates a string pointer (only the space actually needed for the given
  74. string is allocated) *)
  75. (* Integer sets (set arguments are passed by reference even if they are not
  76. modified, for greater efficiency): *)
  77. procedure empty(var M : IntSet);
  78. (* initializes M as empty *)
  79. procedure singleton(var M : IntSet; i : Integer);
  80. (* initializes M as a singleton set containing the element i *)
  81. procedure include(var M : IntSet; i : Integer);
  82. (* include i in M *)
  83. procedure exclude(var M : IntSet; i : Integer);
  84. (* exclude i from M *)
  85. procedure setunion(var M, N : IntSet);
  86. (* adds N to M *)
  87. procedure setminus(var M, N : IntSet);
  88. (* removes N from M *)
  89. procedure intersect(var M, N : IntSet);
  90. (* removes from M all elements NOT in N *)
  91. function size(var M : IntSet) : Integer;
  92. (* cardinality of set M *)
  93. function member(i : Integer; var M : IntSet) : Boolean;
  94. (* tests for membership of i in M *)
  95. function isempty(var M : IntSet) : Boolean;
  96. (* checks whether M is an empty set *)
  97. function equal(var M, N : IntSet) : Boolean;
  98. (* checks whether M and N are equal *)
  99. function subseteq(var M, N : IntSet) : Boolean;
  100. (* checks whether M is a subset of N *)
  101. function newEmptyIntSet : IntSetPtr;
  102. (* creates a pointer to an empty integer set *)
  103. function newIntSet ( var M : IntSet ) : IntSetPtr;
  104. (* creates a dynamic copy of M (only the space actually needed
  105. is allocated) *)
  106. (* Quicksort: *)
  107. type
  108. OrderPredicate = function (i, j : Integer) : Boolean;
  109. SwapProc = procedure (i, j : Integer);
  110. procedure quicksort(lo, hi: Integer;
  111. less : OrderPredicate;
  112. swap : SwapProc);
  113. (* General inplace sorting procedure based on the quicksort algorithm.
  114. This procedure can be applied to any sequential data structure;
  115. only the corresponding routines less which compares, and swap which
  116. swaps two elements i,j of the target data structure, must be
  117. supplied as appropriate for the target data structure.
  118. - lo, hi: the lower and higher indices, indicating the elements to
  119. be sorted
  120. - less(i, j): should return true if element no. i `is less than'
  121. element no. j, and false otherwise; any total quasi-ordering may
  122. be supplied here (if neither less(i, j) nor less(j, i) then elements
  123. i and j are assumed to be `equal').
  124. - swap(i, j): should swap the elements with index i and j *)
  125. (* Generic hash table routines (based on quadratic rehashing; hence the
  126. table size must be a prime number): *)
  127. type
  128. TableLookupProc = function(k : Integer) : String;
  129. TableEntryProc = procedure(k : Integer; symbol : String);
  130. function key(symbol : String;
  131. table_size : Integer;
  132. lookup : TableLookupProc;
  133. entry : TableEntryProc) : Integer;
  134. (* returns a hash table key for symbol; inserts the symbol into the
  135. table if necessary
  136. - table_size is the symbol table size and must be a fixed prime number
  137. - lookup is the table lookup procedure which should return the string
  138. at key k in the table ('' if entry is empty)
  139. - entry is the table entry procedure which is assumed to store the
  140. given symbol at the given location *)
  141. function definedKey(symbol : String;
  142. table_size : Integer;
  143. lookup : TableLookupProc) : Boolean;
  144. (* checks the table to see if symbol is in the table *)
  145. (* Utility routines: *)
  146. function min(i, j : Integer) : Integer;
  147. function max(i, j : Integer) : Integer;
  148. (* minimum and maximum of two integers *)
  149. function upper(str : String) : String;
  150. (* returns str converted to uppercase *)
  151. function strip(str : String) : String;
  152. (* returns str with leading and trailing blanks stripped off *)
  153. function blankStr(str : String) : String;
  154. (* returns string of same length as str, with all non-whitespace characters
  155. replaced by blanks *)
  156. function intStr(i : Integer) : String;
  157. (* returns the string representation of i *)
  158. function isInt(str : String; var i : Integer) : Boolean;
  159. (* checks whether str represents an integer; if so, returns the
  160. value of it in i *)
  161. function path(filename : String) : String;
  162. (* returns the path in filename *)
  163. function root(filename : String) : String;
  164. (* returns root (i.e. extension stripped from filename) of
  165. filename *)
  166. function addExt(filename, ext : String) : String;
  167. (* if filename has no extension and last filename character is not '.',
  168. add extension ext to filename *)
  169. function file_size(filename : String) : LongInt;
  170. (* determines file size in bytes *)
  171. (* Utility functions for list generating routines: *)
  172. type CharSet = set of Char;
  173. function charStr(c : char; reserved : CharSet) : String;
  174. (* returns a print name for character c, using the standard escape
  175. conventions; reserved is the class of `reserved' special characters
  176. which should be quoted with \ (\ itself is always quoted) *)
  177. function singleQuoteStr(str : String) : String;
  178. (* returns print name of str enclosed in single quotes, using the
  179. standard escape conventions *)
  180. function doubleQuoteStr(str : String) : String;
  181. (* returns print name of str enclosed in double quotes, using the
  182. standard escape conventions *)
  183. implementation
  184. uses YaccMsgs;
  185. (* String pointers: *)
  186. function newStr(str : String) : StrPtr;
  187. var strp : StrPtr;
  188. begin
  189. getmem(strp, succ(length(str)));
  190. move(str, strp^, succ(length(str)));
  191. newStr := strp;
  192. end(*newStr*);
  193. (* Integer sets: *)
  194. procedure empty(var M : IntSet);
  195. begin
  196. M[0] := 0;
  197. end(*empty*);
  198. procedure singleton(var M : IntSet; i : Integer);
  199. begin
  200. M[0] := 1; M[1] := i;
  201. end(*singleton*);
  202. procedure include(var M : IntSet; i : Integer);
  203. var l, r, k : Integer;
  204. begin
  205. (* binary search: *)
  206. l := 1; r := M[0];
  207. k := l + (r-l) div 2;
  208. while (l<r) and (M[k]<>i) do
  209. begin
  210. if M[k]<i then
  211. l := succ(k)
  212. else
  213. r := pred(k);
  214. k := l + (r-l) div 2;
  215. end;
  216. if (k>M[0]) or (M[k]<>i) then
  217. begin
  218. if M[0]>=max_elems then fatal(intset_overflow);
  219. if (k<=M[0]) and (M[k]<i) then
  220. begin
  221. move(M[k+1], M[k+2], (M[0]-k)*sizeOf(Integer));
  222. M[k+1] := i;
  223. end
  224. else
  225. begin
  226. move(M[k], M[k+1], (M[0]-k+1)*sizeOf(Integer));
  227. M[k] := i;
  228. end;
  229. inc(M[0]);
  230. end;
  231. end(*include*);
  232. procedure exclude(var M : IntSet; i : Integer);
  233. var l, r, k : Integer;
  234. begin
  235. (* binary search: *)
  236. l := 1; r := M[0];
  237. k := l + (r-l) div 2;
  238. while (l<r) and (M[k]<>i) do
  239. begin
  240. if M[k]<i then
  241. l := succ(k)
  242. else
  243. r := pred(k);
  244. k := l + (r-l) div 2;
  245. end;
  246. if (k<=M[0]) and (M[k]=i) then
  247. begin
  248. move(M[k+1], M[k], (M[0]-k)*sizeOf(Integer));
  249. dec(M[0]);
  250. end;
  251. end(*exclude*);
  252. procedure setunion(var M, N : IntSet);
  253. var
  254. K : IntSet;
  255. i, j, i_M, i_N : Integer;
  256. begin
  257. (* merge sort: *)
  258. i := 0; i_M := 1; i_N := 1;
  259. while (i_M<=M[0]) and (i_N<=N[0]) do
  260. begin
  261. inc(i);
  262. if i>max_elems then fatal(intset_overflow);
  263. if M[i_M]<N[i_N] then
  264. begin
  265. K[i] := M[i_M]; inc(i_M);
  266. end
  267. else if N[i_N]<M[i_M] then
  268. begin
  269. K[i] := N[i_N]; inc(i_N);
  270. end
  271. else
  272. begin
  273. K[i] := M[i_M]; inc(i_M); inc(i_N);
  274. end
  275. end;
  276. for j := i_M to M[0] do
  277. begin
  278. inc(i);
  279. if i>max_elems then fatal(intset_overflow);
  280. K[i] := M[j];
  281. end;
  282. for j := i_N to N[0] do
  283. begin
  284. inc(i);
  285. if i>max_elems then fatal(intset_overflow);
  286. K[i] := N[j];
  287. end;
  288. K[0] := i;
  289. move(K, M, succ(i)*sizeOf(Integer));
  290. end(*setunion*);
  291. procedure setminus(var M, N : IntSet);
  292. var
  293. K : IntSet;
  294. i, i_M, i_N : Integer;
  295. begin
  296. i := 0; i_N := 1;
  297. for i_M := 1 to M[0] do
  298. begin
  299. while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
  300. if (i_N>N[0]) or (N[i_N]>M[i_M]) then
  301. begin
  302. inc(i);
  303. K[i] := M[i_M];
  304. end
  305. else
  306. inc(i_N);
  307. end;
  308. K[0] := i;
  309. move(K, M, succ(i)*sizeOf(Integer));
  310. end(*setminus*);
  311. procedure intersect(var M, N : IntSet);
  312. var
  313. K : IntSet;
  314. i, i_M, i_N : Integer;
  315. begin
  316. i := 0; i_N := 1;
  317. for i_M := 1 to M[0] do
  318. begin
  319. while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
  320. if (i_N<=N[0]) and (N[i_N]=M[i_M]) then
  321. begin
  322. inc(i);
  323. K[i] := M[i_M];
  324. inc(i_N);
  325. end
  326. end;
  327. K[0] := i;
  328. move(K, M, succ(i)*sizeOf(Integer));
  329. end(*intersect*);
  330. function size(var M : IntSet) : Integer;
  331. begin
  332. size := M[0]
  333. end(*size*);
  334. function member(i : Integer; var M : IntSet) : Boolean;
  335. var l, r, k : Integer;
  336. begin
  337. (* binary search: *)
  338. l := 1; r := M[0];
  339. k := l + (r-l) div 2;
  340. while (l<r) and (M[k]<>i) do
  341. begin
  342. if M[k]<i then
  343. l := succ(k)
  344. else
  345. r := pred(k);
  346. k := l + (r-l) div 2;
  347. end;
  348. member := (k<=M[0]) and (M[k]=i);
  349. end(*member*);
  350. function isempty(var M : IntSet) : Boolean;
  351. begin
  352. isempty := M[0]=0
  353. end(*isempty*);
  354. function equal(var M, N : IntSet) : Boolean;
  355. var i : Integer;
  356. begin
  357. if M[0]<>N[0] then
  358. equal := false
  359. else
  360. begin
  361. for i := 1 to M[0] do
  362. if M[i]<>N[i] then
  363. begin
  364. equal := false;
  365. exit
  366. end;
  367. equal := true
  368. end
  369. end(*equal*);
  370. function subseteq(var M, N : IntSet) : Boolean;
  371. var
  372. i_M, i_N : Integer;
  373. begin
  374. if M[0]>N[0] then
  375. subseteq := false
  376. else
  377. begin
  378. i_N := 1;
  379. for i_M := 1 to M[0] do
  380. begin
  381. while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
  382. if (i_N>N[0]) or (N[i_N]>M[i_M]) then
  383. begin
  384. subseteq := false;
  385. exit
  386. end
  387. else
  388. inc(i_N);
  389. end;
  390. subseteq := true
  391. end;
  392. end(*subseteq*);
  393. function newIntSet ( var M : IntSet ) : IntSetPtr;
  394. var
  395. MP : IntSetPtr;
  396. begin
  397. getmem(MP, (size(M)+1)*sizeOf(Integer));
  398. move(M, MP^, (size(M)+1)*sizeOf(Integer));
  399. newIntSet := MP;
  400. end(*newIntSet*);
  401. function newEmptyIntSet : IntSetPtr;
  402. var
  403. MP : IntSetPtr;
  404. begin
  405. getmem(MP, (max_elems+1)*sizeOf(Integer));
  406. MP^[0] := 0;
  407. newEmptyIntSet := MP
  408. end(*newEmptyIntSet*);
  409. (* Quicksort: *)
  410. procedure quicksort(lo, hi: Integer;
  411. less : OrderPredicate;
  412. swap : SwapProc);
  413. (* derived from the quicksort routine in QSORT.PAS in the Turbo Pascal
  414. distribution *)
  415. procedure sort(l, r: Integer);
  416. var i, j, k : Integer;
  417. begin
  418. i := l; j := r; k := (l+r) DIV 2;
  419. repeat
  420. while less(i, k) do inc(i);
  421. while less(k, j) do dec(j);
  422. if i<=j then
  423. begin
  424. swap(i, j);
  425. if k=i then k := j (* pivot element swapped! *)
  426. else if k=j then k := i;
  427. inc(i); dec(j);
  428. end;
  429. until i>j;
  430. if l<j then sort(l,j);
  431. if i<r then sort(i,r);
  432. end(*sort*);
  433. begin
  434. if lo<hi then sort(lo,hi);
  435. end(*quicksort*);
  436. (* Generic hash table routines: *)
  437. function hash(str : String; table_size : Integer) : Integer;
  438. (* computes a hash key for str *)
  439. var i, key : Integer;
  440. begin
  441. key := 0;
  442. for i := 1 to length(str) do
  443. inc(key, ord(str[i]));
  444. hash := key mod table_size + 1;
  445. end(*hash*);
  446. procedure newPos(var pos, incr, count : Integer; table_size : Integer);
  447. (* computes a new position in the table (quadratic collision strategy)
  448. - pos: current position (+inc)
  449. - incr: current increment (+2)
  450. - count: current number of collisions (+1)
  451. quadratic collision formula for position of str after n collisions:
  452. pos(str, n) = (hash(str)+n^2) mod table_size +1
  453. note that n^2-(n-1)^2 = 2n-1 <=> n^2 = (n-1)^2 + (2n-1) for n>0,
  454. i.e. the increment inc=2n-1 increments by two in each collision *)
  455. begin
  456. inc(count);
  457. inc(pos, incr);
  458. if pos>table_size then pos := pos mod table_size + 1;
  459. inc(incr, 2)
  460. end(*newPos*);
  461. function key(symbol : String;
  462. table_size : Integer;
  463. lookup : TableLookupProc;
  464. entry : TableEntryProc) : Integer;
  465. var pos, incr, count : Integer;
  466. begin
  467. pos := hash(symbol, table_size);
  468. incr := 1;
  469. count := 0;
  470. while count<=table_size do
  471. if lookup(pos)='' then
  472. begin
  473. entry(pos, symbol);
  474. key := pos;
  475. exit
  476. end
  477. else if lookup(pos)=symbol then
  478. begin
  479. key := pos;
  480. exit
  481. end
  482. else
  483. newPos(pos, incr, count, table_size);
  484. fatal(sym_table_overflow)
  485. end(*key*);
  486. function definedKey(symbol : String;
  487. table_size : Integer;
  488. lookup : TableLookupProc) : Boolean;
  489. var pos, incr, count : Integer;
  490. begin
  491. pos := hash(symbol, table_size);
  492. incr := 1;
  493. count := 0;
  494. while count<=table_size do
  495. if lookup(pos)='' then
  496. begin
  497. definedKey := false;
  498. exit
  499. end
  500. else if lookup(pos)=symbol then
  501. begin
  502. definedKey := true;
  503. exit
  504. end
  505. else
  506. newPos(pos, incr, count, table_size);
  507. definedKey := false
  508. end(*definedKey*);
  509. (* Utility routines: *)
  510. function min(i, j : Integer) : Integer;
  511. begin
  512. if i<j then
  513. min := i
  514. else
  515. min := j
  516. end(*min*);
  517. function max(i, j : Integer) : Integer;
  518. begin
  519. if i>j then
  520. max := i
  521. else
  522. max := j
  523. end(*max*);
  524. function upper(str : String) : String;
  525. var i : Integer;
  526. begin
  527. for i := 1 to length(str) do
  528. str[i] := upCase(str[i]);
  529. upper := str
  530. end(*upper*);
  531. function strip(str : String) : String;
  532. begin
  533. while (length(str)>0) and ((str[1]=' ') or (str[1]=tab)) do
  534. delete(str, 1, 1);
  535. while (length(str)>0) and
  536. ((str[length(str)]= ' ') or
  537. (str[length(str)]=tab)) do
  538. delete(str, length(str), 1);
  539. strip := str;
  540. end(*strip*);
  541. function blankStr(str : String) : String;
  542. var i : Integer;
  543. begin
  544. for i := 1 to length(str) do
  545. if str[i]<>tab then str[i] := ' ';
  546. blankStr := str;
  547. end(*blankStr*);
  548. function intStr(i : Integer) : String;
  549. var s : String;
  550. begin
  551. str(i, s);
  552. intStr := s
  553. end(*intStr*);
  554. function isInt(str : String; var i : Integer) : Boolean;
  555. var res : Integer;
  556. begin
  557. val(str, i, res);
  558. isInt := res = 0;
  559. end(*isInt*);
  560. function path(filename : String) : String;
  561. var i : Integer;
  562. begin
  563. i := length(filename);
  564. while (i>0) and (filename[i]<>'\') and (filename[i]<>':') do
  565. dec(i);
  566. path := copy(filename, 1, i);
  567. end(*path*);
  568. function root(filename : String) : String;
  569. var
  570. i : Integer;
  571. begin
  572. root := filename;
  573. for i := length(filename) downto 1 do
  574. case filename[i] of
  575. '.' :
  576. begin
  577. root := copy(filename, 1, i-1);
  578. exit
  579. end;
  580. '\': exit;
  581. else
  582. end;
  583. end(*addExt*);
  584. function addExt(filename, ext : String) : String;
  585. (* implemented with goto for maximum efficiency *)
  586. label x;
  587. var
  588. i : Integer;
  589. begin
  590. addExt := filename;
  591. for i := length(filename) downto 1 do
  592. case filename[i] of
  593. '.' : exit;
  594. '\': goto x;
  595. else
  596. end;
  597. x : addExt := filename+'.'+ext
  598. end(*addExt*);
  599. function file_size(filename : String) : LongInt;
  600. var f : File;
  601. begin
  602. assign(f, filename);
  603. reset(f, 1);
  604. if ioresult=0 then
  605. file_size := fileSize(f)
  606. else
  607. file_size := 0;
  608. close(f);
  609. end(*file_size*);
  610. (* Utility functions for list generating routines: *)
  611. function charStr(c : char; reserved : CharSet) : String;
  612. function octStr(c : char) : String;
  613. (* return octal string representation of character c *)
  614. begin
  615. octStr := intStr(ord(c) div 64)+intStr((ord(c) mod 64) div 8)+
  616. intStr(ord(c) mod 8);
  617. end(*octStr*);
  618. begin
  619. case c of
  620. bs : charStr := '\b';
  621. tab : charStr := '\t';
  622. nl : charStr := '\n';
  623. cr : charStr := '\c';
  624. ff : charStr := '\f';
  625. '\' : charStr := '\\';
  626. #0..#7, (* nonprintable characters *)
  627. #11,#14..#31,
  628. #127..#255 : charStr := '\'+octStr(c);
  629. else if c in reserved then
  630. charStr := '\'+c
  631. else
  632. charStr := c
  633. end
  634. end(*charStr*);
  635. function singleQuoteStr(str : String) : String;
  636. var
  637. i : Integer;
  638. str1 : String;
  639. begin
  640. str1 := '';
  641. for i := 1 to length(str) do
  642. str1 := str1+charStr(str[i], ['''']);
  643. singleQuoteStr := ''''+str1+''''
  644. end(*singleQuoteStr*);
  645. function doubleQuoteStr(str : String) : String;
  646. var
  647. i : Integer;
  648. str1 : String;
  649. begin
  650. str1 := '';
  651. for i := 1 to length(str) do
  652. str1 := str1+charStr(str[i], ['"']);
  653. doubleQuoteStr := '"'+str1+'"'
  654. end(*doubleQuoteStr*);
  655. end(*YaccBase*).