Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
8728 leency 1
(*
9659 akron1 2
    Copyright 2021, 2022 Anton Krotov
8728 leency 3
 
4
    This file is part of CEdit.
5
 
6
    CEdit 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
    CEdit 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 CEdit. If not, see .
18
*)
19
 
20
MODULE Languages;
21
 
9210 akron1 22
IMPORT Lines, Utils;
8728 leency 23
 
24
 
25
CONST
26
 
9190 akron1 27
    langText* = 0; langC* = 1; langOberon* = 2; langPascal* = 3;
9174 akron1 28
    langFasm* = 4; langLua* = 5; langIni* = 6; langJSON* = 7;
8728 leency 29
 
9174 akron1 30
    csLang = {langC, langOberon, langLua, langIni, langJSON};
9413 akron1 31
    escLang* = {langC, langLua, langJSON};
9050 leency 32
 
8728 leency 33
TYPE
34
 
35
    tLine = Lines.tLine;
36
 
37
    tKeyWords = RECORD
38
        words: ARRAY 200, 32 OF WCHAR; cnt: INTEGER
39
    END;
40
 
9193 akron1 41
    tDelimiters = ARRAY 256 OF BOOLEAN;
42
 
8728 leency 43
    procGetStr = PROCEDURE (secName, keyName: ARRAY OF CHAR; VAR s: ARRAY OF CHAR);
44
 
45
 
46
VAR
47
 
9193 akron1 48
	KW: ARRAY 8 OF ARRAY 3 OF tKeyWords;
49
	Delim: ARRAY 8 OF tDelimiters;
8728 leency 50
 
9193 akron1 51
    currentLang: INTEGER;
8728 leency 52
 
9210 akron1 53
    fileExt: ARRAY 11 OF RECORD ext: ARRAY 8 OF CHAR; lang: INTEGER END;
9193 akron1 54
 
9210 akron1 55
 
9050 leency 56
PROCEDURE isCS* (lang: INTEGER): BOOLEAN;
57
    RETURN lang IN csLang
58
END isCS;
59
 
60
 
8728 leency 61
PROCEDURE checkKW (s: ARRAY OF WCHAR; KW: tKeyWords): BOOLEAN;
62
VAR
63
    i: INTEGER;
64
BEGIN
65
    i := KW.cnt - 1;
66
    WHILE (i >= 0) & (s # KW.words[i]) DO
67
        DEC(i)
68
    END
69
    RETURN i >= 0
70
END checkKW;
71
 
72
 
73
PROCEDURE isKey* (s: ARRAY OF WCHAR; lang, kwSet: INTEGER): BOOLEAN;
9193 akron1 74
    RETURN checkKW(s, KW[lang][kwSet - 1])
75
END isKey;
76
 
77
 
78
PROCEDURE isDelim* (c: WCHAR): BOOLEAN;
8728 leency 79
VAR
9193 akron1 80
	res: BOOLEAN;
8728 leency 81
BEGIN
9193 akron1 82
	IF c <= 0FFX THEN
83
		res := Delim[currentLang][ORD(c)]
84
	ELSE
85
		res := FALSE
86
	END
87
	RETURN res
88
END isDelim;
8728 leency 89
 
90
 
9413 akron1 91
PROCEDURE SkipString* (line: tLine; VAR pos: INTEGER; n: INTEGER; lang: INTEGER);
8728 leency 92
VAR
9413 akron1 93
    quot, cur, prev: WCHAR;
8728 leency 94
BEGIN
95
    quot := Lines.getChar(line, pos);
9413 akron1 96
    cur := quot;
97
    prev := 0X;
98
    INC(pos);
99
    WHILE pos <= n DO
100
    	IF lang IN escLang THEN
101
    		prev := cur
102
    	END;
103
    	cur := Lines.getChar(line, pos);
104
    	IF (cur = "\") & (prev = "\") THEN
105
    		cur := 0X
106
    	ELSIF (cur = quot) & (prev # "\") THEN
107
    		n := 0; (* exit *)
108
    		DEC(pos)
109
    	END;
110
    	INC(pos)
111
    END
8728 leency 112
END SkipString;
113
 
114
 
9413 akron1 115
PROCEDURE SkipEsc* (line: tLine; VAR pos: INTEGER; n: INTEGER; lang: INTEGER);
116
VAR
117
	c, c1: WCHAR;
118
	k: INTEGER;
119
BEGIN
120
	IF pos < n THEN
121
		c := Lines.getChar(line, pos + 1);
122
		CASE lang OF
123
		|langC:
124
			IF Utils.inString(c, "abfnrtv\'?" + '"') THEN
125
				INC(pos)
126
			ELSIF Utils.isOct(c) THEN
127
				k := 0;
128
				REPEAT
129
					INC(pos);
130
					IF Utils.isOct(Lines.getChar(line, pos)) THEN
131
						INC(k)
132
					ELSE
133
						k := 0
134
					END
135
				UNTIL (k = 0) OR (k = 4);
136
				DEC(pos)
137
			ELSIF (c = "x") OR (c = "u") OR (c = "U") THEN
138
				c1 := c;
139
				k := 0;
140
				INC(pos);
141
				REPEAT
142
					INC(pos);
143
					c := Lines.getChar(line, pos);
144
					IF Utils.cap(c) THEN END;
145
					IF Utils.isHex(c) THEN
146
						INC(k)
147
					ELSE
148
						k := 0
149
					END;
150
					IF (c1 = "u") & (k = 5) OR (c1 = "U") & (k = 9) THEN
151
						k := 0
152
					END
153
				UNTIL k = 0;
154
				DEC(pos)
155
			END
156
		|langLua:
157
			IF Utils.inString(c, "abfnrtv\'[]" + '"') THEN
158
				INC(pos)
159
			END
160
		|langJSON:
161
			IF Utils.inString(c, 'bfnrt\/"') THEN
162
				INC(pos)
163
			ELSIF c = "u" THEN
164
				k := 0;
165
				INC(pos);
166
				REPEAT
167
					INC(pos);
168
					c := Lines.getChar(line, pos);
169
					IF Utils.cap(c) THEN END;
170
					IF Utils.isHex(c) THEN
171
						INC(k)
172
					ELSE
173
						k := 0
174
					END
175
				UNTIL (k = 0) OR (k = 5);
176
				DEC(pos)
177
			END
178
		END
179
	END
180
END SkipEsc;
181
 
182
 
8728 leency 183
PROCEDURE C (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
184
VAR
185
    c: WCHAR;
186
BEGIN
187
    c := Lines.getChar(line, pos);
188
    IF depth = 0 THEN
189
        IF c = "/" THEN
190
            IF cond = 0 THEN
191
                cond := 1
192
            ELSE
193
                cond := 0;
194
                pos := n
195
            END
196
        ELSIF (c = "*") & (cond = 1) THEN
197
            depth := 1;
198
            cond := 0
199
        ELSIF (c = "'") OR (c = '"') THEN
9413 akron1 200
            SkipString(line, pos, n, langC);
8728 leency 201
            cond := 0
202
        ELSE
203
            cond := 0
204
        END
205
    ELSIF depth = 1 THEN
206
        IF c = "*" THEN
207
            cond := 1
208
        ELSIF (c = "/") & (cond = 1) THEN
209
            cond := 0;
210
            depth := 0
211
        ELSE
212
            cond := 0
213
        END
214
    END
215
END C;
216
 
217
 
218
PROCEDURE LuaLong* (line: tLine; pos: INTEGER): INTEGER;
219
VAR
220
    res: INTEGER;
221
BEGIN
222
    res := -1;
9659 akron1 223
    IF Lines.getChar(line, pos) = "[" THEN
8728 leency 224
        INC(pos);
9659 akron1 225
        WHILE Lines.getChar(line, pos) = "=" DO
8728 leency 226
            INC(res);
227
            INC(pos)
228
        END;
9659 akron1 229
        IF Lines.getChar(line, pos) = "[" THEN
8728 leency 230
            INC(res)
231
        ELSE
232
            res := -1
233
        END
234
    END
235
    RETURN res
236
END LuaLong;
237
 
238
 
239
PROCEDURE Lua (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
240
VAR
241
    c: WCHAR;
242
    k: INTEGER;
243
BEGIN
244
    c := Lines.getChar(line, pos);
245
    IF depth = 0 THEN
246
        IF c = "-" THEN
247
            IF cond = 0 THEN
248
                cond := 1
249
            ELSE
250
                cond := 0;
251
                k := LuaLong(line, pos + 1);
252
                IF k >= 0 THEN
253
                    depth := k*2 + 1
254
                ELSE
255
                    pos := n
256
                END
257
            END
258
        ELSIF c = "[" THEN
259
            cond := 0;
260
            k := LuaLong(line, pos);
261
            IF k >= 0 THEN
262
                depth := (k + 1)*2
263
            END
264
        ELSIF (c = "'") OR (c = '"') THEN
9413 akron1 265
            SkipString(line, pos, n, langLua);
8728 leency 266
            cond := 0
267
        ELSE
268
            cond := 0
269
        END
270
    ELSIF depth > 0 THEN
271
        IF (cond = 0) & (c = "]") THEN
272
            cond := 1
273
        ELSIF (cond >= 1) & (c = "=") THEN
274
            INC(cond)
275
        ELSIF (cond >= 1) & (c = "]") & (cond*2 - depth MOD 2 = depth) THEN
276
            depth := 0;
277
            cond := 0
278
        ELSE
279
            cond := 0
280
        END
281
    END
282
END Lua;
283
 
284
 
285
PROCEDURE Pascal (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
286
VAR
287
    c: WCHAR;
288
BEGIN
289
    c := Lines.getChar(line, pos);
290
    IF depth = 0 THEN
291
        IF c = "(" THEN
292
            cond := 1
293
        ELSIF c = "/" THEN
294
            IF cond = 2 THEN
295
                cond := 0;
296
                pos := n
297
            ELSE
298
                cond := 2
299
            END
300
        ELSIF (c = "*") & (cond = 1) THEN
301
            depth := 2;
302
            cond := 0
303
        ELSIF c = "'" THEN
9413 akron1 304
            SkipString(line, pos, n, langPascal);
8728 leency 305
            cond := 0
306
        ELSIF c = "{" THEN
307
            IF Lines.getChar(line, pos + 1) = "$" THEN
308
                depth := 3
309
            ELSE
310
                depth := 1
311
            END;
312
            cond := 0
313
        ELSE
314
            cond := 0
315
        END
316
    ELSIF depth IN {1, 3} THEN
317
        IF c = "}" THEN
318
            depth := 0
319
        END
320
    ELSIF depth = 2 THEN
321
        IF c = "*" THEN
322
            cond := 1
323
        ELSIF (c = ")") & (cond = 1) THEN
324
            depth := 0;
325
            cond := 0
326
        ELSE
327
            cond := 0
328
        END
329
    END
330
END Pascal;
331
 
332
 
333
PROCEDURE Oberon (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
334
VAR
335
    c: WCHAR;
336
BEGIN
337
    c := Lines.getChar(line, pos);
338
    IF (depth = 0) & (c = "/") THEN
339
        IF cond = 3 THEN
340
            cond := 0;
341
            pos := n
342
        ELSE
343
            cond := 3
344
        END
345
    ELSIF (depth = 0) & ((c = "'") OR (c = '"')) THEN
9413 akron1 346
        SkipString(line, pos, n, langOberon);
8728 leency 347
        cond := 0
348
    ELSIF c = "(" THEN
349
        cond := 1
350
    ELSIF c = "*" THEN
351
        IF cond = 1 THEN
352
            INC(depth);
353
            cond := 0
354
        ELSE
355
            cond := 2
356
        END
357
    ELSIF c = ")" THEN
358
        IF cond = 2 THEN
359
            IF depth > 0 THEN
360
                DEC(depth)
361
            END
362
        END;
363
        cond := 0
364
    ELSE
365
        cond := 0
366
    END;
367
END Oberon;
368
 
369
 
370
PROCEDURE Ini (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
371
VAR
372
    c: WCHAR;
373
BEGIN
374
    cond := 0;
375
    c := Lines.getChar(line, pos);
376
    IF depth = 0 THEN
377
        IF c = ";" THEN
378
            pos := n
379
        ELSIF c = '"' THEN
9413 akron1 380
            SkipString(line, pos, n, langIni)
8728 leency 381
        ELSIF c = "[" THEN
382
            depth := 1
383
        END
384
    ELSIF depth = 1 THEN
385
        IF c = "]" THEN
386
            depth := 0
387
        END
388
    END
389
END Ini;
390
 
391
 
392
PROCEDURE comments* (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER; lang: INTEGER);
393
BEGIN
394
    CASE lang OF
9190 akron1 395
    |langText:
8728 leency 396
    |langFasm:
9174 akron1 397
    |langC,
398
     langJSON:    C(line, depth, cond, pos, n)
8728 leency 399
    |langOberon:  Oberon(line, depth, cond, pos, n)
400
    |langPascal:  Pascal(line, depth, cond, pos, n)
401
    |langLua:     Lua(line, depth, cond, pos, n)
402
    |langIni:     Ini(line, depth, cond, pos, n)
403
    END
404
END comments;
405
 
406
 
8762 leency 407
PROCEDURE EnterKW (s: ARRAY OF CHAR; VAR KW: tKeyWords; CPrep: BOOLEAN);
8728 leency 408
CONST
409
    SPACE = 20X; CR = 0DX; LF = 0AX; TAB = 9X; COMMA = ",";
410
VAR
411
    i, j, k: INTEGER;
412
 
413
    PROCEDURE delim (c: CHAR): BOOLEAN;
414
        RETURN (c = COMMA) OR (c = SPACE) OR (c = CR) OR (c = LF) OR (c = TAB)
415
    END delim;
416
 
417
BEGIN
418
    k := KW.cnt;
419
    i := 0;
420
    REPEAT
8762 leency 421
        KW.words[k, 0] := "#";
422
        j := ORD(CPrep);
8728 leency 423
        WHILE (s[i] # 0X) & ~delim(s[i]) DO
424
            KW.words[k, j] := WCHR(ORD(s[i]));
425
            INC(i);
426
            INC(j)
427
        END;
428
        KW.words[k, j] := 0X;
429
        INC(k);
430
        WHILE delim(s[i]) DO
431
            INC(i)
432
        END
433
    UNTIL s[i] = 0X;
434
    KW.cnt := k
435
END EnterKW;
436
 
437
 
9193 akron1 438
PROCEDURE loadKW (VAR KW: ARRAY OF tKeyWords; VAR delim: tDelimiters; getStr: procGetStr; lang: ARRAY OF CHAR);
8728 leency 439
VAR
440
    s: ARRAY 16*1024 OF CHAR;
441
    key: ARRAY 4 OF CHAR;
442
    i: INTEGER;
443
BEGIN
9193 akron1 444
	FOR i := 0 TO LEN(delim) - 1 DO
445
		delim[i] := FALSE
446
	END;
447
	getStr(lang, "delim", s);
448
	i := 0;
449
	WHILE s[i] # 0X DO
450
		delim[ORD(s[i])] := TRUE;
451
		INC(i)
452
	END;
8728 leency 453
    key := "KW1";
454
    FOR i := 0 TO 2 DO
455
        KW[i].cnt := 0;
456
        key[2] := CHR(ORD("1") + i);
457
        getStr(lang, key, s);
8762 leency 458
        EnterKW(s, KW[i], (lang = "lang_C") & (i = 1))
459
    END
8728 leency 460
END loadKW;
461
 
462
 
9193 akron1 463
PROCEDURE setCurLang* (lang: INTEGER);
464
BEGIN
465
	currentLang := lang
466
END setCurLang;
467
 
468
 
9210 akron1 469
PROCEDURE getLang* (ext: ARRAY OF CHAR): INTEGER;
470
VAR
471
	i: INTEGER;
472
BEGIN
473
	i := 0;
474
	WHILE (i < LEN(fileExt)) & (fileExt[i].ext # ext) DO
475
		INC(i)
476
	END;
477
	IF i < LEN(fileExt) THEN
478
		i := fileExt[i].lang
479
	ELSE
480
		i := langText
481
	END
482
	RETURN i
483
END getLang;
484
 
485
 
486
PROCEDURE getExt* (lang: INTEGER; VAR ext: ARRAY OF CHAR);
487
VAR
488
	i: INTEGER;
489
BEGIN
490
	i := 0;
491
	WHILE fileExt[i].lang # lang DO
492
		INC(i)
493
	END;
494
	COPY(fileExt[i].ext, ext);
495
	Utils.lowcase(ext)
496
END getExt;
497
 
498
 
8728 leency 499
PROCEDURE init* (getStr: procGetStr);
500
BEGIN
9193 akron1 501
	currentLang := langText;
502
	loadKW(KW[langText],   Delim[langText],   getStr, "lang_Text");
503
    loadKW(KW[langOberon], Delim[langOberon], getStr, "lang_Oberon");
504
    loadKW(KW[langC],      Delim[langC],      getStr, "lang_C");
505
    loadKW(KW[langPascal], Delim[langPascal], getStr, "lang_Pascal");
506
    loadKW(KW[langLua],    Delim[langLua],    getStr, "lang_Lua");
507
    loadKW(KW[langIni],    Delim[langIni],    getStr, "lang_Ini");
508
    loadKW(KW[langFasm],   Delim[langFasm],   getStr, "lang_Fasm");
509
    loadKW(KW[langJSON],   Delim[langJSON],   getStr, "lang_JSON");
9210 akron1 510
 
511
    fileExt[ 0].ext := "OB07"; fileExt[ 0].lang := langOberon;
512
    fileExt[ 1].ext := "C";    fileExt[ 1].lang := langC;
513
    fileExt[ 2].ext := "H";    fileExt[ 2].lang := langC;
514
    fileExt[ 3].ext := "CPP";  fileExt[ 3].lang := langC;
515
    fileExt[ 4].ext := "PAS";  fileExt[ 4].lang := langPascal;
516
    fileExt[ 5].ext := "PP";   fileExt[ 5].lang := langPascal;
517
    fileExt[ 6].ext := "ASM";  fileExt[ 6].lang := langFasm;
518
    fileExt[ 7].ext := "LUA";  fileExt[ 7].lang := langLua;
519
    fileExt[ 8].ext := "INI";  fileExt[ 8].lang := langIni;
520
    fileExt[ 9].ext := "JSON"; fileExt[ 9].lang := langJSON;
521
    fileExt[10].ext := "TXT";  fileExt[10].lang := langText;
8728 leency 522
END init;
523
 
524
 
525
END Languages.