Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6613 leency 1
(*
2
    Copyright 2016 Anton Krotov
3
 
4
    This file is part of Compiler.
5
 
6
    Compiler is free software: you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation, either version 3 of the License, or
9
    (at your option) any later version.
10
 
11
    Compiler is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with Compiler. If not, see .
18
*)
19
 
20
MODULE SCAN;
21
 
22
IMPORT UTILS, sys := SYSTEM;
23
 
24
CONST
25
 
26
  Tab = 8;
27
  maxINT* = 7FFFFFFFH;
28
  minINT* = 80000000H;
29
  maxREAL* = 3.39E38;
30
  maxDBL* = 1.69D308;
31
  minREAL* = 1.41E-45;
32
  IDLENGTH = 255;
33
  STRLENGTH* = 256;
34
 
35
  lxEOF = 0; lxINT = -1; lxREAL = -2; lxSTRING = -3; lxIDENT = -4; lxHEX = -5; lxCHX = -6; lxLONGREAL = -7;
36
  lxARRAY = 1; lxBEGIN = 2; lxBY = 3; lxCASE = 4; lxCONST = 5; lxDIV = 6; lxDO = 7; lxELSE = 8;
37
  lxELSIF = 9; lxEND = 10; lxFALSE = 11; lxFOR = 12; lxIF = 13; lxIMPORT = 14; lxIN = 15; lxIS = 16;
38
  lxMOD = 17; lxMODULE = 18; lxNIL = 19; lxOF = 20; lxOR = 21; lxPOINTER = 22; lxPROCEDURE = 23;
39
  lxRECORD = 24; lxREPEAT = 25; lxRETURN = 26; lxTHEN = 27; lxTO = 28; lxTRUE = 29; lxTYPE = 30;
40
  lxUNTIL = 31; lxVAR = 32; lxWHILE = 33;
41
 
42
  lxPlus = 51; lxMinus = 52; lxMult = 53; lxSlash = 54; lxNot = 55; lxAnd = 56; lxComma = 57; lxSemi = 58;
43
  lxStick = 59; lxLRound = 60; lxLSquare = 61; lxLCurly = 62; lxCaret = 63; lxRRound = 64; lxRSquare = 65;
44
  lxRCurly = 66; lxDot = 67; lxDbl = 68; lxAssign = 69; lxColon = 70;
45
  lxEQ = 71; lxNE = 72; lxLT = 73; lxGT = 74; lxLE = 75; lxGE = 76;
46
 
47
  lxERR0 = 100; lxERR1 = 101; lxERR2 = 102; lxERR3 = 103; lxERR4 = 104; lxERR5 = 105; lxERR6 = 106;
48
  lxERR7 = 107; lxERR8 = 108; lxERR9 = 109; lxERR10 = 110; lxERR11 = 111; lxERR20 = 120;
49
 
50
TYPE
51
 
52
  TCoord* = RECORD line*, col*: INTEGER END;
53
 
54
  NODE* = POINTER TO RECORD
55
    Left, Right: NODE;
56
    tLex: INTEGER;
57
    Name*: UTILS.STRING
58
  END;
59
 
60
  SCANNER* = POINTER TO RECORD
61
    File, ccol, cline, count, tLex, vINT: INTEGER;
62
    coord: TCoord;
63
    ch, vCHX: CHAR;
64
    Lex: UTILS.STRING;
65
    vFLT: LONGREAL;
66
    id: NODE;
67
    buf, bufpos: INTEGER;
68
    CR, UTF8: BOOLEAN
69
  END;
70
 
71
VAR
72
 
73
  Lex*: UTILS.STRING; File, ccol, cline, count*, tLex*, vINT*: INTEGER;
74
  coord*: TCoord;
75
  vFLT*: LONGREAL; id*: NODE; ch, vCHX*: CHAR;
76
  buf, bufpos: INTEGER; CR, UTF8: BOOLEAN;
77
  Nodes: ARRAY 256 OF NODE;
78
  _START*, _version*: NODE;
79
 
80
PROCEDURE AddNode*(Name: UTILS.STRING): NODE;
81
VAR cur, res: NODE;
82
 
83
  PROCEDURE NewNode(Right: BOOLEAN);
84
  BEGIN
85
    NEW(res);
86
    UTILS.MemErr(res = NIL);
87
    res.Name := Name;
88
    res.tLex := lxIDENT;
89
    res.Left := NIL;
90
    res.Right := NIL;
91
    IF Right THEN
92
      cur.Right := res
93
    ELSE
94
      cur.Left := res
95
    END
96
  END NewNode;
97
 
98
BEGIN
99
  res := NIL;
100
  cur := Nodes[ORD(Name[0])];
101
  REPEAT
102
    IF Name > cur.Name THEN
103
      IF cur.Right # NIL THEN
104
        cur := cur.Right
105
      ELSE
106
        NewNode(TRUE)
107
      END
108
    ELSIF Name < cur.Name THEN
109
      IF cur.Left # NIL THEN
110
        cur := cur.Left
111
      ELSE
112
        NewNode(FALSE)
113
      END
114
    ELSE
115
      res := cur
116
    END
117
  UNTIL res # NIL
118
  RETURN res
119
END AddNode;
120
 
121
PROCEDURE Backup*(scanner: SCANNER);
122
BEGIN
123
  scanner.File := File;
124
  scanner.ccol := ccol;
125
  scanner.cline := cline;
126
  scanner.ch := ch;
127
  scanner.Lex := Lex;
128
  scanner.count := count;
129
  scanner.coord := coord;
130
  scanner.tLex := tLex;
131
  scanner.vINT := vINT;
132
  scanner.vFLT := vFLT;
133
  scanner.vCHX := vCHX;
134
  scanner.buf := buf;
135
  scanner.bufpos := bufpos;
136
  scanner.CR := CR;
137
  scanner.UTF8 := UTF8
138
END Backup;
139
 
140
PROCEDURE Recover*(scanner: SCANNER);
141
BEGIN
142
  File := scanner.File;
143
  ccol := scanner.ccol;
144
  cline := scanner.cline;
145
  ch := scanner.ch;
146
  Lex := scanner.Lex;
147
  count := scanner.count;
148
  coord := scanner.coord;
149
  tLex := scanner.tLex;
150
  vINT := scanner.vINT;
151
  vFLT := scanner.vFLT;
152
  vCHX := scanner.vCHX;
153
  buf := scanner.buf;
154
  bufpos := scanner.bufpos;
155
  CR := scanner.CR;
156
  UTF8 := scanner.UTF8
157
END Recover;
158
 
159
PROCEDURE Next;
160
VAR cr: BOOLEAN;
161
BEGIN
162
  cr := FALSE;
163
  sys.GET(bufpos, ch);
164
  INC(ccol);
165
  CASE ch OF
166
  |0AX: IF ~CR THEN INC(cline) END; ccol := 0
167
  |0DX: INC(cline); ccol := 0; cr := TRUE
168
  |09X: DEC(ccol); ccol := (ccol DIV Tab) * Tab + Tab
169
  |80X..0BFX: IF UTF8 THEN DEC(ccol) END
170
  ELSE
171
  END;
172
  CR := cr;
173
  INC(bufpos)
174
END Next;
175
 
176
PROCEDURE Open*(FName: ARRAY OF CHAR; VAR FHandle: INTEGER): BOOLEAN;
177
VAR n, size: INTEGER; c: CHAR;
178
BEGIN
179
  File := UTILS.OpenF(FName);
180
  FHandle := File;
181
  IF File # 0 THEN
182
    CR := FALSE;
183
    UTF8 := FALSE;
184
    ccol := 0;
185
    cline := 1;
186
    ch := 0X;
187
    size := UTILS.FileSize(File);
188
    buf := UTILS.GetMem(size + 1024);
189
    UTILS.MemErr(buf = 0);
190
    sys.PUT(buf + size, 0X);
191
    n := UTILS.Read(File, buf, size);
192
    UTILS.CloseF(File);
193
    bufpos := buf;
194
    sys.GET(buf, c);
195
    IF c = 0EFX THEN
196
      sys.GET(buf + 1, c);
197
      IF c = 0BBX THEN
198
        sys.GET(buf + 2, c);
199
        IF c = 0BFX THEN
200
          INC(bufpos, 3);
201
          UTF8 := TRUE
202
        END
203
      END
204
    END;
205
    Next
206
  END
207
  RETURN (File # 0) & (n = size)
208
END Open;
209
 
210
PROCEDURE Space(ch: CHAR): BOOLEAN;
211
  RETURN (ch <= 20X) & (ch > 0X)
212
END Space;
213
 
214
PROCEDURE Letter(ch: CHAR): BOOLEAN;
215
  RETURN (ch >= "A") & (ch <= "Z") OR (ch >= "a") & (ch <= "z") OR (ch = "_")
216
END Letter;
217
 
218
PROCEDURE Digit*(ch: CHAR): BOOLEAN;
219
  RETURN (ch >= "0") & (ch <= "9")
220
END Digit;
221
 
222
PROCEDURE HexDigit*(ch: CHAR): BOOLEAN;
223
  RETURN (ch >= "A") & (ch <= "F") OR (ch >= "0") & (ch <= "9")
224
END HexDigit;
225
 
226
PROCEDURE PutChar(ch: CHAR);
227
BEGIN
228
  Lex[count] := ch;
229
  IF ch # 0X THEN
230
    INC(count)
231
  END
232
END PutChar;
233
 
234
PROCEDURE PutNext(ch: CHAR);
235
BEGIN
236
  PutChar(ch);
237
  Next
238
END PutNext;
239
 
240
PROCEDURE Ident;
241
BEGIN
242
  tLex := lxIDENT;
243
  WHILE Letter(ch) OR Digit(ch) DO
244
    PutNext(ch)
245
  END;
246
  PutChar(0X);
247
  IF count > IDLENGTH THEN
248
    tLex := lxERR10
249
  END
250
END Ident;
251
 
252
PROCEDURE hex*(ch: CHAR): INTEGER;
253
VAR Res: INTEGER;
254
BEGIN
255
  Res := ORD(ch);
256
  CASE ch OF
257
  |"0".."9": DEC(Res, ORD("0"))
258
  |"A".."F": DEC(Res, ORD("A") - 10)
259
  ELSE
260
  END
261
  RETURN Res
262
END hex;
263
 
264
PROCEDURE StrToInt16(str: UTILS.STRING): INTEGER;
265
VAR i, res, n: INTEGER; flag: BOOLEAN;
266
BEGIN
267
  res := 0;
268
  i := 0;
269
  n := 0;
270
  WHILE str[i] = "0" DO
271
    INC(i)
272
  END;
273
  flag := TRUE;
274
  WHILE flag & (str[i] # "X") & (str[i] # "H") DO
275
    INC(n);
276
    IF n > 8 THEN
277
      tLex := lxERR5;
278
      flag := FALSE
279
    ELSE
280
      res := LSL(res, 4) + hex(str[i]);
281
      INC(i)
282
    END
283
  END
284
  RETURN res
285
END StrToInt16;
286
 
287
PROCEDURE StrToChx(str: UTILS.STRING): CHAR;
288
VAR res: INTEGER;
289
BEGIN
290
  res := StrToInt16(str);
291
  IF (res < 0) OR (res > 0FFH) THEN
292
    tLex := lxERR6;
293
    res := 0
294
  END
295
  RETURN CHR(res)
296
END StrToChx;
297
 
298
PROCEDURE StrToInt*(str: UTILS.STRING): INTEGER;
299
VAR i, res: INTEGER; flag: BOOLEAN;
300
BEGIN
301
  res := 0;
302
  i := 0;
303
  flag := TRUE;
304
  WHILE flag & (str[i] # 0X) DO
305
    IF res > maxINT DIV 10 THEN
306
      tLex := lxERR5;
307
      flag := FALSE;
308
      res := 0
309
    ELSE
310
      res := res * 10;
311
      IF res > maxINT - (ORD(str[i]) - ORD("0")) THEN
312
        tLex := lxERR5;
313
        flag := FALSE;
314
        res := 0
315
      ELSE
316
        res := res + (ORD(str[i]) - ORD("0"));
317
        INC(i)
318
      END
319
    END
320
  END
321
  RETURN res
322
END StrToInt;
323
 
324
PROCEDURE StrToFloat(str: UTILS.STRING): LONGREAL;
325
VAR i, scale: INTEGER; res, m, d: LONGREAL; minus, nez: BOOLEAN;
326
 
327
  PROCEDURE Error(e: INTEGER; VAR cont: BOOLEAN);
328
  BEGIN
329
    tLex := e;
330
    res := 0.0D0;
331
    cont := FALSE
332
  END Error;
333
 
334
  PROCEDURE Inf(VAR cont: BOOLEAN; VAR i: INTEGER);
335
  BEGIN
336
    IF UTILS.IsInf(res) THEN
337
      Error(lxERR7, cont)
338
    END;
339
    INC(i)
340
  END Inf;
341
 
342
  PROCEDURE part1(): BOOLEAN;
343
  VAR cont: BOOLEAN;
344
  BEGIN
345
    res := 0.0D0;
346
    i := 0;
347
    d := 1.0D0;
348
    nez := FALSE;
349
    cont := TRUE;
350
    WHILE cont & Digit(str[i]) DO
351
      nez := nez OR (str[i] # "0");
352
      res := res * 10.0D0 + LONG(FLT(ORD(str[i]) - ORD("0")));
353
      Inf(cont, i)
354
    END
355
    RETURN cont
356
  END part1;
357
 
358
  PROCEDURE part2(): BOOLEAN;
359
  VAR cont: BOOLEAN;
360
  BEGIN
361
    INC(i);
362
    cont := TRUE;
363
    WHILE cont & Digit(str[i]) DO
364
      nez := nez OR (str[i] # "0");
365
      d := d / 10.0D0;
366
      res := res + LONG(FLT(ORD(str[i]) - ORD("0"))) * d;
367
      Inf(cont, i)
368
    END
369
    RETURN cont
370
  END part2;
371
 
372
  PROCEDURE part3(): BOOLEAN;
373
  VAR cont: BOOLEAN;
374
  BEGIN
375
    cont := TRUE;
376
    IF str[i] = 0X THEN
377
      IF res > LONG(maxREAL) THEN
378
        Error(lxERR7, cont)
379
      ELSIF nez & ((res = 0.0D0) OR (res < LONG(minREAL)) & (tLex = lxREAL)) THEN
380
        Error(lxERR9, cont)
381
      END
382
    END
383
    RETURN cont
384
  END part3;
385
 
386
  PROCEDURE part4(): BOOLEAN;
387
  VAR cont: BOOLEAN;
388
  BEGIN
389
    IF str[i] = "D" THEN
390
      tLex := lxLONGREAL
391
    END;
392
    INC(i);
393
    m := 10.0D0;
394
    minus := FALSE;
395
    IF str[i] = "+" THEN
396
      INC(i)
397
    ELSIF str[i] = "-" THEN
398
      minus := TRUE;
399
      INC(i);
400
      m := 0.1D0
401
    END;
402
    scale := 0;
403
    cont := TRUE;
404
    WHILE cont & Digit(str[i]) DO
405
      IF scale > maxINT DIV 10 THEN
406
        Error(lxERR8, cont)
407
      ELSE
408
        scale := scale * 10;
409
        IF scale > maxINT - (ORD(str[i]) - ORD("0")) THEN
410
          Error(lxERR8, cont)
411
        ELSE
412
          scale := scale + (ORD(str[i]) - ORD("0"));
413
          INC(i)
414
        END
415
      END
416
    END
417
    RETURN cont
418
  END part4;
419
 
420
  PROCEDURE part5(): BOOLEAN;
421
  VAR cont: BOOLEAN; i: INTEGER;
422
  BEGIN
423
    cont := TRUE;
424
    IF scale = maxINT THEN
425
      Error(lxERR8, cont)
426
    END;
427
    i := 1;
428
    WHILE cont & (i <= scale) DO
429
      res := res * m;
430
      Inf(cont, i)
431
    END;
432
    IF cont & (nez & (res = 0.0D0) OR (res > 0.0D0) & (res < LONG(minREAL)) & (tLex = lxREAL)) THEN
433
      Error(lxERR9, cont)
434
    ELSIF cont & (tLex = lxREAL) & (res > LONG(maxREAL)) THEN
435
      Error(lxERR7, cont)
436
    END
437
    RETURN cont
438
  END part5;
439
 
440
BEGIN
441
  IF part1() & part2() & part3() & part4() & part5() THEN END
442
  RETURN res
443
END StrToFloat;
444
 
445
PROCEDURE Number;
446
VAR nextchr: CHAR;
447
BEGIN
448
  tLex := lxINT;
449
  WHILE Digit(ch) DO
450
    PutNext(ch)
451
  END;
452
  IF ch = "H" THEN
453
    tLex := lxHEX
454
  ELSIF ch = "X" THEN
455
    tLex := lxCHX
456
  END;
457
  IF tLex # lxINT THEN
458
    PutNext(ch)
459
  ELSE
460
    WHILE HexDigit(ch) DO
461
      tLex := lxHEX;
462
      PutNext(ch)
463
    END;
464
    IF tLex = lxHEX THEN
465
      IF ch = "H" THEN
466
        PutNext(ch)
467
      ELSIF ch = "X" THEN
468
        tLex := lxCHX;
469
        PutNext(ch)
470
      ELSE
471
        tLex := lxERR1
472
      END
473
    ELSIF ch = "." THEN
474
      sys.GET(bufpos, nextchr);
475
      IF nextchr # "." THEN
476
        tLex := lxREAL;
477
        PutNext(ch);
478
        WHILE Digit(ch) DO
479
          PutNext(ch)
480
        END;
481
        IF (ch = "E") OR (ch = "D") THEN
482
          PutNext(ch);
483
          IF (ch = "+") OR (ch = "-") THEN
484
            PutNext(ch)
485
          END;
486
          IF ~Digit(ch) THEN
487
            tLex := lxERR2
488
          ELSE
489
            WHILE Digit(ch) DO
490
              PutNext(ch)
491
            END
492
          END
493
        END
494
      END
495
    END
496
  END;
497
  PutChar(0X)
498
END Number;
499
 
500
PROCEDURE Delim(ch: CHAR): INTEGER;
501
VAR Res: INTEGER;
502
BEGIN
503
  CASE ch OF
504
  |"+": Res := lxPlus
505
  |"-": Res := lxMinus
506
  |"*": Res := lxMult
507
  |"/": Res := lxSlash
508
  |"~": Res := lxNot
509
  |"&": Res := lxAnd
510
  |",": Res := lxComma
511
  |";": Res := lxSemi
512
  |"|": Res := lxStick
513
  |"[": Res := lxLSquare
514
  |"{": Res := lxLCurly
515
  |"^": Res := lxCaret
516
  |"=": Res := lxEQ
517
  |"#": Res := lxNE
518
  |")": Res := lxRRound
519
  |"]": Res := lxRSquare
520
  |"}": Res := lxRCurly
521
  |">": Res := lxGT
522
  |"<": Res := lxLT
523
  |":": Res := lxColon
524
  ELSE
525
  END
526
  RETURN Res
527
END Delim;
528
 
529
PROCEDURE Comment;
530
VAR c, level: INTEGER; cont: BOOLEAN;
531
BEGIN
532
  c := 1;
533
  level := 1;
534
  cont := TRUE;
535
  WHILE cont & (level > 0) DO
536
    Next;
537
    CASE ch OF
538
    |"(": c := 2
539
    |")": IF c = 3 THEN DEC(level) END; c := 1
540
    |"*": IF c = 2 THEN INC(level); c := 1 ELSE c := 3 END
541
    |0X : cont := FALSE
542
    ELSE
543
          c := 1
544
    END;
545
  END;
546
  IF cont THEN
547
    Next
548
  END
549
END Comment;
550
 
551
PROCEDURE GetLex*;
552
BEGIN
553
  WHILE Space(ch) DO
554
    Next
555
  END;
556
  coord.col := ccol;
557
  coord.line := cline;
558
  count := 0;
559
  CASE ch OF
560
  |"A".."Z", "a".."z", "_":
561
    Ident;
562
    id := AddNode(Lex);
563
    tLex := id.tLex;
564
  |"0".."9":
565
    Number;
566
    CASE tLex OF
567
    |lxINT:  vINT := StrToInt(Lex)
568
    |lxHEX:  vINT := StrToInt16(Lex)
569
    |lxCHX:  vCHX := StrToChx(Lex)
570
    |lxREAL: vFLT := StrToFloat(Lex)
571
    ELSE
572
    END
573
  |22X:
574
    tLex := lxSTRING;
575
    Next;
576
    WHILE (ch # 22X) & (ch >= 20X) DO
577
      PutNext(ch)
578
    END;
579
    IF ch = 22X THEN
580
      Next
581
    ELSE
582
      tLex := lxERR3
583
    END;
584
    PutChar(0X);
585
    INC(count);
586
    IF count > STRLENGTH THEN
587
      tLex := lxERR11
588
    END
589
  |"/":
590
    tLex := Delim(ch);
591
    PutNext(ch);
592
    IF ch = "/" THEN
593
      WHILE (ch >= 20X) OR (ch = 9X) DO
594
        PutNext(ch)
595
      END;
596
      GetLex
597
    END;
598
    PutChar(0X)
599
  |">", "<", ":":
600
    tLex := Delim(ch);
601
    PutNext(ch);
602
    IF ch = "=" THEN
603
      CASE tLex OF
604
      |lxLT:    tLex := lxLE
605
      |lxGT:    tLex := lxGE
606
      |lxColon: tLex := lxAssign
607
      ELSE
608
      END;
609
      PutNext(ch)
610
    END;
611
    PutChar(0X)
612
  |".":
613
    tLex := lxDot;
614
    PutNext(ch);
615
    IF ch = "." THEN
616
      tLex := lxDbl;
617
      PutNext(ch)
618
    END;
619
    PutChar(0X)
620
  |"(":
621
    tLex := lxLRound;
622
    PutNext(ch);
623
    IF ch = "*" THEN
624
      Comment;
625
      GetLex
626
    END;
627
    PutChar(0X)
628
  |"+", "-", "*", "~", "&", ",", ";", "|",
629
   "[", "{", "^", "=", "#", ")", "]", "}":
630
    tLex := Delim(ch);
631
    PutChar(ch);
632
    PutNext(0X)
633
  |0X:
634
    tLex := lxEOF;
635
    PutChar(0X)
636
  ELSE
637
    tLex := lxERR4
638
  END
639
END GetLex;
640
 
641
PROCEDURE AddNodeKey(Name: UTILS.STRING; key: INTEGER);
642
VAR node: NODE;
643
BEGIN
644
  node := AddNode(Name);
645
  node.tLex := key
646
END AddNodeKey;
647
 
648
PROCEDURE Init;
649
VAR i: INTEGER; node: NODE;
650
BEGIN
651
  FOR i := 0 TO LEN(Nodes) - 1 DO
652
    NEW(node);
653
    UTILS.MemErr(node = NIL);
654
    sys.PUT(sys.ADR(node.Name), i);
655
    node.Left := NIL;
656
    node.Right := NIL;
657
    node.tLex := lxIDENT;
658
    Nodes[i] := node
659
  END;
660
  _START := AddNode("lib_init");
661
  _version := AddNode("version");
662
  AddNodeKey("MOD", lxMOD);
663
  AddNodeKey("ELSE", lxELSE);
664
  AddNodeKey("RETURN", lxRETURN);
665
  AddNodeKey("CASE", lxCASE);
666
  AddNodeKey("IF", lxIF);
667
  AddNodeKey("POINTER", lxPOINTER);
668
  AddNodeKey("TYPE", lxTYPE);
669
  AddNodeKey("BEGIN", lxBEGIN);
670
  AddNodeKey("DIV", lxDIV);
671
  AddNodeKey("FALSE", lxFALSE);
672
  AddNodeKey("IN", lxIN);
673
  AddNodeKey("NIL", lxNIL);
674
  AddNodeKey("RECORD", lxRECORD);
675
  AddNodeKey("TO", lxTO);
676
  AddNodeKey("VAR", lxVAR);
677
  AddNodeKey("ARRAY", lxARRAY);
678
  AddNodeKey("DO", lxDO);
679
  AddNodeKey("END", lxEND);
680
  AddNodeKey("IS", lxIS);
681
  AddNodeKey("OF", lxOF);
682
  AddNodeKey("PROCEDURE", lxPROCEDURE);
683
  AddNodeKey("THEN", lxTHEN);
684
  AddNodeKey("WHILE", lxWHILE);
685
  AddNodeKey("BY", lxBY);
686
  AddNodeKey("CONST", lxCONST);
687
  AddNodeKey("ELSIF", lxELSIF);
688
  AddNodeKey("IMPORT", lxIMPORT);
689
  AddNodeKey("MODULE", lxMODULE);
690
  AddNodeKey("OR", lxOR);
691
  AddNodeKey("REPEAT", lxREPEAT);
692
  AddNodeKey("TRUE", lxTRUE);
693
  AddNodeKey("UNTIL", lxUNTIL);
694
  AddNodeKey("FOR", lxFOR)
695
END Init;
696
 
697
BEGIN
698
  Init
699
END SCAN.