6
(* Standard Lex library unit for TP Lex Version 3.0.
11
(* The Lex library unit supplies a collection of variables and routines
12
needed by the lexical analyzer routine yylex and application programs
13
using Lex-generated lexical analyzers. It also provides access to the
14
input/output streams used by the lexical analyzer and the text of the
15
matched string, and provides some utility functions which may be used
18
This `standard' version of the LexLib unit is used to implement lexical
19
analyzers which read from and write to MS-DOS files (using standard input
20
and output, by default). It is suitable for many standard applications
21
for lexical analyzers, such as text conversion tools or compilers.
23
However, you may create your own version of the LexLib unit, tailored to
24
your target applications. In particular, you may wish to provide another
25
set of I/O functions, e.g., if you want to read from or write to memory
26
instead to files, or want to use different file types. *)
30
The variable yytext contains the current match, yyleng its length.
31
The variable yyline contains the current input line, and yylineno and
32
yycolno denote the current input position (line, column). These values
33
are often used in giving error diagnostics (however, they will only be
34
meaningful if there is no rescanning across line ends).
36
The variables yyinput and yyoutput are the text files which are used
37
by the lexical analyzer. By default, they are assigned to standard
38
input and output, but you may change these assignments to fit your
39
target application (use the Turbo Pascal standard routines assign,
40
reset, and rewrite for this purpose). *)
44
yyinput, yyoutput : Text; (* input and output file *)
45
yyline : String; (* current input line *)
46
yylineno, yycolno : Integer; (* current input position *)
47
yytext : String; (* matched text (should be considered r/o) *)
48
yyleng : Byte (* length of matched text *)
53
The following routines get_char, unget_char and put_char are used to
54
implement access to the input and output files. Since \n (newline) for
55
Lex means line end, the I/O routines have to translate MS-DOS line ends
56
(carriage-return/line-feed) into newline characters and vice versa. Input
57
is buffered to allow rescanning text (via unput_char).
59
The input buffer holds the text of the line to be scanned. When the input
60
buffer empties, a new line is obtained from the input stream. Characters
61
can be returned to the input buffer by calls to unget_char. At end-of-
62
file a null character is returned.
64
The input routines also keep track of the input position and set the
65
yyline, yylineno, yycolno variables accordingly.
67
Since the rest of the Lex library only depends on these three routines
68
(there are no direct references to the yyinput and yyoutput files or
69
to the input buffer), you can easily replace get_char, unget_char and
70
put_char by another suitable set of routines, e.g. if you want to read
71
from/write to memory, etc. *)
73
function get_char : Char;
74
(* obtain one character from the input file (null character at end-of-
77
procedure unget_char ( c : Char );
78
(* return one character to the input file to be reread in subsequent calls
81
procedure put_char ( c : Char );
82
(* write one character to the output file *)
84
(* Utility routines: *)
87
(* echoes the current match to the output stream *)
90
(* append the next match to the current one *)
92
procedure yyless ( n : Integer );
93
(* truncate yytext to size n and return the remaining characters to the
97
(* reject the current match and execute the next one *)
99
(* reject does not actually cause the input to be rescanned; instead,
100
internal state information is used to find the next match. Hence
101
you should not try to modify the input stream or the yytext variable
102
when rejecting a match. *)
104
procedure return ( n : Integer );
105
procedure returnc ( c : Char );
106
(* sets the return value of yylex *)
108
procedure start ( state : Integer );
109
(* puts the lexical analyzer in the given start state; state=0 denotes
110
the default start state, other values are user-defined *)
114
The yywrap function is called by yylex at end-of-file (unless you have
115
specified a rule matching end-of-file). You may redefine this routine
116
in your Lex program to do application-dependent processing at end of
117
file. In particular, yywrap may arrange for more input and return false
118
in which case the yylex routine resumes lexical analysis. *)
120
function yywrap : Boolean;
121
(* The default yywrap routine supplied here closes input and output files
122
and returns true (causing yylex to terminate). *)
124
(* The following are the internal data structures and routines used by the
125
lexical analyzer routine yylex; they should not be used directly. *)
129
yystate : Integer; (* current state of lexical analyzer *)
130
yyactchar : Char; (* current character *)
131
yylastchar : Char; (* last matched character (#0 if none) *)
132
yyrule : Integer; (* matched rule *)
133
yyreject : Boolean; (* current match rejected? *)
134
yydone : Boolean; (* yylex return value set? *)
135
yyretval : Integer; (* yylex return value *)
138
(* starts next match; initializes state information of the lexical
142
(* gets next character from the input stream and updates yytext and
143
yyactchar accordingly *)
145
procedure yymark ( n : Integer );
146
(* marks position for rule no. n *)
148
procedure yymatch ( n : Integer );
149
(* declares a match for rule number n *)
151
function yyfind ( var n : Integer ) : Boolean;
152
(* finds the last match and the corresponding marked position and adjusts
153
the matched string accordingly; returns:
154
- true if a rule has been matched, false otherwise
155
- n: the number of the matched rule *)
157
function yydefault : Boolean;
158
(* executes the default action (copy character); returns true unless
162
(* reinitializes state information after lexical analysis has been
167
procedure fatal ( msg : String );
168
(* writes a fatal error message and halts program *)
170
writeln('LexLib: ', msg);
176
const nl = #10; (* newline character *)
178
const max_chars = 2048;
183
buf : array [1..max_chars] of Char;
185
function get_char : Char;
188
if (bufptr=0) and not eof(yyinput) then
190
readln(yyinput, yyline);
191
inc(yylineno); yycolno := 1;
193
for i := 1 to length(yyline) do
194
buf[i+1] := yyline[length(yyline)-i+1];
195
inc(bufptr, length(yyline)+1);
199
get_char := buf[bufptr];
207
procedure unget_char ( c : Char );
209
if bufptr=max_chars then fatal('input buffer overflow');
215
procedure put_char ( c : Char );
227
Some state information is maintained to keep track with calls to yymore,
228
yyless, reject, start and yymatch/yymark, and to initialize state
229
information used by the lexical analyzer.
230
- yystext: contains the initial contents of the yytext variable; this
231
will be the empty string, unless yymore is called which sets yystext
232
to the current yytext
233
- yysstate: start state of lexical analyzer (set to 0 during
234
initialization, and modified in calls to the start routine)
235
- yylstate: line state information (1 if at beginning of line, 0
237
- yystack: stack containing matched rules; yymatches contains the number of
239
- yypos: for each rule the last marked position (yymark); zeroed when rule
240
has already been considered
241
- yysleng: copy of the original yyleng used to restore state information
242
when reject is used *)
252
yysstate, yylstate : Integer;
254
yystack : array [1..max_matches] of Integer;
255
yypos : array [1..max_rules] of Integer;
263
for i := 1 to yyleng do
272
procedure yyless ( n : Integer );
275
for i := yyleng downto n+1 do
276
unget_char(yytext[i]);
284
for i := yyleng+1 to yysleng do
285
yytext := yytext+get_char;
289
procedure return ( n : Integer );
295
procedure returnc ( c : Char );
301
procedure start ( state : Integer );
308
function yywrap : Boolean;
310
close(yyinput); close(yyoutput);
314
(* Internal routines: *)
318
if yylastchar<>#0 then
319
if yylastchar=nl then
323
yystate := yysstate+yylstate;
332
if yyleng=255 then fatal('yytext overflow');
333
yyactchar := get_char;
335
yytext[yyleng] := yyactchar;
338
procedure yymark ( n : Integer );
340
if n>max_rules then fatal('too many rules');
344
procedure yymatch ( n : Integer );
347
if yymatches>max_matches then fatal('match stack overflow');
348
yystack[yymatches] := n;
351
function yyfind ( var n : Integer ) : Boolean;
354
while (yymatches>0) and (yypos[yystack[yymatches]]=0) do
359
n := yystack[yymatches];
363
yylastchar := yytext[yyleng]
376
function yydefault : Boolean;
379
yyactchar := get_char;
380
if yyactchar<>#0 then
390
yylastchar := yyactchar;
405
assign(yyoutput, '');
406
reset(yyinput); rewrite(yyoutput);