]>
Commit | Line | Data |
---|---|---|
1eee94d3 GM |
1 | (* M2LexBuf.mod provides a buffer for m2.lex. |
2 | ||
a945c346 | 3 | Copyright (C) 2001-2024 Free Software Foundation, Inc. |
1eee94d3 GM |
4 | Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
5 | ||
6 | This file is part of GNU Modula-2. | |
7 | ||
8 | GNU Modula-2 is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GNU Modula-2 is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GNU Modula-2; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. *) | |
21 | ||
22 | IMPLEMENTATION MODULE M2LexBuf ; | |
23 | ||
24 | IMPORT m2flex ; | |
25 | ||
26 | FROM libc IMPORT strlen ; | |
27 | FROM SYSTEM IMPORT ADDRESS ; | |
28 | FROM Storage IMPORT ALLOCATE, DEALLOCATE ; | |
29 | FROM DynamicStrings IMPORT string, InitString, InitStringCharStar, Equal, Mark, KillString ; | |
30 | FROM FormatStrings IMPORT Sprintf1 ; | |
31 | FROM NameKey IMPORT NulName, Name, makekey, MakeKey, KeyToCharStar ; | |
32 | FROM M2Reserved IMPORT toktype, tokToTok ; | |
33 | FROM M2Printf IMPORT printf0, printf1, printf2, printf3 ; | |
34 | FROM M2Debug IMPORT Assert ; | |
35 | FROM NameKey IMPORT makekey ; | |
36 | FROM m2linemap IMPORT location_t, GetLocationBinary ; | |
37 | FROM M2Emit IMPORT UnknownLocation, BuiltinsLocation ; | |
38 | FROM M2Error IMPORT WarnStringAt ; | |
39 | ||
40 | CONST | |
41 | MaxBucketSize = 100 ; | |
42 | Debugging = FALSE ; | |
43 | DebugRecover = FALSE ; | |
44 | InitialSourceToken = 2 ; (* 0 is unknown, 1 is builtin. *) | |
45 | ||
46 | TYPE | |
47 | SourceList = POINTER TO RECORD | |
48 | left, | |
49 | right: SourceList ; | |
50 | name : String ; | |
51 | line : CARDINAL ; | |
52 | col : CARDINAL ; | |
53 | END ; | |
54 | ||
55 | TokenDesc = RECORD | |
56 | token : toktype ; | |
57 | str : Name ; (* ident name or string literal. *) | |
58 | int : INTEGER ; | |
59 | line : CARDINAL ; | |
60 | col : CARDINAL ; | |
61 | file : SourceList ; | |
62 | loc : location_t ; | |
63 | insert: TokenBucket ; (* contains any inserted tokens. *) | |
64 | END ; | |
65 | ||
66 | TokenBucket = POINTER TO RECORD | |
67 | buf : ARRAY [0..MaxBucketSize] OF TokenDesc ; | |
68 | len : CARDINAL ; | |
69 | next: TokenBucket ; | |
70 | END ; | |
71 | ||
72 | ListDesc = RECORD | |
73 | head, | |
74 | tail : TokenBucket ; | |
75 | LastBucketOffset: CARDINAL ; | |
76 | END ; | |
77 | ||
78 | VAR | |
79 | CurrentSource : SourceList ; | |
80 | UseBufferedTokens, | |
81 | CurrentUsed : BOOLEAN ; | |
82 | ListOfTokens : ListDesc ; | |
83 | CurrentTokNo : CARDINAL ; | |
84 | InsertionIndex : CARDINAL ; | |
97bf709f GM |
85 | SeenEof : BOOLEAN ; (* Have we seen eof since the last call |
86 | to OpenSource. *) | |
1eee94d3 GM |
87 | |
88 | ||
89 | (* | |
90 | InitTokenList - creates an empty token list, which starts the first source token | |
91 | at position 2. This allows position 0 to be for unknown location | |
92 | and position 1 for builtin token. | |
93 | *) | |
94 | ||
95 | PROCEDURE InitTokenList ; | |
96 | BEGIN | |
97 | NEW (ListOfTokens.head) ; | |
98 | ListOfTokens.tail := ListOfTokens.head ; | |
99 | WITH ListOfTokens.tail^.buf[0] DO | |
100 | token := eoftok ; | |
101 | str := NulName ; | |
102 | int := 0 ; | |
103 | line := 0 ; | |
104 | col := 0 ; | |
105 | file := NIL ; | |
106 | loc := UnknownLocation () | |
107 | END ; | |
108 | WITH ListOfTokens.tail^.buf[1] DO | |
109 | token := eoftok ; | |
110 | str := NulName ; | |
111 | int := 0 ; | |
112 | line := 0 ; | |
113 | col := 0 ; | |
114 | file := NIL ; | |
115 | loc := BuiltinsLocation () | |
116 | END ; | |
117 | ListOfTokens.tail^.len := InitialSourceToken | |
118 | END InitTokenList ; | |
119 | ||
120 | ||
121 | (* | |
122 | Init - initializes the token list and source list. | |
123 | *) | |
124 | ||
125 | PROCEDURE Init ; | |
126 | BEGIN | |
97bf709f | 127 | SeenEof := FALSE ; |
1eee94d3 GM |
128 | InsertionIndex := 0 ; |
129 | currenttoken := eoftok ; | |
130 | CurrentTokNo := InitialSourceToken ; | |
131 | CurrentSource := NIL ; | |
132 | ListOfTokens.head := NIL ; | |
133 | ListOfTokens.tail := NIL ; | |
134 | UseBufferedTokens := FALSE ; | |
135 | InitTokenList | |
136 | END Init ; | |
137 | ||
138 | ||
139 | (* | |
140 | AddTo - adds a new element to the end of SourceList, CurrentSource. | |
141 | *) | |
142 | ||
143 | PROCEDURE AddTo (l: SourceList) ; | |
144 | BEGIN | |
145 | l^.right := CurrentSource ; | |
146 | l^.left := CurrentSource^.left ; | |
147 | CurrentSource^.left^.right := l ; | |
148 | CurrentSource^.left := l ; | |
149 | WITH l^.left^ DO | |
150 | line := m2flex.GetLineNo() ; | |
151 | col := m2flex.GetColumnNo() | |
152 | END | |
153 | END AddTo ; | |
154 | ||
155 | ||
156 | (* | |
157 | SubFrom - subtracts, l, from the source list. | |
158 | *) | |
159 | ||
160 | PROCEDURE SubFrom (l: SourceList) ; | |
161 | BEGIN | |
162 | l^.left^.right := l^.right ; | |
163 | l^.right^.left := l^.left | |
164 | END SubFrom ; | |
165 | ||
166 | ||
167 | (* | |
168 | NewElement - returns a new SourceList | |
169 | *) | |
170 | ||
171 | PROCEDURE NewElement (s: ADDRESS) : SourceList ; | |
172 | VAR | |
173 | l: SourceList ; | |
174 | BEGIN | |
175 | NEW (l) ; | |
176 | IF l = NIL | |
177 | THEN | |
178 | HALT | |
179 | ELSE | |
180 | WITH l^ DO | |
181 | name := InitStringCharStar(s) ; | |
182 | left := NIL ; | |
183 | right := NIL | |
184 | END | |
185 | END ; | |
186 | RETURN l | |
187 | END NewElement ; | |
188 | ||
189 | ||
190 | (* | |
191 | NewList - initializes an empty list with the classic dummy header element. | |
192 | *) | |
193 | ||
194 | PROCEDURE NewList () : SourceList ; | |
195 | VAR | |
196 | l: SourceList ; | |
197 | BEGIN | |
198 | NEW (l) ; | |
199 | WITH l^ DO | |
200 | left := l ; | |
201 | right := l ; | |
202 | name := NIL | |
203 | END ; | |
204 | RETURN l | |
205 | END NewList ; | |
206 | ||
207 | ||
208 | (* | |
209 | CheckIfNeedToDuplicate - checks to see whether the CurrentSource has | |
210 | been used, if it has then duplicate the list. | |
211 | *) | |
212 | ||
213 | PROCEDURE CheckIfNeedToDuplicate ; | |
214 | VAR | |
215 | l, h: SourceList ; | |
216 | BEGIN | |
217 | IF CurrentUsed | |
218 | THEN | |
219 | l := CurrentSource^.right ; | |
220 | h := CurrentSource ; | |
221 | CurrentSource := NewList() ; | |
222 | WHILE l#h DO | |
223 | AddTo (NewElement (l^.name)) ; | |
224 | l := l^.right | |
225 | END | |
226 | END | |
227 | END CheckIfNeedToDuplicate ; | |
228 | ||
229 | ||
230 | (* | |
231 | PushFile - indicates that, filename, has just been included. | |
232 | *) | |
233 | ||
234 | PROCEDURE PushFile (filename: ADDRESS) ; | |
235 | VAR | |
236 | l: SourceList ; | |
237 | BEGIN | |
238 | CheckIfNeedToDuplicate ; | |
239 | AddTo (NewElement (filename)) ; | |
240 | IF Debugging | |
241 | THEN | |
242 | IF CurrentSource^.right#CurrentSource | |
243 | THEN | |
244 | l := CurrentSource ; | |
245 | REPEAT | |
246 | printf3('name = %s, line = %d, col = %d\n', l^.name, l^.line, l^.col) ; | |
247 | l := l^.right | |
248 | UNTIL l=CurrentSource | |
249 | END | |
250 | END | |
251 | END PushFile ; | |
252 | ||
253 | ||
254 | (* | |
255 | PopFile - indicates that we are returning to, filename, having finished | |
256 | an include. | |
257 | *) | |
258 | ||
259 | PROCEDURE PopFile (filename: ADDRESS) ; | |
260 | VAR | |
261 | l: SourceList ; | |
262 | BEGIN | |
263 | CheckIfNeedToDuplicate ; | |
264 | IF (CurrentSource#NIL) AND (CurrentSource^.left#CurrentSource) | |
265 | THEN | |
266 | l := CurrentSource^.left ; (* last element *) | |
267 | SubFrom (l) ; | |
268 | DISPOSE (l) ; | |
269 | IF (CurrentSource^.left#CurrentSource) AND | |
270 | (NOT Equal(CurrentSource^.name, Mark(InitStringCharStar(filename)))) | |
271 | THEN | |
272 | (* mismatch in source file names after preprocessing files *) | |
273 | END | |
274 | ELSE | |
275 | (* source file list is empty, cannot pop an include.. *) | |
276 | END | |
277 | END PopFile ; | |
278 | ||
279 | ||
280 | (* | |
281 | KillList - kills the SourceList providing that it has not been used. | |
282 | *) | |
283 | ||
284 | PROCEDURE KillList ; | |
285 | VAR | |
286 | l, k: SourceList ; | |
287 | BEGIN | |
288 | IF (NOT CurrentUsed) AND (CurrentSource#NIL) | |
289 | THEN | |
290 | l := CurrentSource ; | |
291 | REPEAT | |
292 | k := l ; | |
293 | l := l^.right ; | |
294 | DISPOSE(k) | |
295 | UNTIL l=CurrentSource | |
296 | END | |
297 | END KillList ; | |
298 | ||
299 | ||
300 | (* | |
301 | ReInitialize - re-initialize the all the data structures. | |
302 | *) | |
303 | ||
304 | PROCEDURE ReInitialize ; | |
305 | VAR | |
306 | s, t: TokenBucket ; | |
307 | BEGIN | |
308 | IF ListOfTokens.head#NIL | |
309 | THEN | |
310 | t := ListOfTokens.head ; | |
311 | REPEAT | |
312 | s := t ; | |
313 | t := t^.next ; | |
314 | DISPOSE(s) ; | |
315 | UNTIL t=NIL ; | |
316 | CurrentUsed := FALSE ; | |
317 | KillList | |
318 | END ; | |
319 | Init | |
320 | END ReInitialize ; | |
321 | ||
322 | ||
323 | (* | |
324 | SetFile - sets the current filename to, filename. | |
325 | *) | |
326 | ||
327 | PROCEDURE SetFile (filename: ADDRESS) ; | |
328 | BEGIN | |
329 | KillList ; | |
330 | CurrentUsed := FALSE ; | |
331 | CurrentSource := NewList () ; | |
332 | AddTo (NewElement (filename)) | |
333 | END SetFile ; | |
334 | ||
335 | ||
336 | (* | |
337 | OpenSource - Attempts to open the source file, s. | |
338 | The success of the operation is returned. | |
339 | *) | |
340 | ||
341 | PROCEDURE OpenSource (s: String) : BOOLEAN ; | |
342 | BEGIN | |
97bf709f | 343 | SeenEof := FALSE ; |
1eee94d3 GM |
344 | IF UseBufferedTokens |
345 | THEN | |
346 | GetToken ; | |
347 | RETURN TRUE | |
348 | ELSE | |
349 | IF m2flex.OpenSource (string (s)) | |
350 | THEN | |
351 | SetFile (string (s)) ; | |
352 | SyncOpenWithBuffer ; | |
353 | GetToken ; | |
354 | RETURN TRUE | |
355 | ELSE | |
356 | RETURN FALSE | |
357 | END | |
358 | END | |
359 | END OpenSource ; | |
360 | ||
361 | ||
362 | (* | |
363 | CloseSource - closes the current open file. | |
364 | *) | |
365 | ||
366 | PROCEDURE CloseSource ; | |
367 | BEGIN | |
368 | IF UseBufferedTokens | |
369 | THEN | |
370 | WHILE currenttoken#eoftok DO | |
371 | GetToken | |
372 | END | |
373 | ELSE | |
374 | (* a subsequent call to m2flex.OpenSource will really close the file *) | |
375 | END | |
376 | END CloseSource ; | |
377 | ||
378 | ||
379 | (* | |
380 | ResetForNewPass - reset the buffer pointers to the beginning ready for | |
381 | a new pass | |
382 | *) | |
383 | ||
384 | PROCEDURE ResetForNewPass ; | |
385 | BEGIN | |
386 | InsertionIndex := 0 ; | |
387 | CurrentTokNo := InitialSourceToken ; | |
388 | UseBufferedTokens := TRUE | |
389 | END ResetForNewPass ; | |
390 | ||
391 | ||
392 | (* | |
393 | DisplayToken - display the token name using printf0 no newline is emitted. | |
394 | *) | |
395 | ||
396 | PROCEDURE DisplayToken (tok: toktype) ; | |
397 | BEGIN | |
398 | CASE tok OF | |
399 | ||
400 | eoftok: printf0('eoftok') | | |
401 | plustok: printf0('plustok') | | |
402 | minustok: printf0('minustok') | | |
403 | timestok: printf0('timestok') | | |
404 | dividetok: printf0('dividetok') | | |
405 | becomestok: printf0('becomestok') | | |
406 | ambersandtok: printf0('ambersandtok') | | |
407 | periodtok: printf0('periodtok') | | |
408 | commatok: printf0('commatok') | | |
409 | semicolontok: printf0('semicolontok') | | |
410 | lparatok: printf0('lparatok') | | |
411 | rparatok: printf0('rparatok') | | |
412 | lsbratok: printf0('lsbratok') | | |
413 | rsbratok: printf0('rsbratok') | | |
414 | lcbratok: printf0('lcbratok') | | |
415 | rcbratok: printf0('rcbratok') | | |
416 | uparrowtok: printf0('uparrowtok') | | |
417 | singlequotetok: printf0('singlequotetok') | | |
418 | equaltok: printf0('equaltok') | | |
419 | hashtok: printf0('hashtok') | | |
420 | lesstok: printf0('lesstok') | | |
421 | greatertok: printf0('greatertok') | | |
422 | lessgreatertok: printf0('lessgreatertok') | | |
423 | lessequaltok: printf0('lessequaltok') | | |
424 | greaterequaltok: printf0('greaterequaltok') | | |
425 | periodperiodtok: printf0('periodperiodtok') | | |
426 | colontok: printf0('colontok') | | |
427 | doublequotestok: printf0('doublequotestok') | | |
428 | bartok: printf0('bartok') | | |
429 | andtok: printf0('andtok') | | |
430 | arraytok: printf0('arraytok') | | |
431 | begintok: printf0('begintok') | | |
432 | bytok: printf0('bytok') | | |
433 | casetok: printf0('casetok') | | |
434 | consttok: printf0('consttok') | | |
435 | definitiontok: printf0('definitiontok') | | |
436 | divtok: printf0('divtok') | | |
437 | dotok: printf0('dotok') | | |
438 | elsetok: printf0('elsetok') | | |
439 | elsiftok: printf0('elsiftok') | | |
440 | endtok: printf0('endtok') | | |
441 | exittok: printf0('exittok') | | |
442 | exporttok: printf0('exporttok') | | |
443 | fortok: printf0('fortok') | | |
444 | fromtok: printf0('fromtok') | | |
445 | iftok: printf0('iftok') | | |
446 | implementationtok: printf0('implementationtok') | | |
447 | importtok: printf0('importtok') | | |
448 | intok: printf0('intok') | | |
449 | looptok: printf0('looptok') | | |
450 | modtok: printf0('modtok') | | |
451 | moduletok: printf0('moduletok') | | |
452 | nottok: printf0('nottok') | | |
453 | oftok: printf0('oftok') | | |
454 | ortok: printf0('ortok') | | |
455 | pointertok: printf0('pointertok') | | |
456 | proceduretok: printf0('proceduretok') | | |
457 | qualifiedtok: printf0('qualifiedtok') | | |
458 | unqualifiedtok: printf0('unqualifiedtok') | | |
459 | recordtok: printf0('recordtok') | | |
460 | repeattok: printf0('repeattok') | | |
461 | returntok: printf0('returntok') | | |
462 | settok: printf0('settok') | | |
463 | thentok: printf0('thentok') | | |
464 | totok: printf0('totok') | | |
465 | typetok: printf0('typetok') | | |
466 | untiltok: printf0('untiltok') | | |
467 | vartok: printf0('vartok') | | |
468 | whiletok: printf0('whiletok') | | |
469 | withtok: printf0('withtok') | | |
470 | asmtok: printf0('asmtok') | | |
471 | volatiletok: printf0('volatiletok') | | |
472 | periodperiodperiodtok: printf0('periodperiodperiodtok') | | |
473 | datetok: printf0('datetok') | | |
474 | linetok: printf0('linetok') | | |
475 | filetok: printf0('filetok') | | |
476 | integertok: printf0('integertok') | | |
477 | identtok: printf0('identtok') | | |
478 | realtok: printf0('realtok') | | |
479 | stringtok: printf0('stringtok') | |
480 | ||
481 | ELSE | |
482 | END | |
483 | END DisplayToken ; | |
484 | ||
485 | ||
486 | (* | |
487 | UpdateFromBucket - updates the global variables: currenttoken, | |
488 | currentstring, currentcolumn and currentinteger | |
489 | from TokenBucket, b, and, offset. | |
490 | *) | |
491 | ||
492 | PROCEDURE UpdateFromBucket (b: TokenBucket; offset: CARDINAL) ; | |
493 | BEGIN | |
494 | IF InsertionIndex > 0 | |
495 | THEN | |
496 | (* we have an inserted token to use. *) | |
497 | Assert (b^.buf[offset].insert # NIL) ; | |
498 | WITH b^.buf[offset].insert^.buf[InsertionIndex] DO | |
499 | currenttoken := token ; | |
500 | currentstring := KeyToCharStar(str) ; | |
501 | currentcolumn := col ; | |
502 | currentinteger := int ; | |
503 | IF Debugging | |
504 | THEN | |
505 | printf3('line %d (# %d %d) ', line, offset, CurrentTokNo) | |
506 | END | |
507 | END ; | |
508 | INC (InsertionIndex) ; | |
509 | IF InsertionIndex = b^.buf[offset].insert^.len | |
510 | THEN | |
511 | InsertionIndex := 0 ; (* finished consuming the inserted tokens. *) | |
512 | INC (CurrentTokNo) | |
513 | END | |
514 | ELSIF (b^.buf[offset].insert # NIL) AND (InsertionIndex = 0) | |
515 | THEN | |
516 | (* this source token has extra tokens appended after it by the error recovery. *) | |
517 | Assert (b^.buf[offset].insert^.len > 0) ; (* we must have at least one token. *) | |
518 | InsertionIndex := 1 ; (* so set the index ready for the next UpdateFromBucket. *) | |
519 | (* and read the original token. *) | |
520 | WITH b^.buf[offset] DO | |
521 | currenttoken := token ; | |
522 | currentstring := KeyToCharStar(str) ; | |
523 | currentcolumn := col ; | |
524 | currentinteger := int ; | |
525 | IF Debugging | |
526 | THEN | |
527 | printf3('line %d (# %d %d) ', line, offset, CurrentTokNo) | |
528 | END | |
529 | END | |
530 | ELSE | |
531 | (* no inserted tokens after this token so read it and move on. *) | |
532 | WITH b^.buf[offset] DO | |
533 | currenttoken := token ; | |
534 | currentstring := KeyToCharStar(str) ; | |
535 | currentcolumn := col ; | |
536 | currentinteger := int ; | |
537 | IF Debugging | |
538 | THEN | |
539 | printf3('line %d (# %d %d) ', line, offset, CurrentTokNo) | |
540 | END | |
541 | END ; | |
542 | INC (CurrentTokNo) | |
543 | END | |
544 | END UpdateFromBucket ; | |
545 | ||
546 | ||
547 | (* | |
548 | DisplayTokenEntry - | |
549 | *) | |
550 | ||
551 | PROCEDURE DisplayTokenEntry (topBucket: TokenBucket; index, total: CARDINAL) ; | |
552 | VAR | |
553 | i: CARDINAL ; | |
554 | BEGIN | |
555 | printf1 ("%d: ", total) ; | |
556 | DisplayToken (topBucket^.buf[index].token) ; | |
557 | printf1 (" %a ", topBucket^.buf[index].str) ; | |
558 | IF total = GetTokenNo () | |
559 | THEN | |
560 | printf0 (" <- current token") | |
561 | END ; | |
562 | printf0 ("\n") ; | |
563 | (* now check for inserted tokens. *) | |
564 | IF topBucket^.buf[index].insert # NIL | |
565 | THEN | |
566 | i := 1 ; | |
567 | WHILE i < topBucket^.buf[index].insert^.len DO | |
568 | printf1 (" %d: ", i) ; | |
569 | DisplayToken (topBucket^.buf[index].insert^.buf[i].token) ; | |
570 | printf1 (" %a\n", topBucket^.buf[index].insert^.buf[i].str) ; | |
571 | INC (i) | |
572 | END | |
573 | END | |
574 | END DisplayTokenEntry ; | |
575 | ||
576 | ||
577 | (* | |
578 | DumpTokens - developer debugging aid. | |
579 | *) | |
580 | ||
581 | PROCEDURE DumpTokens ; | |
582 | VAR | |
583 | tb : TokenBucket ; | |
584 | i, | |
585 | tokenNo, | |
586 | total, | |
587 | length : CARDINAL ; | |
588 | BEGIN | |
589 | tokenNo := GetTokenNo () ; | |
590 | tb := ListOfTokens.head ; | |
591 | total := 0 ; | |
592 | WHILE tb # NIL DO | |
593 | length := tb^.len ; | |
594 | i := 0 ; | |
595 | WHILE i < length DO | |
596 | DisplayTokenEntry (tb, i, total) ; | |
597 | INC (i) ; | |
598 | INC (total) | |
599 | END ; | |
600 | tb := tb^.next | |
601 | END ; | |
602 | printf2 ("%d: tokenNo, %d: total\n", tokenNo, total) ; | |
603 | IF (total # 0) AND (tokenNo = total) | |
604 | THEN | |
605 | printf1 ("%d: end of buffer ", total) ; | |
606 | printf0 (" <- current token") ; | |
607 | printf0 ("\n") ; | |
608 | END ; | |
609 | END DumpTokens ; | |
610 | ||
611 | ||
97bf709f GM |
612 | (* |
613 | GetNonEofToken - providing that we have not already seen an eof for this source | |
614 | file call m2flex.GetToken and GetToken if requested. | |
615 | *) | |
616 | ||
617 | PROCEDURE GetNonEofToken (callGetToken: BOOLEAN) ; | |
618 | BEGIN | |
619 | IF SeenEof | |
620 | THEN | |
621 | currenttoken := eoftok | |
622 | ELSE | |
623 | (* Call the lexical phase to place a new token into the last bucket. *) | |
624 | m2flex.GetToken () ; | |
625 | IF callGetToken | |
626 | THEN | |
627 | GetToken | |
628 | END | |
629 | END | |
630 | END GetNonEofToken ; | |
631 | ||
632 | ||
1eee94d3 GM |
633 | (* |
634 | GetToken - gets the next token into currenttoken. | |
635 | *) | |
636 | ||
637 | PROCEDURE GetToken ; | |
638 | VAR | |
639 | t: CARDINAL ; | |
640 | b: TokenBucket ; | |
641 | BEGIN | |
642 | IF UseBufferedTokens | |
643 | THEN | |
644 | t := CurrentTokNo ; | |
645 | b := FindTokenBucket(t) ; | |
646 | UpdateFromBucket (b, t) | |
647 | ELSE | |
648 | IF ListOfTokens.tail=NIL | |
649 | THEN | |
97bf709f | 650 | GetNonEofToken (FALSE) ; |
1eee94d3 GM |
651 | IF ListOfTokens.tail=NIL |
652 | THEN | |
653 | HALT | |
654 | END | |
655 | END ; | |
656 | IF CurrentTokNo>=ListOfTokens.LastBucketOffset | |
657 | THEN | |
97bf709f | 658 | (* CurrentTokNo is in the last bucket or needs to be read. *) |
1eee94d3 GM |
659 | IF CurrentTokNo-ListOfTokens.LastBucketOffset<ListOfTokens.tail^.len |
660 | THEN | |
661 | UpdateFromBucket (ListOfTokens.tail, | |
662 | CurrentTokNo-ListOfTokens.LastBucketOffset) | |
663 | ELSE | |
97bf709f GM |
664 | (* and call ourselves again to collect the token from bucket *) |
665 | GetNonEofToken (TRUE) | |
1eee94d3 GM |
666 | END |
667 | ELSE | |
668 | t := CurrentTokNo ; | |
669 | b := FindTokenBucket (t) ; | |
670 | UpdateFromBucket (b, t) | |
671 | END | |
672 | END | |
673 | END GetToken ; | |
674 | ||
675 | ||
676 | (* | |
677 | SyncOpenWithBuffer - synchronise the buffer with the start of a file. | |
678 | Skips all the tokens to do with the previous file. | |
679 | *) | |
680 | ||
681 | PROCEDURE SyncOpenWithBuffer ; | |
682 | BEGIN | |
683 | IF ListOfTokens.tail#NIL | |
684 | THEN | |
685 | WITH ListOfTokens.tail^ DO | |
686 | CurrentTokNo := ListOfTokens.LastBucketOffset+len | |
687 | END | |
688 | END | |
689 | END SyncOpenWithBuffer ; | |
690 | ||
691 | ||
692 | (* | |
693 | GetInsertBucket - returns the insertion bucket associated with token count | |
694 | and the topBucket. It creates a new TokenBucket if necessary. | |
695 | *) | |
696 | ||
697 | PROCEDURE GetInsertBucket (topBucket: TokenBucket; count: CARDINAL) : TokenBucket ; | |
698 | BEGIN | |
699 | IF topBucket^.buf[count].insert = NIL | |
700 | THEN | |
701 | NEW (topBucket^.buf[count].insert) ; | |
702 | topBucket^.buf[count].insert^.buf[0] := topBucket^.buf[count] ; | |
703 | topBucket^.buf[count].insert^.buf[0].insert := NIL ; | |
704 | topBucket^.buf[count].insert^.len := 1 (* empty, slot 0 contains the original token for ease. *) | |
705 | END ; | |
706 | RETURN topBucket^.buf[count].insert | |
707 | END GetInsertBucket ; | |
708 | ||
709 | ||
710 | (* | |
711 | AppendToken - appends desc to the end of the insertionBucket. | |
712 | *) | |
713 | ||
714 | PROCEDURE AppendToken (insertionBucket: TokenBucket; desc: TokenDesc) ; | |
715 | BEGIN | |
716 | IF insertionBucket^.len < MaxBucketSize | |
717 | THEN | |
718 | insertionBucket^.buf[insertionBucket^.len] := desc ; | |
719 | INC (insertionBucket^.len) | |
720 | END | |
721 | END AppendToken ; | |
722 | ||
723 | ||
724 | (* | |
725 | InsertToken - inserts a symbol, token, infront of the current token | |
726 | ready for the next pass. | |
727 | *) | |
728 | ||
729 | PROCEDURE InsertToken (token: toktype) ; | |
730 | VAR | |
731 | topBucket, insertionBucket: TokenBucket ; | |
732 | count : CARDINAL ; | |
733 | desc : TokenDesc ; | |
734 | BEGIN | |
735 | Assert (ListOfTokens.tail # NIL) ; | |
736 | count := GetTokenNo () -1 ; | |
737 | topBucket := FindTokenBucket (count) ; | |
738 | insertionBucket := GetInsertBucket (topBucket, count) ; | |
739 | desc := topBucket^.buf[count] ; | |
740 | desc.token := token ; | |
741 | desc.insert := NIL ; | |
742 | AppendToken (insertionBucket, desc) ; | |
743 | IF DebugRecover | |
744 | THEN | |
745 | DumpTokens | |
746 | END | |
747 | END InsertToken ; | |
748 | ||
749 | ||
750 | (* | |
751 | InsertTokenAndRewind - inserts a symbol, token, infront of the current token | |
752 | and then moves the token stream back onto the inserted token. | |
753 | *) | |
754 | ||
755 | PROCEDURE InsertTokenAndRewind (token: toktype) ; | |
756 | VAR | |
757 | offset : CARDINAL ; | |
758 | topBucket: TokenBucket ; | |
759 | BEGIN | |
760 | IF GetTokenNo () > 0 | |
761 | THEN | |
762 | InsertToken (token) ; | |
763 | offset := CurrentTokNo -2 ; | |
764 | topBucket := FindTokenBucket (offset) ; | |
765 | InsertionIndex := topBucket^.buf[offset].insert^.len -1 ; | |
766 | DEC (CurrentTokNo, 2) ; | |
767 | GetToken | |
768 | END | |
769 | END InsertTokenAndRewind ; | |
770 | ||
771 | ||
772 | (* | |
773 | GetPreviousTokenLineNo - returns the line number of the previous token. | |
774 | *) | |
775 | ||
776 | PROCEDURE GetPreviousTokenLineNo () : CARDINAL ; | |
777 | BEGIN | |
778 | (* | |
779 | IF GetTokenNo()>0 | |
780 | THEN | |
781 | RETURN( TokenToLineNo(GetTokenNo()-1, 0) ) | |
782 | ELSE | |
783 | RETURN( 0 ) | |
784 | END | |
785 | *) | |
786 | RETURN GetLineNo () | |
787 | END GetPreviousTokenLineNo ; | |
788 | ||
789 | ||
790 | (* | |
791 | GetLineNo - returns the current line number where the symbol occurs in | |
792 | the source file. | |
793 | *) | |
794 | ||
795 | PROCEDURE GetLineNo () : CARDINAL ; | |
796 | BEGIN | |
797 | IF CurrentTokNo = 0 | |
798 | THEN | |
799 | RETURN 0 | |
800 | ELSE | |
801 | RETURN TokenToLineNo (GetTokenNo (), 0) | |
802 | END | |
803 | END GetLineNo ; | |
804 | ||
805 | ||
806 | (* | |
807 | GetColumnNo - returns the current column where the symbol occurs in | |
808 | the source file. | |
809 | *) | |
810 | ||
811 | PROCEDURE GetColumnNo () : CARDINAL ; | |
812 | BEGIN | |
813 | IF CurrentTokNo = 0 | |
814 | THEN | |
815 | RETURN 0 | |
816 | ELSE | |
817 | RETURN TokenToColumnNo (GetTokenNo (), 0) | |
818 | END | |
819 | END GetColumnNo ; | |
820 | ||
821 | ||
822 | (* | |
823 | GetTokenNo - returns the current token number. | |
824 | *) | |
825 | ||
826 | PROCEDURE GetTokenNo () : CARDINAL ; | |
827 | BEGIN | |
828 | IF CurrentTokNo = 0 | |
829 | THEN | |
830 | RETURN 0 | |
831 | ELSE | |
832 | RETURN CurrentTokNo-1 | |
833 | END | |
834 | END GetTokenNo ; | |
835 | ||
836 | ||
837 | (* | |
838 | GetTokenName - returns the token name given the tokenno. | |
839 | *) | |
840 | ||
841 | PROCEDURE GetTokenName (tokenno: CARDINAL) : Name ; | |
842 | VAR | |
843 | b: TokenBucket ; | |
844 | n: Name ; | |
845 | BEGIN | |
846 | b := FindTokenBucket (tokenno) ; | |
847 | IF b=NIL | |
848 | THEN | |
849 | RETURN NulName | |
850 | ELSE | |
851 | WITH b^.buf[tokenno] DO | |
852 | n := tokToTok (token) ; | |
853 | IF n=NulName | |
854 | THEN | |
855 | RETURN str | |
856 | ELSE | |
857 | RETURN n | |
858 | END | |
859 | END | |
860 | END | |
861 | END GetTokenName ; | |
862 | ||
863 | ||
864 | (* | |
865 | FindTokenBucket - returns the TokenBucket corresponding to the TokenNo. | |
866 | *) | |
867 | ||
868 | PROCEDURE FindTokenBucket (VAR TokenNo: CARDINAL) : TokenBucket ; | |
869 | VAR | |
870 | b: TokenBucket ; | |
871 | BEGIN | |
872 | b := ListOfTokens.head ; | |
873 | WHILE b#NIL DO | |
874 | WITH b^ DO | |
875 | IF TokenNo<len | |
876 | THEN | |
877 | RETURN b | |
878 | ELSE | |
879 | DEC (TokenNo, len) | |
880 | END | |
881 | END ; | |
882 | b := b^.next | |
883 | END ; | |
884 | RETURN NIL | |
885 | END FindTokenBucket ; | |
886 | ||
887 | ||
888 | (* | |
889 | TokenToLineNo - returns the line number of the current file for the | |
890 | TokenNo. The depth refers to the include depth. | |
891 | A depth of 0 is the current file, depth of 1 is the file | |
892 | which included the current file. Zero is returned if the | |
893 | depth exceeds the file nesting level. | |
894 | *) | |
895 | ||
896 | PROCEDURE TokenToLineNo (TokenNo: CARDINAL; depth: CARDINAL) : CARDINAL ; | |
897 | VAR | |
898 | b: TokenBucket ; | |
899 | l: SourceList ; | |
900 | BEGIN | |
901 | IF (TokenNo = UnknownTokenNo) OR (TokenNo = BuiltinTokenNo) | |
902 | THEN | |
903 | RETURN 0 | |
904 | ELSE | |
905 | b := FindTokenBucket (TokenNo) ; | |
906 | IF b = NIL | |
907 | THEN | |
908 | RETURN 0 | |
909 | ELSE | |
910 | IF depth = 0 | |
911 | THEN | |
912 | RETURN b^.buf[TokenNo].line | |
913 | ELSE | |
914 | l := b^.buf[TokenNo].file^.left ; | |
915 | WHILE depth>0 DO | |
916 | l := l^.left ; | |
917 | IF l=b^.buf[TokenNo].file^.left | |
918 | THEN | |
919 | RETURN 0 | |
920 | END ; | |
921 | DEC (depth) | |
922 | END ; | |
923 | RETURN l^.line | |
924 | END | |
925 | END | |
926 | END | |
927 | END TokenToLineNo ; | |
928 | ||
929 | ||
930 | (* | |
931 | TokenToColumnNo - returns the column number of the current file for the | |
932 | TokenNo. The depth refers to the include depth. | |
933 | A depth of 0 is the current file, depth of 1 is the file | |
934 | which included the current file. Zero is returned if the | |
935 | depth exceeds the file nesting level. | |
936 | *) | |
937 | ||
938 | PROCEDURE TokenToColumnNo (TokenNo: CARDINAL; depth: CARDINAL) : CARDINAL ; | |
939 | VAR | |
940 | b: TokenBucket ; | |
941 | l: SourceList ; | |
942 | BEGIN | |
943 | IF (TokenNo = UnknownTokenNo) OR (TokenNo = BuiltinTokenNo) | |
944 | THEN | |
945 | RETURN 0 | |
946 | ELSE | |
947 | b := FindTokenBucket (TokenNo) ; | |
948 | IF b=NIL | |
949 | THEN | |
950 | RETURN 0 | |
951 | ELSE | |
952 | IF depth = 0 | |
953 | THEN | |
954 | RETURN b^.buf[TokenNo].col | |
955 | ELSE | |
956 | l := b^.buf[TokenNo].file^.left ; | |
957 | WHILE depth>0 DO | |
958 | l := l^.left ; | |
959 | IF l=b^.buf[TokenNo].file^.left | |
960 | THEN | |
961 | RETURN 0 | |
962 | END ; | |
963 | DEC (depth) | |
964 | END ; | |
965 | RETURN l^.col | |
966 | END | |
967 | END | |
968 | END | |
969 | END TokenToColumnNo ; | |
970 | ||
971 | ||
972 | (* | |
973 | TokenToLocation - returns the location_t corresponding to, TokenNo. | |
974 | *) | |
975 | ||
976 | PROCEDURE TokenToLocation (TokenNo: CARDINAL) : location_t ; | |
977 | VAR | |
978 | b: TokenBucket ; | |
979 | BEGIN | |
980 | IF TokenNo = UnknownTokenNo | |
981 | THEN | |
982 | RETURN UnknownLocation () | |
983 | ELSIF TokenNo = BuiltinTokenNo | |
984 | THEN | |
985 | RETURN BuiltinsLocation () | |
986 | ELSE | |
987 | b := FindTokenBucket (TokenNo) ; | |
988 | IF b=NIL | |
989 | THEN | |
990 | RETURN UnknownLocation () | |
991 | ELSE | |
992 | RETURN b^.buf[TokenNo].loc | |
993 | END | |
994 | END | |
995 | END TokenToLocation ; | |
996 | ||
997 | ||
998 | (* | |
999 | FindFileNameFromToken - returns the complete FileName for the appropriate | |
1000 | source file yields the token number, TokenNo. | |
1001 | The, Depth, indicates the include level: 0..n | |
1002 | Level 0 is the current. NIL is returned if n+1 | |
1003 | is requested. | |
1004 | *) | |
1005 | ||
1006 | PROCEDURE FindFileNameFromToken (TokenNo: CARDINAL; depth: CARDINAL) : String ; | |
1007 | VAR | |
1008 | b: TokenBucket ; | |
1009 | l: SourceList ; | |
1010 | BEGIN | |
1011 | b := FindTokenBucket (TokenNo) ; | |
1012 | IF b=NIL | |
1013 | THEN | |
1014 | RETURN NIL | |
1015 | ELSE | |
1016 | IF TokenNo = UnknownTokenNo | |
1017 | THEN | |
1018 | RETURN NIL | |
1019 | ELSIF TokenNo = BuiltinTokenNo | |
1020 | THEN | |
1021 | RETURN NIL | |
1022 | ELSE | |
1023 | l := b^.buf[TokenNo].file^.left ; | |
1024 | WHILE depth>0 DO | |
1025 | l := l^.left ; | |
1026 | IF l=b^.buf[TokenNo].file^.left | |
1027 | THEN | |
1028 | RETURN NIL | |
1029 | END ; | |
1030 | DEC (depth) | |
1031 | END ; | |
1032 | RETURN l^.name | |
1033 | END | |
1034 | END | |
1035 | END FindFileNameFromToken ; | |
1036 | ||
1037 | ||
1038 | (* | |
1039 | GetFileName - returns a String defining the current file. | |
1040 | *) | |
1041 | ||
1042 | PROCEDURE GetFileName () : String ; | |
1043 | BEGIN | |
1044 | RETURN FindFileNameFromToken (GetTokenNo (), 0) | |
1045 | END GetFileName ; | |
1046 | ||
1047 | ||
1048 | (* | |
1049 | AddTokToList - adds a token to a dynamic list. | |
1050 | *) | |
1051 | ||
1052 | PROCEDURE AddTokToList (t: toktype; n: Name; | |
1053 | i: INTEGER; l: CARDINAL; c: CARDINAL; | |
1054 | f: SourceList; location: location_t) ; | |
1055 | BEGIN | |
1056 | IF ListOfTokens.head=NIL | |
1057 | THEN | |
1058 | NEW (ListOfTokens.head) ; | |
1059 | IF ListOfTokens.head=NIL | |
1060 | THEN | |
1061 | (* list error *) | |
1062 | END ; | |
1063 | ListOfTokens.tail := ListOfTokens.head ; | |
1064 | ListOfTokens.tail^.len := 0 | |
1065 | ELSIF ListOfTokens.tail^.len=MaxBucketSize | |
1066 | THEN | |
1067 | Assert(ListOfTokens.tail^.next=NIL) ; | |
1068 | NEW (ListOfTokens.tail^.next) ; | |
1069 | IF ListOfTokens.tail^.next=NIL | |
1070 | THEN | |
1071 | (* list error *) | |
1072 | ELSE | |
1073 | ListOfTokens.tail := ListOfTokens.tail^.next ; | |
1074 | ListOfTokens.tail^.len := 0 | |
1075 | END ; | |
1076 | INC (ListOfTokens.LastBucketOffset, MaxBucketSize) | |
1077 | END ; | |
1078 | WITH ListOfTokens.tail^ DO | |
1079 | next := NIL ; | |
1080 | WITH buf[len] DO | |
1081 | token := t ; | |
1082 | str := n ; | |
1083 | int := i ; | |
1084 | line := l ; | |
1085 | col := c ; | |
1086 | file := f ; | |
1087 | loc := location ; | |
1088 | insert := NIL ; | |
1089 | END ; | |
1090 | INC (len) | |
1091 | END | |
1092 | END AddTokToList ; | |
1093 | ||
1094 | ||
1095 | (* | |
1096 | IsLastTokenEof - returns TRUE if the last token was an eoftok | |
1097 | *) | |
1098 | ||
1099 | PROCEDURE IsLastTokenEof () : BOOLEAN ; | |
1100 | VAR | |
1101 | b: TokenBucket ; | |
1102 | BEGIN | |
1103 | IF ListOfTokens.tail#NIL | |
1104 | THEN | |
1105 | IF ListOfTokens.tail^.len=0 | |
1106 | THEN | |
1107 | b := ListOfTokens.head ; | |
1108 | IF b=ListOfTokens.tail | |
1109 | THEN | |
1110 | RETURN FALSE | |
1111 | END ; | |
1112 | WHILE b^.next#ListOfTokens.tail DO | |
1113 | b := b^.next | |
1114 | END ; | |
1115 | ELSE | |
1116 | b := ListOfTokens.tail | |
1117 | END ; | |
1118 | WITH b^ DO | |
1119 | Assert (len>0) ; (* len should always be >0 *) | |
1120 | RETURN buf[len-1].token=eoftok | |
1121 | END | |
1122 | END ; | |
1123 | RETURN FALSE | |
1124 | END IsLastTokenEof ; | |
1125 | ||
1126 | ||
1127 | (* | |
1128 | PrintTokenNo - displays token and the location of the token. | |
1129 | *) | |
1130 | ||
1131 | PROCEDURE PrintTokenNo (tokenno: CARDINAL) ; | |
1132 | VAR | |
1133 | s: String ; | |
1134 | BEGIN | |
1135 | printf1 ("tokenno = %d, ", tokenno) ; | |
1136 | s := InitStringCharStar (KeyToCharStar (GetTokenName (tokenno))) ; | |
1137 | printf1 ("%s\n", s) ; | |
1138 | s := KillString (s) | |
1139 | END PrintTokenNo ; | |
1140 | ||
1141 | ||
1142 | (* | |
c8f2be5d GM |
1143 | isSrcToken - returns TRUE if tokenno is associated with |
1144 | program source code. | |
1eee94d3 GM |
1145 | *) |
1146 | ||
1147 | PROCEDURE isSrcToken (tokenno: CARDINAL) : BOOLEAN ; | |
1148 | BEGIN | |
1149 | RETURN (tokenno # UnknownTokenNo) AND (tokenno # BuiltinTokenNo) | |
1150 | END isSrcToken ; | |
1151 | ||
1152 | ||
1153 | (* | |
1154 | MakeVirtualTok - providing caret, left, right are associated with a source file | |
1155 | and exist on the same src line then | |
1156 | create and return a new tokenno which is created from | |
1157 | tokenno range1 and range2. Otherwise return caret. | |
1158 | *) | |
1159 | ||
1160 | PROCEDURE MakeVirtualTok (caret, left, right: CARDINAL) : CARDINAL ; | |
1161 | VAR | |
1162 | bufLeft, bufRight: TokenBucket ; | |
1163 | lc, ll, lr : location_t ; | |
1164 | BEGIN | |
1eee94d3 GM |
1165 | IF isSrcToken (caret) AND isSrcToken (left) AND isSrcToken (right) |
1166 | THEN | |
1167 | lc := TokenToLocation (caret) ; | |
1168 | ll := TokenToLocation (left) ; | |
1169 | lr := TokenToLocation (right) ; | |
1170 | bufLeft := FindTokenBucket (left) ; (* left maybe changed now. *) | |
1171 | bufRight := FindTokenBucket (right) ; (* right maybe changed now. *) | |
1172 | ||
1173 | IF (bufLeft^.buf[left].line = bufRight^.buf[right].line) AND | |
1174 | (bufLeft^.buf[left].file = bufRight^.buf[right].file) | |
1175 | THEN | |
1176 | (* on the same line, create a new token and location. *) | |
1177 | AddTokToList (virtualrangetok, NulName, 0, | |
1178 | bufLeft^.buf[left].line, bufLeft^.buf[left].col, bufLeft^.buf[left].file, | |
1179 | GetLocationBinary (lc, ll, lr)) ; | |
1180 | RETURN ListOfTokens.LastBucketOffset + ListOfTokens.tail^.len - 1 | |
1181 | END | |
1182 | END ; | |
1183 | RETURN caret | |
1184 | END MakeVirtualTok ; | |
1185 | ||
1186 | ||
1187 | (* *********************************************************************** | |
1188 | * | |
1189 | * These functions allow m2.flex to deliver tokens into the buffer | |
1190 | * | |
1191 | ************************************************************************* *) | |
1192 | ||
1193 | (* | |
1194 | AddTok - adds a token to the buffer. | |
1195 | *) | |
1196 | ||
1197 | PROCEDURE AddTok (t: toktype) ; | |
1198 | VAR | |
1199 | s: String ; | |
1200 | BEGIN | |
97bf709f GM |
1201 | IF t = eoftok |
1202 | THEN | |
1203 | SeenEof := TRUE | |
1204 | END ; | |
1eee94d3 GM |
1205 | IF NOT ((t=eoftok) AND IsLastTokenEof()) |
1206 | THEN | |
1207 | AddTokToList(t, NulName, 0, | |
1208 | m2flex.GetLineNo(), m2flex.GetColumnNo(), CurrentSource, | |
1209 | m2flex.GetLocation()) ; | |
1210 | CurrentUsed := TRUE ; | |
1211 | IF Debugging | |
1212 | THEN | |
1213 | (* display each token as a warning. *) | |
1214 | s := InitStringCharStar (KeyToCharStar (GetTokenName (GetTokenNo ()))) ; | |
1215 | WarnStringAt (s, GetTokenNo ()) | |
1216 | END | |
1217 | END | |
1218 | END AddTok ; | |
1219 | ||
1220 | ||
1221 | (* | |
1222 | AddTokCharStar - adds a token to the buffer and an additional string, s. | |
1223 | A copy of string, s, is made. | |
1224 | *) | |
1225 | ||
1226 | PROCEDURE AddTokCharStar (t: toktype; s: ADDRESS) ; | |
1227 | BEGIN | |
1228 | AddTokToList(t, makekey(s), 0, m2flex.GetLineNo(), | |
1229 | m2flex.GetColumnNo(), CurrentSource, m2flex.GetLocation()) ; | |
1230 | CurrentUsed := TRUE | |
1231 | END AddTokCharStar ; | |
1232 | ||
1233 | ||
1234 | (* | |
1235 | AddTokInteger - adds a token and an integer to the buffer. | |
1236 | *) | |
1237 | ||
1238 | PROCEDURE AddTokInteger (t: toktype; i: INTEGER) ; | |
1239 | VAR | |
1240 | s: String ; | |
1241 | c, | |
1242 | l: CARDINAL ; | |
1243 | BEGIN | |
1244 | l := m2flex.GetLineNo() ; | |
1245 | c := m2flex.GetColumnNo() ; | |
1246 | s := Sprintf1(Mark(InitString('%d')), i) ; | |
1247 | AddTokToList(t, makekey(string(s)), i, l, c, CurrentSource, m2flex.GetLocation()) ; | |
1248 | s := KillString(s) ; | |
1249 | CurrentUsed := TRUE | |
1250 | END AddTokInteger ; | |
1251 | ||
1252 | ||
1253 | BEGIN | |
1254 | Init | |
1255 | END M2LexBuf. |