yaccbase.pas 20 KB

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