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