Subversion Repositories Kolibri OS

Rev

Rev 6613 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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