123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739 |
- {
- This module collects the basic data types and operations used in the TP
- Yacc program, and other basic stuff that does not belong anywhere else:
- - Yacc input and output files and corresponding bookkeeping information
- used by the parser
- - symbolic character constants
- - dynamically allocated strings
- - integer sets
- - generic quicksort and hash table routines
- - utilities for list-generating
- - other tiny utilities
- Copyright (c) 1990-92 Albert Graef <[email protected]>
- Copyright (C) 1996 Berend de Boer <[email protected]>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Revision: 1.2 $
- $Modtime: 96-07-31 15:18 $
- $History: YACCBASE.PAS $
- *
- * ***************** Version 2 *****************
- * User: Berend Date: 96-10-10 Time: 21:16
- * Updated in $/Lex and Yacc/tply
- * Updated for protected mode, windows and Delphi 1.X and 2.X.
- }
- unit YaccBase;
- interface
- const
- (* symbolic character constants: *)
- bs = #8; (* backspace character *)
- tab = #9; (* tab character *)
- nl = #10; (* newline character *)
- cr = #13; (* carriage return *)
- ff = #12; (* form feed character *)
- var
- (* Filenames: *)
- yfilename : String;
- pasfilename : String;
- lstfilename : String;
- codfilename : String;
- codfilepath1,
- codfilepath2 : String; { Under Linux,
- binary and conf file are never in 1 directory.}
- (* Yacc input, output, list and code template file: *)
- yyin, yyout, yylst, yycod : Text;
- (* the following values are initialized and updated by the parser: *)
- line : String; (* current input line *)
- lno, cno : Integer; (* current input position (line/column) *)
- tokleng : Integer; (* length of current token *)
- const
- {$IFDEF MsDos}
- max_elems = 50; (* maximum size of integer sets *)
- {$ELSE}
- max_elems = 150; (* maximum size of integer sets *)
- {$ENDIF}
- type
- (* String pointers: *)
- StrPtr = ^String;
- (* Sorted integer sets: *)
- IntSet = array [0..max_elems] of Integer;
- (* word 0 is size *)
- IntSetPtr = ^IntSet;
- (* Operations: *)
- (* Strings pointers: *)
- function newStr(str : String) : StrPtr;
- (* creates a string pointer (only the space actually needed for the given
- string is allocated) *)
- (* Integer sets (set arguments are passed by reference even if they are not
- modified, for greater efficiency): *)
- procedure empty(var M : IntSet);
- (* initializes M as empty *)
- procedure singleton(var M : IntSet; i : Integer);
- (* initializes M as a singleton set containing the element i *)
- procedure include(var M : IntSet; i : Integer);
- (* include i in M *)
- procedure exclude(var M : IntSet; i : Integer);
- (* exclude i from M *)
- procedure setunion(var M, N : IntSet);
- (* adds N to M *)
- procedure setminus(var M, N : IntSet);
- (* removes N from M *)
- procedure intersect(var M, N : IntSet);
- (* removes from M all elements NOT in N *)
- function size(var M : IntSet) : Integer;
- (* cardinality of set M *)
- function member(i : Integer; var M : IntSet) : Boolean;
- (* tests for membership of i in M *)
- function isempty(var M : IntSet) : Boolean;
- (* checks whether M is an empty set *)
- function equal(var M, N : IntSet) : Boolean;
- (* checks whether M and N are equal *)
- function subseteq(var M, N : IntSet) : Boolean;
- (* checks whether M is a subset of N *)
- function newEmptyIntSet : IntSetPtr;
- (* creates a pointer to an empty integer set *)
- function newIntSet ( var M : IntSet ) : IntSetPtr;
- (* creates a dynamic copy of M (only the space actually needed
- is allocated) *)
- (* Quicksort: *)
- type
- OrderPredicate = function (i, j : Integer) : Boolean;
- SwapProc = procedure (i, j : Integer);
- procedure quicksort(lo, hi: Integer;
- less : OrderPredicate;
- swap : SwapProc);
- (* General inplace sorting procedure based on the quicksort algorithm.
- This procedure can be applied to any sequential data structure;
- only the corresponding routines less which compares, and swap which
- swaps two elements i,j of the target data structure, must be
- supplied as appropriate for the target data structure.
- - lo, hi: the lower and higher indices, indicating the elements to
- be sorted
- - less(i, j): should return true if element no. i `is less than'
- element no. j, and false otherwise; any total quasi-ordering may
- be supplied here (if neither less(i, j) nor less(j, i) then elements
- i and j are assumed to be `equal').
- - swap(i, j): should swap the elements with index i and j *)
- (* Generic hash table routines (based on quadratic rehashing; hence the
- table size must be a prime number): *)
- type
- TableLookupProc = function(k : Integer) : String;
- TableEntryProc = procedure(k : Integer; symbol : String);
- function key(symbol : String;
- table_size : Integer;
- lookup : TableLookupProc;
- entry : TableEntryProc) : Integer;
- (* returns a hash table key for symbol; inserts the symbol into the
- table if necessary
- - table_size is the symbol table size and must be a fixed prime number
- - lookup is the table lookup procedure which should return the string
- at key k in the table ('' if entry is empty)
- - entry is the table entry procedure which is assumed to store the
- given symbol at the given location *)
- function definedKey(symbol : String;
- table_size : Integer;
- lookup : TableLookupProc) : Boolean;
- (* checks the table to see if symbol is in the table *)
- (* Utility routines: *)
- function min(i, j : Integer) : Integer;
- function max(i, j : Integer) : Integer;
- (* minimum and maximum of two integers *)
- function upper(str : String) : String;
- (* returns str converted to uppercase *)
- function strip(str : String) : String;
- (* returns str with leading and trailing blanks stripped off *)
- function blankStr(str : String) : String;
- (* returns string of same length as str, with all non-whitespace characters
- replaced by blanks *)
- function intStr(i : Integer) : String;
- (* returns the string representation of i *)
- function isInt(str : String; var i : Integer) : Boolean;
- (* checks whether str represents an integer; if so, returns the
- value of it in i *)
- function path(filename : String) : String;
- (* returns the path in filename *)
- function root(filename : String) : String;
- (* returns root (i.e. extension stripped from filename) of
- filename *)
- function addExt(filename, ext : String) : String;
- (* if filename has no extension and last filename character is not '.',
- add extension ext to filename *)
- function file_size(filename : String) : LongInt;
- (* determines file size in bytes *)
- (* Utility functions for list generating routines: *)
- type CharSet = set of Char;
- function charStr(c : char; reserved : CharSet) : String;
- (* returns a print name for character c, using the standard escape
- conventions; reserved is the class of `reserved' special characters
- which should be quoted with \ (\ itself is always quoted) *)
- function singleQuoteStr(str : String) : String;
- (* returns print name of str enclosed in single quotes, using the
- standard escape conventions *)
- function doubleQuoteStr(str : String) : String;
- (* returns print name of str enclosed in double quotes, using the
- standard escape conventions *)
- implementation
- uses YaccMsgs;
- (* String pointers: *)
- function newStr(str : String) : StrPtr;
- var strp : StrPtr;
- begin
- getmem(strp, succ(length(str)));
- move(str, strp^, succ(length(str)));
- newStr := strp;
- end(*newStr*);
- (* Integer sets: *)
- procedure empty(var M : IntSet);
- begin
- M[0] := 0;
- end(*empty*);
- procedure singleton(var M : IntSet; i : Integer);
- begin
- M[0] := 1; M[1] := i;
- end(*singleton*);
- procedure include(var M : IntSet; i : Integer);
- var l, r, k : Integer;
- begin
- (* binary search: *)
- l := 1; r := M[0];
- k := l + (r-l) div 2;
- while (l<r) and (M[k]<>i) do
- begin
- if M[k]<i then
- l := succ(k)
- else
- r := pred(k);
- k := l + (r-l) div 2;
- end;
- if (k>M[0]) or (M[k]<>i) then
- begin
- if M[0]>=max_elems then fatal(intset_overflow);
- if (k<=M[0]) and (M[k]<i) then
- begin
- move(M[k+1], M[k+2], (M[0]-k)*sizeOf(Integer));
- M[k+1] := i;
- end
- else
- begin
- move(M[k], M[k+1], (M[0]-k+1)*sizeOf(Integer));
- M[k] := i;
- end;
- inc(M[0]);
- end;
- end(*include*);
- procedure exclude(var M : IntSet; i : Integer);
- var l, r, k : Integer;
- begin
- (* binary search: *)
- l := 1; r := M[0];
- k := l + (r-l) div 2;
- while (l<r) and (M[k]<>i) do
- begin
- if M[k]<i then
- l := succ(k)
- else
- r := pred(k);
- k := l + (r-l) div 2;
- end;
- if (k<=M[0]) and (M[k]=i) then
- begin
- move(M[k+1], M[k], (M[0]-k)*sizeOf(Integer));
- dec(M[0]);
- end;
- end(*exclude*);
- procedure setunion(var M, N : IntSet);
- var
- K : IntSet;
- i, j, i_M, i_N : Integer;
- begin
- (* merge sort: *)
- i := 0; i_M := 1; i_N := 1;
- while (i_M<=M[0]) and (i_N<=N[0]) do
- begin
- inc(i);
- if i>max_elems then fatal(intset_overflow);
- if M[i_M]<N[i_N] then
- begin
- K[i] := M[i_M]; inc(i_M);
- end
- else if N[i_N]<M[i_M] then
- begin
- K[i] := N[i_N]; inc(i_N);
- end
- else
- begin
- K[i] := M[i_M]; inc(i_M); inc(i_N);
- end
- end;
- for j := i_M to M[0] do
- begin
- inc(i);
- if i>max_elems then fatal(intset_overflow);
- K[i] := M[j];
- end;
- for j := i_N to N[0] do
- begin
- inc(i);
- if i>max_elems then fatal(intset_overflow);
- K[i] := N[j];
- end;
- K[0] := i;
- move(K, M, succ(i)*sizeOf(Integer));
- end(*setunion*);
- procedure setminus(var M, N : IntSet);
- var
- K : IntSet;
- i, i_M, i_N : Integer;
- begin
- i := 0; i_N := 1;
- for i_M := 1 to M[0] do
- begin
- while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
- if (i_N>N[0]) or (N[i_N]>M[i_M]) then
- begin
- inc(i);
- K[i] := M[i_M];
- end
- else
- inc(i_N);
- end;
- K[0] := i;
- move(K, M, succ(i)*sizeOf(Integer));
- end(*setminus*);
- procedure intersect(var M, N : IntSet);
- var
- K : IntSet;
- i, i_M, i_N : Integer;
- begin
- i := 0; i_N := 1;
- for i_M := 1 to M[0] do
- begin
- while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
- if (i_N<=N[0]) and (N[i_N]=M[i_M]) then
- begin
- inc(i);
- K[i] := M[i_M];
- inc(i_N);
- end
- end;
- K[0] := i;
- move(K, M, succ(i)*sizeOf(Integer));
- end(*intersect*);
- function size(var M : IntSet) : Integer;
- begin
- size := M[0]
- end(*size*);
- function member(i : Integer; var M : IntSet) : Boolean;
- var l, r, k : Integer;
- begin
- (* binary search: *)
- l := 1; r := M[0];
- k := l + (r-l) div 2;
- while (l<r) and (M[k]<>i) do
- begin
- if M[k]<i then
- l := succ(k)
- else
- r := pred(k);
- k := l + (r-l) div 2;
- end;
- member := (k<=M[0]) and (M[k]=i);
- end(*member*);
- function isempty(var M : IntSet) : Boolean;
- begin
- isempty := M[0]=0
- end(*isempty*);
- function equal(var M, N : IntSet) : Boolean;
- var i : Integer;
- begin
- if M[0]<>N[0] then
- equal := false
- else
- begin
- for i := 1 to M[0] do
- if M[i]<>N[i] then
- begin
- equal := false;
- exit
- end;
- equal := true
- end
- end(*equal*);
- function subseteq(var M, N : IntSet) : Boolean;
- var
- i_M, i_N : Integer;
- begin
- if M[0]>N[0] then
- subseteq := false
- else
- begin
- i_N := 1;
- for i_M := 1 to M[0] do
- begin
- while (i_N<=N[0]) and (N[i_N]<M[i_M]) do inc(i_N);
- if (i_N>N[0]) or (N[i_N]>M[i_M]) then
- begin
- subseteq := false;
- exit
- end
- else
- inc(i_N);
- end;
- subseteq := true
- end;
- end(*subseteq*);
- function newIntSet ( var M : IntSet ) : IntSetPtr;
- var
- MP : IntSetPtr;
- begin
- getmem(MP, (size(M)+1)*sizeOf(Integer));
- move(M, MP^, (size(M)+1)*sizeOf(Integer));
- newIntSet := MP;
- end(*newIntSet*);
- function newEmptyIntSet : IntSetPtr;
- var
- MP : IntSetPtr;
- begin
- getmem(MP, (max_elems+1)*sizeOf(Integer));
- MP^[0] := 0;
- newEmptyIntSet := MP
- end(*newEmptyIntSet*);
- (* Quicksort: *)
- procedure quicksort(lo, hi: Integer;
- less : OrderPredicate;
- swap : SwapProc);
- (* derived from the quicksort routine in QSORT.PAS in the Turbo Pascal
- distribution *)
- procedure sort(l, r: Integer);
- var i, j, k : Integer;
- begin
- i := l; j := r; k := (l+r) DIV 2;
- repeat
- while less(i, k) do inc(i);
- while less(k, j) do dec(j);
- if i<=j then
- begin
- swap(i, j);
- if k=i then k := j (* pivot element swapped! *)
- else if k=j then k := i;
- inc(i); dec(j);
- end;
- until i>j;
- if l<j then sort(l,j);
- if i<r then sort(i,r);
- end(*sort*);
- begin
- if lo<hi then sort(lo,hi);
- end(*quicksort*);
- (* Generic hash table routines: *)
- function hash(str : String; table_size : Integer) : Integer;
- (* computes a hash key for str *)
- var i, key : Integer;
- begin
- key := 0;
- for i := 1 to length(str) do
- inc(key, ord(str[i]));
- hash := key mod table_size + 1;
- end(*hash*);
- procedure newPos(var pos, incr, count : Integer; table_size : Integer);
- (* computes a new position in the table (quadratic collision strategy)
- - pos: current position (+inc)
- - incr: current increment (+2)
- - count: current number of collisions (+1)
- quadratic collision formula for position of str after n collisions:
- pos(str, n) = (hash(str)+n^2) mod table_size +1
- note that n^2-(n-1)^2 = 2n-1 <=> n^2 = (n-1)^2 + (2n-1) for n>0,
- i.e. the increment inc=2n-1 increments by two in each collision *)
- begin
- inc(count);
- inc(pos, incr);
- if pos>table_size then pos := pos mod table_size + 1;
- inc(incr, 2)
- end(*newPos*);
- function key(symbol : String;
- table_size : Integer;
- lookup : TableLookupProc;
- entry : TableEntryProc) : Integer;
- var pos, incr, count : Integer;
- begin
- pos := hash(symbol, table_size);
- incr := 1;
- count := 0;
- while count<=table_size do
- if lookup(pos)='' then
- begin
- entry(pos, symbol);
- key := pos;
- exit
- end
- else if lookup(pos)=symbol then
- begin
- key := pos;
- exit
- end
- else
- newPos(pos, incr, count, table_size);
- fatal(sym_table_overflow)
- end(*key*);
- function definedKey(symbol : String;
- table_size : Integer;
- lookup : TableLookupProc) : Boolean;
- var pos, incr, count : Integer;
- begin
- pos := hash(symbol, table_size);
- incr := 1;
- count := 0;
- while count<=table_size do
- if lookup(pos)='' then
- begin
- definedKey := false;
- exit
- end
- else if lookup(pos)=symbol then
- begin
- definedKey := true;
- exit
- end
- else
- newPos(pos, incr, count, table_size);
- definedKey := false
- end(*definedKey*);
- (* Utility routines: *)
- function min(i, j : Integer) : Integer;
- begin
- if i<j then
- min := i
- else
- min := j
- end(*min*);
- function max(i, j : Integer) : Integer;
- begin
- if i>j then
- max := i
- else
- max := j
- end(*max*);
- function upper(str : String) : String;
- var i : Integer;
- begin
- for i := 1 to length(str) do
- str[i] := upCase(str[i]);
- upper := str
- end(*upper*);
- function strip(str : String) : String;
- begin
- while (length(str)>0) and ((str[1]=' ') or (str[1]=tab)) do
- delete(str, 1, 1);
- while (length(str)>0) and
- ((str[length(str)]= ' ') or
- (str[length(str)]=tab)) do
- delete(str, length(str), 1);
- strip := str;
- end(*strip*);
- function blankStr(str : String) : String;
- var i : Integer;
- begin
- for i := 1 to length(str) do
- if str[i]<>tab then str[i] := ' ';
- blankStr := str;
- end(*blankStr*);
- function intStr(i : Integer) : String;
- var s : String;
- begin
- str(i, s);
- intStr := s
- end(*intStr*);
- function isInt(str : String; var i : Integer) : Boolean;
- var res : Integer;
- begin
- val(str, i, res);
- isInt := res = 0;
- end(*isInt*);
- function path(filename : String) : String;
- var i : Integer;
- begin
- i := length(filename);
- while (i>0) and (filename[i]<>DirectorySeparator) and (filename[i]<>':') do
- dec(i);
- path := copy(filename, 1, i);
- end(*path*);
- function root(filename : String) : String;
- var
- i : Integer;
- begin
- root := filename;
- for i := length(filename) downto 1 do
- case filename[i] of
- '.' :
- begin
- root := copy(filename, 1, i-1);
- exit
- end;
- DirectorySeparator: exit;
- else
- end;
- end(*root*);
- function addExt(filename, ext : String) : String;
- (* implemented with goto for maximum efficiency *)
- label x;
- var
- i : Integer;
- begin
- addExt := filename;
- for i := length(filename) downto 1 do
- case filename[i] of
- '.' : exit;
- DirectorySeparator : goto x;
- else
- end;
- x : addExt := filename+'.'+ext
- end(*addExt*);
- function file_size(filename : String) : LongInt;
- var f : File;
- begin
- assign(f, filename);
- reset(f, 1);
- if ioresult=0 then
- file_size := fileSize(f)
- else
- file_size := 0;
- close(f);
- end(*file_size*);
- (* Utility functions for list generating routines: *)
- function charStr(c : char; reserved : CharSet) : String;
- function octStr(c : char) : String;
- (* return octal string representation of character c *)
- begin
- octStr := intStr(ord(c) div 64)+intStr((ord(c) mod 64) div 8)+
- intStr(ord(c) mod 8);
- end(*octStr*);
- begin
- case c of
- bs : charStr := '\b';
- tab : charStr := '\t';
- nl : charStr := '\n';
- cr : charStr := '\c';
- ff : charStr := '\f';
- '\' : charStr := '\\';
- #0..#7, (* nonprintable characters *)
- #11,#14..#31,
- #127..#255 : charStr := '\'+octStr(c);
- else if c in reserved then
- charStr := '\'+c
- else
- charStr := c
- end
- end(*charStr*);
- function singleQuoteStr(str : String) : String;
- var
- i : Integer;
- str1 : String;
- begin
- str1 := '';
- for i := 1 to length(str) do
- str1 := str1+charStr(str[i], ['''']);
- singleQuoteStr := ''''+str1+''''
- end(*singleQuoteStr*);
- function doubleQuoteStr(str : String) : String;
- var
- i : Integer;
- str1 : String;
- begin
- str1 := '';
- for i := 1 to length(str) do
- str1 := str1+charStr(str[i], ['"']);
- doubleQuoteStr := '"'+str1+'"'
- end(*doubleQuoteStr*);
- end(*YaccBase*).
|