Subversion Repositories Kolibri OS

Rev

Rev 7983 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
7597 akron1 2
    BSD 2-Clause License
6613 leency 3
 
8097 maxcodehac 4
    Copyright (c) 2018-2020, Anton Krotov
7597 akron1 5
    All rights reserved.
6613 leency 6
*)
7
 
8
MODULE SCAN;
9
 
8097 maxcodehac 10
IMPORT TXT := TEXTDRV, AVL := AVLTREES, ARITH, S := STRINGS, ERRORS, LISTS;
6613 leency 11
 
7597 akron1 12
 
6613 leency 13
CONST
14
 
7597 akron1 15
    LEXLEN = 1024;
6613 leency 16
 
7693 akron1 17
    lxUNDEF*   =  0;  lxIDENT*   =  1;  lxINTEGER*   =  2;  lxHEX*     =  3;
18
    lxCHAR*    =  4;  lxFLOAT*   =  5;  lxSTRING*    =  6;  lxCOMMENT* =  7;
19
    lxEOF*     =  8;
6613 leency 20
 
7693 akron1 21
    lxPLUS*    = 21;  lxMINUS*   = 22;  lxMUL*       = 23;  lxSLASH*   = 24;
22
    lxNOT*     = 25;  lxAND*     = 26;  lxPOINT*     = 27;  lxCOMMA*   = 28;
23
    lxSEMI*    = 29;  lxBAR*     = 30;  lxLROUND*    = 31;  lxLSQUARE* = 32;
24
    lxLCURLY*  = 33;  lxCARET*   = 34;  lxEQ*        = 35;  lxNE*      = 36;
25
    lxLT*      = 37;  lxGT*      = 38;  lxCOLON*     = 39;  lxRROUND*  = 40;
26
    lxRSQUARE* = 41;  lxRCURLY*  = 42;  lxLE*        = 43;  lxGE*      = 44;
27
    lxASSIGN*  = 45;  lxRANGE*   = 46;
6613 leency 28
 
7693 akron1 29
    lxKW       = 51;
6613 leency 30
 
7693 akron1 31
    lxARRAY*   = 51;  lxBEGIN*   = 52;  lxBY*        = 53;  lxCASE*    = 54;
32
    lxCONST*   = 55;  lxDIV*     = 56;  lxDO*        = 57;  lxELSE*    = 58;
33
    lxELSIF*   = 59;  lxEND*     = 60;  lxFALSE*     = 61;  lxFOR*     = 62;
34
    lxIF*      = 63;  lxIMPORT*  = 64;  lxIN*        = 65;  lxIS*      = 66;
35
    lxMOD*     = 67;  lxMODULE*  = 68;  lxNIL*       = 69;  lxOF*      = 70;
36
    lxOR*      = 71;  lxPOINTER* = 72;  lxPROCEDURE* = 73;  lxRECORD*  = 74;
37
    lxREPEAT*  = 75;  lxRETURN*  = 76;  lxTHEN*      = 77;  lxTO*      = 78;
38
    lxTRUE*    = 79;  lxTYPE*    = 80;  lxUNTIL*     = 81;  lxVAR*     = 82;
39
    lxWHILE*   = 83;
7597 akron1 40
 
7693 akron1 41
    lxERROR01* =  -1;  lxERROR02* =  -2;  lxERROR03* =  -3;  lxERROR04* =  -4;
42
    lxERROR05* =  -5;  lxERROR06* =  -6;  lxERROR07* =  -7;  lxERROR08* =  -8;
43
    lxERROR09* =  -9;  lxERROR10* = -10;  lxERROR11* = -11;  lxERROR12* = -12;
44
    lxERROR13* = -13;
7597 akron1 45
 
46
 
6613 leency 47
TYPE
48
 
7597 akron1 49
    LEXSTR* = ARRAY LEXLEN OF CHAR;
6613 leency 50
 
8097 maxcodehac 51
    DEF = POINTER TO RECORD (LISTS.ITEM)
52
 
53
        ident: LEXSTR
54
 
55
    END;
56
 
7597 akron1 57
    IDENT* = POINTER TO RECORD (AVL.DATA)
6613 leency 58
 
7597 akron1 59
        s*: LEXSTR;
7696 akron1 60
        offset*, offsetW*: INTEGER;
61
        key: INTEGER
6613 leency 62
 
7597 akron1 63
    END;
64
 
65
    POSITION* = RECORD
66
 
67
        line*, col*: INTEGER
68
 
69
    END;
70
 
71
    LEX* = RECORD
72
 
7693 akron1 73
        s*:         LEXSTR;
74
        length*:    INTEGER;
75
        sym*:       INTEGER;
76
        pos*:       POSITION;
77
        ident*:     IDENT;
78
        string*:    IDENT;
79
        value*:     ARITH.VALUE;
80
        error*:     INTEGER;
7597 akron1 81
 
7693 akron1 82
        over:       BOOLEAN
7597 akron1 83
 
84
    END;
85
 
7693 akron1 86
    SCANNER* = TXT.TEXT;
7597 akron1 87
 
88
 
6613 leency 89
VAR
90
 
7696 akron1 91
    idents: AVL.NODE;
6613 leency 92
 
7696 akron1 93
    delimiters: ARRAY 256 OF BOOLEAN;
6613 leency 94
 
7696 akron1 95
    NewIdent: IDENT;
6613 leency 96
 
8097 maxcodehac 97
    upto, LowerCase, _if: BOOLEAN;
6613 leency 98
 
8097 maxcodehac 99
    def: LISTS.LIST;
7597 akron1 100
 
8097 maxcodehac 101
 
7597 akron1 102
PROCEDURE nodecmp (a, b: AVL.DATA): INTEGER;
103
    RETURN ORD(a(IDENT).s > b(IDENT).s) - ORD(a(IDENT).s < b(IDENT).s)
104
END nodecmp;
105
 
106
 
107
PROCEDURE enterid* (s: LEXSTR): IDENT;
108
VAR
109
    newnode: BOOLEAN;
110
    node:    AVL.NODE;
6613 leency 111
 
112
BEGIN
7696 akron1 113
    NewIdent.s := s;
114
    idents := AVL.insert(idents, NewIdent, nodecmp, newnode, node);
6613 leency 115
 
7597 akron1 116
    IF newnode THEN
7696 akron1 117
        NEW(NewIdent);
118
        NewIdent.offset  := -1;
119
        NewIdent.offsetW := -1;
120
        NewIdent.key := 0
7597 akron1 121
    END
6613 leency 122
 
7597 akron1 123
    RETURN node.data(IDENT)
124
END enterid;
6613 leency 125
 
7597 akron1 126
 
127
PROCEDURE putchar (VAR lex: LEX; c: CHAR);
6613 leency 128
BEGIN
7597 akron1 129
    IF lex.length < LEXLEN - 1 THEN
130
        lex.s[lex.length] := c;
131
        INC(lex.length);
132
        lex.s[lex.length] := 0X
6613 leency 133
    ELSE
7597 akron1 134
        lex.over := TRUE
6613 leency 135
    END
7597 akron1 136
END putchar;
6613 leency 137
 
7597 akron1 138
 
7693 akron1 139
PROCEDURE nextc (text: TXT.TEXT): CHAR;
140
BEGIN
141
    TXT.next(text)
142
    RETURN text.peak
143
END nextc;
144
 
145
 
146
PROCEDURE ident (text: TXT.TEXT; VAR lex: LEX);
7597 akron1 147
VAR
148
    c: CHAR;
149
 
6613 leency 150
BEGIN
7693 akron1 151
    c := text.peak;
7597 akron1 152
    ASSERT(S.letter(c));
6613 leency 153
 
7597 akron1 154
    WHILE S.letter(c) OR S.digit(c) DO
155
        putchar(lex, c);
7693 akron1 156
        c := nextc(text)
7597 akron1 157
    END;
158
 
159
    IF lex.over THEN
160
        lex.sym := lxERROR06
6613 leency 161
    ELSE
7696 akron1 162
        lex.ident := enterid(lex.s);
163
        IF lex.ident.key # 0 THEN
164
            lex.sym := lex.ident.key
165
        ELSE
166
            lex.sym := lxIDENT
167
        END
6613 leency 168
    END
169
 
7597 akron1 170
END ident;
6613 leency 171
 
172
 
7693 akron1 173
PROCEDURE number (text: TXT.TEXT; VAR lex: LEX);
7597 akron1 174
VAR
175
    c: CHAR;
176
    hex: BOOLEAN;
8097 maxcodehac 177
    error, sym: INTEGER;
6613 leency 178
 
7597 akron1 179
BEGIN
7693 akron1 180
    c := text.peak;
7597 akron1 181
    ASSERT(S.digit(c));
6613 leency 182
 
7597 akron1 183
    error := 0;
6613 leency 184
 
8097 maxcodehac 185
    sym := lxINTEGER;
7597 akron1 186
    hex := FALSE;
187
 
188
    WHILE S.digit(c) DO
189
        putchar(lex, c);
7693 akron1 190
        c := nextc(text)
6613 leency 191
    END;
7597 akron1 192
 
193
    WHILE S.hexdigit(c) DO
194
        putchar(lex, c);
7693 akron1 195
        c := nextc(text);
7597 akron1 196
        hex := TRUE
6613 leency 197
    END;
7597 akron1 198
 
199
    IF c = "H" THEN
200
        putchar(lex, c);
7693 akron1 201
        TXT.next(text);
8097 maxcodehac 202
        sym := lxHEX
7597 akron1 203
 
204
    ELSIF c = "X" THEN
205
        putchar(lex, c);
7693 akron1 206
        TXT.next(text);
8097 maxcodehac 207
        sym := lxCHAR
7597 akron1 208
 
209
    ELSIF c = "." THEN
210
 
211
        IF hex THEN
8097 maxcodehac 212
            sym := lxERROR01
6613 leency 213
        ELSE
7597 akron1 214
 
7693 akron1 215
            c := nextc(text);
7597 akron1 216
 
217
            IF c # "." THEN
218
                putchar(lex, ".");
8097 maxcodehac 219
                sym := lxFLOAT
7597 akron1 220
            ELSE
8097 maxcodehac 221
                sym := lxINTEGER;
7693 akron1 222
                text.peak := 7FX;
223
                upto := TRUE
7597 akron1 224
            END;
225
 
226
            WHILE S.digit(c) DO
227
                putchar(lex, c);
7693 akron1 228
                c := nextc(text)
7597 akron1 229
            END;
230
 
231
            IF c = "E" THEN
232
 
233
                putchar(lex, c);
7693 akron1 234
                c := nextc(text);
7597 akron1 235
                IF (c = "+") OR (c = "-") THEN
236
                    putchar(lex, c);
7693 akron1 237
                    c := nextc(text)
7597 akron1 238
                END;
239
 
240
                IF S.digit(c) THEN
241
                    WHILE S.digit(c) DO
242
                        putchar(lex, c);
7693 akron1 243
                        c := nextc(text)
7597 akron1 244
                    END
245
                ELSE
8097 maxcodehac 246
                    sym := lxERROR02
7597 akron1 247
                END
248
 
249
            END
250
 
6613 leency 251
        END
7597 akron1 252
 
7693 akron1 253
    ELSIF hex THEN
8097 maxcodehac 254
        sym := lxERROR01
7597 akron1 255
 
256
    END;
257
 
8097 maxcodehac 258
    IF lex.over & (sym >= 0) THEN
259
        sym := lxERROR07
7597 akron1 260
    END;
261
 
8097 maxcodehac 262
    IF sym = lxINTEGER THEN
7597 akron1 263
        ARITH.iconv(lex.s, lex.value, error)
8097 maxcodehac 264
    ELSIF (sym = lxHEX) OR (sym = lxCHAR) THEN
7597 akron1 265
        ARITH.hconv(lex.s, lex.value, error)
8097 maxcodehac 266
    ELSIF sym = lxFLOAT THEN
7597 akron1 267
        ARITH.fconv(lex.s, lex.value, error)
268
    END;
269
 
270
    CASE error OF
271
    |0:
8097 maxcodehac 272
    |1: sym := lxERROR08
273
    |2: sym := lxERROR09
274
    |3: sym := lxERROR10
275
    |4: sym := lxERROR11
276
    |5: sym := lxERROR12
277
    END;
6613 leency 278
 
8097 maxcodehac 279
    lex.sym := sym
7597 akron1 280
END number;
281
 
282
 
7693 akron1 283
PROCEDURE string (text: TXT.TEXT; VAR lex: LEX; quot: CHAR);
7597 akron1 284
VAR
7693 akron1 285
    c: CHAR;
286
    n: INTEGER;
7597 akron1 287
 
288
BEGIN
7693 akron1 289
    c  := nextc(text);
290
    n  := 0;
7597 akron1 291
 
292
    WHILE (c # quot) & (c # 0X) & ~text.eol & ~text.eof DO
293
        putchar(lex, c);
7693 akron1 294
        c := nextc(text);
7597 akron1 295
        INC(n)
6613 leency 296
    END;
7597 akron1 297
 
298
    IF c = quot THEN
7693 akron1 299
        TXT.next(text);
7597 akron1 300
        IF lex.over THEN
301
            lex.sym := lxERROR05
302
        ELSE
303
            IF n # 1 THEN
304
                lex.sym := lxSTRING
305
            ELSE
306
                lex.sym := lxCHAR;
7693 akron1 307
                ARITH.setChar(lex.value, ORD(lex.s[0]))
7597 akron1 308
            END
309
        END
310
    ELSE
311
        lex.sym := lxERROR03
6613 leency 312
    END;
7597 akron1 313
 
314
    IF lex.sym = lxSTRING THEN
315
        lex.string := enterid(lex.s);
316
        lex.value.typ := ARITH.tSTRING;
317
        lex.value.string := lex.string
6613 leency 318
    END
319
 
7597 akron1 320
END string;
321
 
322
 
7693 akron1 323
PROCEDURE comment (text: TXT.TEXT);
7597 akron1 324
VAR
325
    c: CHAR;
326
    cond, depth: INTEGER;
327
 
6613 leency 328
BEGIN
7693 akron1 329
    cond  := 0;
7597 akron1 330
    depth := 1;
6613 leency 331
 
7597 akron1 332
    REPEAT
333
 
7693 akron1 334
        c := text.peak;
335
        TXT.next(text);
7597 akron1 336
 
337
        IF c = "*" THEN
338
            IF cond = 1 THEN
339
                cond := 0;
340
                INC(depth)
341
            ELSE
342
               cond := 2
343
            END
344
        ELSIF c = ")" THEN
345
            IF cond = 2 THEN
346
                DEC(depth)
347
            END;
348
            cond := 0
349
        ELSIF c = "(" THEN
350
            cond := 1
351
        ELSE
352
            cond := 0
353
        END
354
 
355
    UNTIL (depth = 0) OR text.eof
356
 
357
END comment;
358
 
359
 
7693 akron1 360
PROCEDURE delimiter (text: TXT.TEXT; VAR lex: LEX; c: CHAR);
8097 maxcodehac 361
VAR
362
    sym: INTEGER;
363
 
6613 leency 364
BEGIN
7597 akron1 365
    putchar(lex, c);
7693 akron1 366
    c := nextc(text);
7597 akron1 367
 
7693 akron1 368
    CASE lex.s[0] OF
7597 akron1 369
    |"+":
8097 maxcodehac 370
        sym := lxPLUS
7597 akron1 371
 
372
    |"-":
8097 maxcodehac 373
        sym := lxMINUS
7597 akron1 374
 
375
    |"*":
8097 maxcodehac 376
        sym := lxMUL
7597 akron1 377
 
378
    |"/":
8097 maxcodehac 379
        sym := lxSLASH;
7597 akron1 380
 
7693 akron1 381
        IF c = "/" THEN
8097 maxcodehac 382
            sym := lxCOMMENT;
7597 akron1 383
            REPEAT
7693 akron1 384
                TXT.next(text)
7597 akron1 385
            UNTIL text.eol OR text.eof
386
        END
387
 
388
    |"~":
8097 maxcodehac 389
        sym := lxNOT
7597 akron1 390
 
391
    |"&":
8097 maxcodehac 392
        sym := lxAND
7597 akron1 393
 
394
    |".":
8097 maxcodehac 395
        sym := lxPOINT;
7597 akron1 396
 
7693 akron1 397
        IF c = "." THEN
8097 maxcodehac 398
            sym := lxRANGE;
7693 akron1 399
            putchar(lex, c);
400
            TXT.next(text)
6613 leency 401
        END
7597 akron1 402
 
403
    |",":
8097 maxcodehac 404
        sym := lxCOMMA
7597 akron1 405
 
406
    |";":
8097 maxcodehac 407
        sym := lxSEMI
7597 akron1 408
 
409
    |"|":
8097 maxcodehac 410
        sym := lxBAR
7597 akron1 411
 
412
    |"(":
8097 maxcodehac 413
        sym := lxLROUND;
7597 akron1 414
 
415
        IF c = "*" THEN
8097 maxcodehac 416
            sym := lxCOMMENT;
7693 akron1 417
            TXT.next(text);
7597 akron1 418
            comment(text)
419
        END
420
 
421
    |"[":
8097 maxcodehac 422
        sym := lxLSQUARE
7597 akron1 423
 
424
    |"{":
8097 maxcodehac 425
        sym := lxLCURLY
7597 akron1 426
 
427
    |"^":
8097 maxcodehac 428
        sym := lxCARET
7597 akron1 429
 
430
    |"=":
8097 maxcodehac 431
        sym := lxEQ
7597 akron1 432
 
433
    |"#":
8097 maxcodehac 434
        sym := lxNE
7597 akron1 435
 
436
    |"<":
8097 maxcodehac 437
        sym := lxLT;
7597 akron1 438
 
439
        IF c = "=" THEN
8097 maxcodehac 440
            sym := lxLE;
7597 akron1 441
            putchar(lex, c);
7693 akron1 442
            TXT.next(text)
7597 akron1 443
        END
444
 
445
    |">":
8097 maxcodehac 446
        sym := lxGT;
7597 akron1 447
 
448
        IF c = "=" THEN
8097 maxcodehac 449
            sym := lxGE;
7597 akron1 450
            putchar(lex, c);
7693 akron1 451
            TXT.next(text)
7597 akron1 452
        END
453
 
454
    |":":
8097 maxcodehac 455
        sym := lxCOLON;
7597 akron1 456
 
457
        IF c = "=" THEN
8097 maxcodehac 458
            sym := lxASSIGN;
7597 akron1 459
            putchar(lex, c);
7693 akron1 460
            TXT.next(text)
7597 akron1 461
        END
462
 
463
    |")":
8097 maxcodehac 464
        sym := lxRROUND
7597 akron1 465
 
466
    |"]":
8097 maxcodehac 467
        sym := lxRSQUARE
7597 akron1 468
 
469
    |"}":
8097 maxcodehac 470
        sym := lxRCURLY
7597 akron1 471
 
8097 maxcodehac 472
    END;
6613 leency 473
 
8097 maxcodehac 474
    lex.sym := sym
475
 
7597 akron1 476
END delimiter;
477
 
478
 
7693 akron1 479
PROCEDURE Next* (text: SCANNER; VAR lex: LEX);
7597 akron1 480
VAR
481
    c: CHAR;
482
 
8097 maxcodehac 483
 
484
    PROCEDURE check (cond: BOOLEAN; text: SCANNER; lex: LEX; errno: INTEGER);
485
    BEGIN
486
        IF ~cond THEN
487
            ERRORS.ErrorMsg(text.fname, lex.pos.line, lex.pos.col, errno)
488
        END
489
    END check;
490
 
491
 
492
    PROCEDURE IsDef (str: ARRAY OF CHAR): BOOLEAN;
493
    VAR
494
        cur: DEF;
495
 
496
    BEGIN
497
        cur := def.first(DEF);
498
        WHILE (cur # NIL) & (cur.ident # str) DO
499
            cur := cur.next(DEF)
500
        END
501
 
502
        RETURN cur # NIL
503
    END IsDef;
504
 
505
 
506
    PROCEDURE Skip (text: SCANNER);
507
    VAR
508
        i: INTEGER;
509
 
510
    BEGIN
511
        i := 0;
512
        WHILE (i <= text.ifc) & ~text._skip[i] DO
513
            INC(i)
514
        END;
515
        text.skip := i <= text.ifc
516
    END Skip;
517
 
518
 
519
    PROCEDURE prep_if (text: SCANNER; VAR lex: LEX);
520
    VAR
521
        skip: BOOLEAN;
522
 
523
    BEGIN
524
        INC(text.ifc);
525
        text._elsif[text.ifc] := lex.sym = lxELSIF;
526
        IF lex.sym = lxIF THEN
527
            INC(text.elsec);
528
            text._else[text.elsec] := FALSE
529
        END;
530
        _if := TRUE;
531
        skip := TRUE;
532
        text.skip := FALSE;
533
 
534
        Next(text, lex);
535
        check(lex.sym = lxLROUND, text, lex, 64);
536
 
537
        Next(text, lex);
538
        check(lex.sym = lxIDENT, text, lex, 22);
539
 
540
        REPEAT
541
            IF IsDef(lex.s) THEN
542
                skip := FALSE
543
            END;
544
 
545
            Next(text, lex);
546
            IF lex.sym = lxBAR THEN
547
                Next(text, lex);
548
                check(lex.sym = lxIDENT, text, lex, 22)
549
            ELSE
550
                check(lex.sym = lxRROUND, text, lex, 33)
551
            END
552
        UNTIL lex.sym = lxRROUND;
553
 
554
        _if := FALSE;
555
        text._skip[text.ifc] := skip;
556
        Skip(text);
557
        Next(text, lex)
558
    END prep_if;
559
 
560
 
561
    PROCEDURE prep_end (text: SCANNER; VAR lex: LEX);
562
    BEGIN
563
        check(text.ifc > 0, text, lex, 118);
564
        IF lex.sym = lxEND THEN
565
            WHILE text._elsif[text.ifc] DO
566
                DEC(text.ifc)
567
            END;
568
            DEC(text.ifc);
569
            DEC(text.elsec)
570
        ELSIF (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN
571
            check(~text._else[text.elsec], text, lex, 118);
572
            text._skip[text.ifc] := ~text._skip[text.ifc];
573
            text._else[text.elsec] := lex.sym = lxELSE
574
        END;
575
        Skip(text);
576
        IF lex.sym = lxELSIF THEN
577
            prep_if(text, lex)
578
        ELSE
579
            Next(text, lex)
580
        END
581
    END prep_end;
582
 
583
 
6613 leency 584
BEGIN
585
 
7597 akron1 586
    REPEAT
7693 akron1 587
        c := text.peak;
7597 akron1 588
 
589
        WHILE S.space(c) DO
7693 akron1 590
            c := nextc(text)
7597 akron1 591
        END;
592
 
593
        lex.s[0]     := 0X;
594
        lex.length   := 0;
595
        lex.pos.line := text.line;
596
        lex.pos.col  := text.col;
597
        lex.ident    := NIL;
598
        lex.over     := FALSE;
599
 
600
        IF S.letter(c) THEN
601
            ident(text, lex)
602
        ELSIF S.digit(c) THEN
7693 akron1 603
            number(text, lex)
7597 akron1 604
        ELSIF (c = '"') OR (c = "'") THEN
7693 akron1 605
            string(text, lex, c)
7696 akron1 606
        ELSIF delimiters[ORD(c)] THEN
7693 akron1 607
            delimiter(text, lex, c)
8097 maxcodehac 608
        ELSIF c = "$" THEN
609
            IF S.letter(nextc(text)) THEN
610
                ident(text, lex);
611
                IF lex.sym = lxIF THEN
612
                    IF ~_if THEN
613
                        prep_if(text, lex)
614
                    END
615
                ELSIF (lex.sym = lxEND) OR (lex.sym = lxELSE) OR (lex.sym = lxELSIF) THEN
616
                    IF ~_if THEN
617
                        prep_end(text, lex)
618
                    END
619
                ELSE
620
                    check(FALSE, text, lex, 119)
621
                END
622
            ELSE
623
                check(FALSE, text, lex, 119)
624
            END
7597 akron1 625
        ELSIF c = 0X THEN
626
            lex.sym := lxEOF;
8097 maxcodehac 627
            text.skip := FALSE;
7597 akron1 628
            IF text.eof THEN
629
                INC(lex.pos.col)
630
            END
7693 akron1 631
        ELSIF (c = 7FX) & upto THEN
632
            upto := FALSE;
633
            lex.sym := lxRANGE;
634
            putchar(lex, ".");
635
            putchar(lex, ".");
636
            DEC(lex.pos.col);
637
            TXT.next(text)
7597 akron1 638
        ELSE
639
            putchar(lex, c);
7693 akron1 640
            TXT.next(text);
7597 akron1 641
            lex.sym := lxERROR04
642
        END;
643
 
644
        IF lex.sym < 0 THEN
645
            lex.error := -lex.sym
646
        ELSE
647
            lex.error := 0
648
        END
649
 
8097 maxcodehac 650
    UNTIL (lex.sym # lxCOMMENT) & ~text.skip
7597 akron1 651
 
652
END Next;
653
 
654
 
655
PROCEDURE open* (name: ARRAY OF CHAR): SCANNER;
7693 akron1 656
    RETURN TXT.open(name)
7597 akron1 657
END open;
658
 
659
 
660
PROCEDURE close* (VAR scanner: SCANNER);
661
BEGIN
7693 akron1 662
    TXT.close(scanner)
7597 akron1 663
END close;
664
 
665
 
8097 maxcodehac 666
PROCEDURE init* (lower: BOOLEAN);
7597 akron1 667
VAR
668
    i: INTEGER;
669
    delim: ARRAY 23 OF CHAR;
670
 
7693 akron1 671
 
7696 akron1 672
    PROCEDURE enterkw (key: INTEGER; kw: LEXSTR);
673
    VAR
674
        id: IDENT;
8097 maxcodehac 675
        upper: LEXSTR;
7696 akron1 676
 
7597 akron1 677
    BEGIN
8097 maxcodehac 678
        IF LowerCase THEN
679
            id := enterid(kw);
680
            id.key := key
681
        END;
682
        upper := kw;
683
        S.UpCase(upper);
684
        id := enterid(upper);
7696 akron1 685
        id.key := key
7597 akron1 686
    END enterkw;
687
 
7693 akron1 688
 
7597 akron1 689
BEGIN
7693 akron1 690
    upto := FALSE;
8097 maxcodehac 691
    LowerCase := lower;
7597 akron1 692
 
693
    FOR i := 0 TO 255 DO
7696 akron1 694
        delimiters[i] := FALSE
6613 leency 695
    END;
7597 akron1 696
 
697
    delim := "+-*/~&.,;|([{^=#<>:)]}";
698
 
699
    FOR i := 0 TO LEN(delim) - 2 DO
7696 akron1 700
        delimiters[ORD(delim[i])] := TRUE
6613 leency 701
    END;
702
 
7696 akron1 703
    NEW(NewIdent);
704
    NewIdent.s       := "";
705
    NewIdent.offset  := -1;
706
    NewIdent.offsetW := -1;
707
    NewIdent.key     := 0;
6613 leency 708
 
7696 akron1 709
    idents := NIL;
710
 
8097 maxcodehac 711
    enterkw(lxARRAY, "array");
712
    enterkw(lxBEGIN, "begin");
713
    enterkw(lxBY, "by");
714
    enterkw(lxCASE, "case");
715
    enterkw(lxCONST, "const");
716
    enterkw(lxDIV, "div");
717
    enterkw(lxDO, "do");
718
    enterkw(lxELSE, "else");
719
    enterkw(lxELSIF, "elsif");
720
    enterkw(lxEND, "end");
721
    enterkw(lxFALSE, "false");
722
    enterkw(lxFOR, "for");
723
    enterkw(lxIF, "if");
724
    enterkw(lxIMPORT, "import");
725
    enterkw(lxIN, "in");
726
    enterkw(lxIS, "is");
727
    enterkw(lxMOD, "mod");
728
    enterkw(lxMODULE, "module");
729
    enterkw(lxNIL, "nil");
730
    enterkw(lxOF, "of");
731
    enterkw(lxOR, "or");
732
    enterkw(lxPOINTER, "pointer");
733
    enterkw(lxPROCEDURE, "procedure");
734
    enterkw(lxRECORD, "record");
735
    enterkw(lxREPEAT, "repeat");
736
    enterkw(lxRETURN, "return");
737
    enterkw(lxTHEN, "then");
738
    enterkw(lxTO, "to");
739
    enterkw(lxTRUE, "true");
740
    enterkw(lxTYPE, "type");
741
    enterkw(lxUNTIL, "until");
742
    enterkw(lxVAR, "var");
743
    enterkw(lxWHILE, "while")
7696 akron1 744
 
7597 akron1 745
END init;
6613 leency 746
 
7597 akron1 747
 
8097 maxcodehac 748
PROCEDURE NewDef* (str: ARRAY OF CHAR);
749
VAR
750
    item: DEF;
751
 
6613 leency 752
BEGIN
8097 maxcodehac 753
    NEW(item);
754
    COPY(str, item.ident);
755
    LISTS.push(def, item)
756
END NewDef;
757
 
758
 
759
BEGIN
760
    def := LISTS.create(NIL)
7983 leency 761
END SCAN.