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.>>=>=>": |