home *** CD-ROM | disk | FTP | other *** search
-
- unit LexLib;
- (* Library of supplementing routines for Lex generated lexical analysers.
- V1.1 9-29-88 AG
- V2.0 2-28-89, 5-28-89 AG *)
-
- interface
-
- (* The Lex library defines
- - the default input and output streams to be used by a generated
- lexical analyser yylex (these defaults may be overwritten by
- appropriate declarations in the user program or Lex specification)
- - the default yylex error handler yyloverflow; this routine can be
- overwritten by an appropriate user-defined procedure *)
-
- (* Default I/O streams: **************************************************)
-
- (* The default input/output streams are implemented as Pascal text files
- that are initialized to read from standard input and write to standard
- output, allowing for DOS I/O redirection and piping. The I/O streams may
- also be redirected and manipulated by using the appropriate Turbo Pascal
- file routines (assign, reset, rewrite, close, ...) on yyin and yyout.
- Furthermore, if the I/O streams to be used are something other
- than MS-DOS files and devices (e.g. internal memory), the procedures
- listed below can be replaced altogether by suitable user defined
- routines with compatible specifications, since yylex uses only the
- routines input, output, unput and yywrap and does not access the
- I/O files directly.
- yyin and yyout are closed automatically at the end of the main
- program; however, if you want to process multiple files in sequence, you
- will have to close, reassign and reopen the files explicitly (and also
- reinitialize yylineno appropriately, if you intend to use it).
- Error handling: the result of the latest LexLib I/O operation is stored
- in the yyioresult variable; in case of an error (yyioresult<>0) yyin will
- return #0 (end-of-file).
- A nonzero value of yyioresult can be used to determine the nature of an
- error (refer to the description of `ioresult' in the Turbo Pascal
- documentation). *)
-
- var
- yyin, yyout : Text;
- (* default I/O streams; initialized to standard input and output *)
- yyioresult : integer;
- (* result of last I/O operation *)
- yylineno : integer;
- (* current line number, initialized to 1 and updated automatically
- by input and unput *)
- function input : char;
- (* read a character from the input stream; return #0 for
- end-of-file; convert line end (<CR><LF>) to newline (\n) *)
- procedure output(c : char);
- (* write a character on the output stream; convert newline (\n) to
- <CR><LF> *)
- procedure unput(c : char);
- (* return c to the input stream to be reread by subsequent calls to
- yyin; the current implementation of unput is restricted to
- 255 characters max; if this restriction is violated unput will
- call LexLib.yyloverflow *)
- function yywrap : boolean;
- (* this routine is called by yylex at end of input to determine whether
- to terminate lexical analysis and perform the normal wrapup (return
- end-of-file, etc.); the standard version of yywrap always returns
- TRUE, indicating that yylex should perform normal wrapup.
- This routine may be redefined to do application dependent processing
- at end-of-file; in particular, it can arrange for more input and
- return FALSE in which case yylex will continue lexical analysis. *)
-
- (* Error handler: ********************************************************)
-
- function yyloverflow : boolean;
- (* Called by yylex in case of input buffer overflow; this default version
- prints an error message and returns TRUE indicating a non-recoverable
- overflow which causes yylex to terminate the program with errorlevel 1.
- yyloverflow may be redefined to print a more appropriate error message,
- or do some other processing. In particular, it may inspect and
- manipulate the input stream (e.g. insert a character that will
- terminate the current match), and return FALSE to yylex, in which case
- yylex will automatically recover from the overflow error (yylex will
- obtain the next input character, and if that character does not
- already terminate the match, will append the character to the match
- and assume that now the next input character cannot be accepted).
- NOTE: This routine is *nonstandard*, i.e. not provided by UNIX Lex
- versions. *)
-
- (* procedures and variables defined by yylex: ****************************)
-
- (* the following user procedures and variables are not defined by the Lex
- library, but are declared directly in the Lex output file (they are
- compatible with the corresponding UNIX Lex routines and macros):
- var
- yytext : string[yylbufsize];
- { text of token previously matched by yylex }
- yyleng : Byte;
- { current length of yytext (last character in yytext is
- yytext[yyleng]) }
- procedure yymore;
- { extend the current match by appending the next match to the current
- token in yytext }
- procedure yyless(n : integer);
- { only retain the first n characters from the current match in yytext;
- return all other characters to the input stream }
- procedure reject;
- { reject the current match and process whatever rule was second
- choice after the current rule; this routine may be used to detect
- items that overlap or include each other }
- procedure begin_(s : integer);
- { put yylex in start state s (0: initial start state; <id>: start
- state defined by %start <id> declaration (note the underscore
- at the end of the name of this routine!) }
- procedure return(tok : integer);
- { sets tok as the return value for yylex and causes yylex to exit
- as soon as all actions of the current rule have been executed (to
- exit from an action - but not automatically from yylex -, the Turbo-
- Pascal standard procedure exit may be used); this routine is
- provided as a sort of `replacement' for the C return statement }
- procedure echo;
- { echo the matched token in yytext to the output } *)
-
- implementation
- {$I-}
-
- var nextExitProc : Pointer;
- (* pointer to next exit procedure *)
- {$F+}
- procedure yylexit;
- {$F-}
- (* LexLib exit procedure; MUST be called FAR *)
- begin
- close(yyin); if ioresult<>0 then ;
- close(yyout); if ioresult<>0 then ;
- exitProc := nextExitProc (* chain to next exit procedure *)
- end(*yylexit*);
- (* character codes: *)
- const
- LF = #10; (* line feed *)
- CR = #13; (* carriage return *)
- NEWLINE = LF; (* newline character *)
-
- (* The default I/O streams are implemented in terms of the text files
- yyin and yyout. unput is implemented via a string buffer
- yybuf.
- input needs lookahead itself in order to determine line ends <CR><LF>;
- this lookahead is also handled with unput. *)
- var
- yybuf : string;
- yybufleng : Byte absolute yybuf;
- (* buffer holding input to be reread (unput) *)
- function input : char;
- var c : char;
- begin
- if yybufleng>0 then
- begin
- if yybuf[yybufleng]=NEWLINE then
- inc(yylineno);
- input := yybuf[yybufleng];
- dec(yybufleng)
- end
- else if eof(yyin) then
- input := #0
- else
- begin
- read(yyin, c);
- yyioresult := ioresult;
- if yyioresult<>0 then
- input := #0
- else if (c=CR) and not eof(yyin) then
- begin
- read(yyin, c);
- if c=LF then
- begin
- inc(yylineno);
- input := NEWLINE
- end
- else
- begin
- unput(c);
- input := CR
- end
- end
- else
- input := c;
- end;
- yyioresult := ioresult;
- if yyioresult<>0 then
- input := #0
- end(*input*);
- procedure output(c : char);
- begin
- if c=NEWLINE then
- (* convert NEWLINE to <CR><LF> *)
- write(yyout, CR, LF)
- else
- write(yyout, c);
- yyioresult := ioresult
- end(*output*);
- procedure unput(c : char);
- begin
- if yybufleng=255 then
- if yyloverflow then halt(1) else
- else
- begin
- inc(yybufleng);
- yybuf[yybufleng] := c;
- if c=NEWLINE then
- dec(yylineno)
- end
- end(*unput*);
- function yywrap : boolean;
- begin
- yywrap := true
- end(*yywrap*);
- function yyloverflow : boolean;
- begin
- writeln('yylex: buffer overflow');
- yyloverflow := true
- end(*yyloverflow*);
- begin
- (* obtain current exit procedure chain: *)
- nextExitProc := exitProc;
- (* install LexLib exit procedure: *)
- exitProc := @yylexit;
- (* assign yyin and yyout to stdin and stdout, respectively *)
- assign(yyin, ''); assign(yyout, '');
- reset(yyin); rewrite(yyout);
- yyioresult := ioresult;
- yybuf := '';
- yylineno := 1
- end(*LexLib*).