Subversion Repositories Kolibri OS

Rev

Rev 9190 | Rev 9210 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2021 Anton Krotov
  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 <http://www.gnu.org/licenses/>.
  18. *)
  19.  
  20. MODULE Languages;
  21.  
  22. IMPORT Lines;
  23.  
  24.  
  25. CONST
  26.  
  27.     langText* = 0; langC* = 1; langOberon* = 2; langPascal* = 3;
  28.     langFasm* = 4; langLua* = 5; langIni* = 6; langJSON* = 7;
  29.  
  30.     csLang = {langC, langOberon, langLua, langIni, langJSON};
  31.  
  32. TYPE
  33.  
  34.     tLine = Lines.tLine;
  35.  
  36.     tKeyWords = RECORD
  37.         words: ARRAY 200, 32 OF WCHAR; cnt: INTEGER
  38.     END;
  39.  
  40.     tDelimiters = ARRAY 256 OF BOOLEAN;
  41.  
  42.     procGetStr = PROCEDURE (secName, keyName: ARRAY OF CHAR; VAR s: ARRAY OF CHAR);
  43.  
  44.  
  45. VAR
  46.  
  47.         KW: ARRAY 8 OF ARRAY 3 OF tKeyWords;
  48.         Delim: ARRAY 8 OF tDelimiters;
  49.  
  50.     currentLang: INTEGER;
  51.  
  52.  
  53. PROCEDURE isCS* (lang: INTEGER): BOOLEAN;
  54.     RETURN lang IN csLang
  55. END isCS;
  56.  
  57.  
  58. PROCEDURE checkKW (s: ARRAY OF WCHAR; KW: tKeyWords): BOOLEAN;
  59. VAR
  60.     i: INTEGER;
  61. BEGIN
  62.     i := KW.cnt - 1;
  63.     WHILE (i >= 0) & (s # KW.words[i]) DO
  64.         DEC(i)
  65.     END
  66.     RETURN i >= 0
  67. END checkKW;
  68.  
  69.  
  70. PROCEDURE isKey* (s: ARRAY OF WCHAR; lang, kwSet: INTEGER): BOOLEAN;
  71.     RETURN checkKW(s, KW[lang][kwSet - 1])
  72. END isKey;
  73.  
  74.  
  75. PROCEDURE isDelim* (c: WCHAR): BOOLEAN;
  76. VAR
  77.         res: BOOLEAN;
  78. BEGIN
  79.         IF c <= 0FFX THEN
  80.                 res := Delim[currentLang][ORD(c)]
  81.         ELSE
  82.                 res := FALSE
  83.         END
  84.         RETURN res
  85. END isDelim;
  86.  
  87.  
  88. PROCEDURE SkipString* (line: tLine; VAR pos: INTEGER; n: INTEGER);
  89. VAR
  90.     quot: WCHAR;
  91. BEGIN
  92.     quot := Lines.getChar(line, pos);
  93.     REPEAT
  94.         INC(pos)
  95.     UNTIL (pos > n) OR (Lines.getChar(line, pos) = quot)
  96. END SkipString;
  97.  
  98.  
  99. PROCEDURE C (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
  100. VAR
  101.     c: WCHAR;
  102. BEGIN
  103.     c := Lines.getChar(line, pos);
  104.     IF depth = 0 THEN
  105.         IF c = "/" THEN
  106.             IF cond = 0 THEN
  107.                 cond := 1
  108.             ELSE
  109.                 cond := 0;
  110.                 pos := n
  111.             END
  112.         ELSIF (c = "*") & (cond = 1) THEN
  113.             depth := 1;
  114.             cond := 0
  115.         ELSIF (c = "'") OR (c = '"') THEN
  116.             SkipString(line, pos, n);
  117.             cond := 0
  118.         ELSE
  119.             cond := 0
  120.         END
  121.     ELSIF depth = 1 THEN
  122.         IF c = "*" THEN
  123.             cond := 1
  124.         ELSIF (c = "/") & (cond = 1) THEN
  125.             cond := 0;
  126.             depth := 0
  127.         ELSE
  128.             cond := 0
  129.         END
  130.     END
  131. END C;
  132.  
  133.  
  134. PROCEDURE getChar (line: tLine; i: INTEGER): WCHAR;
  135. VAR
  136.     res: WCHAR;
  137. BEGIN
  138.     IF i >= line.length THEN
  139.         res := 0X
  140.     ELSE
  141.         res := Lines.getChar(line, i)
  142.     END
  143.     RETURN res
  144. END getChar;
  145.  
  146.  
  147. PROCEDURE LuaLong* (line: tLine; pos: INTEGER): INTEGER;
  148. VAR
  149.     res: INTEGER;
  150. BEGIN
  151.     res := -1;
  152.     IF getChar(line, pos) = "[" THEN
  153.         INC(pos);
  154.         WHILE getChar(line, pos) = "=" DO
  155.             INC(res);
  156.             INC(pos)
  157.         END;
  158.         IF getChar(line, pos) = "[" THEN
  159.             INC(res)
  160.         ELSE
  161.             res := -1
  162.         END
  163.     END
  164.     RETURN res
  165. END LuaLong;
  166.  
  167.  
  168. PROCEDURE Lua (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
  169. VAR
  170.     c: WCHAR;
  171.     k: INTEGER;
  172. BEGIN
  173.     c := Lines.getChar(line, pos);
  174.     IF depth = 0 THEN
  175.         IF c = "-" THEN
  176.             IF cond = 0 THEN
  177.                 cond := 1
  178.             ELSE
  179.                 cond := 0;
  180.                 k := LuaLong(line, pos + 1);
  181.                 IF k >= 0 THEN
  182.                     depth := k*2 + 1
  183.                 ELSE
  184.                     pos := n
  185.                 END
  186.             END
  187.         ELSIF c = "[" THEN
  188.             cond := 0;
  189.             k := LuaLong(line, pos);
  190.             IF k >= 0 THEN
  191.                 depth := (k + 1)*2
  192.             END
  193.         ELSIF (c = "'") OR (c = '"') THEN
  194.             SkipString(line, pos, n);
  195.             cond := 0
  196.         ELSE
  197.             cond := 0
  198.         END
  199.     ELSIF depth > 0 THEN
  200.         IF (cond = 0) & (c = "]") THEN
  201.             cond := 1
  202.         ELSIF (cond >= 1) & (c = "=") THEN
  203.             INC(cond)
  204.         ELSIF (cond >= 1) & (c = "]") & (cond*2 - depth MOD 2 = depth) THEN
  205.             depth := 0;
  206.             cond := 0
  207.         ELSE
  208.             cond := 0
  209.         END
  210.     END
  211. END Lua;
  212.  
  213.  
  214. PROCEDURE Pascal (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
  215. VAR
  216.     c: WCHAR;
  217. BEGIN
  218.     c := Lines.getChar(line, pos);
  219.     IF depth = 0 THEN
  220.         IF c = "(" THEN
  221.             cond := 1
  222.         ELSIF c = "/" THEN
  223.             IF cond = 2 THEN
  224.                 cond := 0;
  225.                 pos := n
  226.             ELSE
  227.                 cond := 2
  228.             END
  229.         ELSIF (c = "*") & (cond = 1) THEN
  230.             depth := 2;
  231.             cond := 0
  232.         ELSIF c = "'" THEN
  233.             SkipString(line, pos, n);
  234.             cond := 0
  235.         ELSIF c = "{" THEN
  236.             IF Lines.getChar(line, pos + 1) = "$" THEN
  237.                 depth := 3
  238.             ELSE
  239.                 depth := 1
  240.             END;
  241.             cond := 0
  242.         ELSE
  243.             cond := 0
  244.         END
  245.     ELSIF depth IN {1, 3} THEN
  246.         IF c = "}" THEN
  247.             depth := 0
  248.         END
  249.     ELSIF depth = 2 THEN
  250.         IF c = "*" THEN
  251.             cond := 1
  252.         ELSIF (c = ")") & (cond = 1) THEN
  253.             depth := 0;
  254.             cond := 0
  255.         ELSE
  256.             cond := 0
  257.         END
  258.     END
  259. END Pascal;
  260.  
  261.  
  262. PROCEDURE Oberon (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
  263. VAR
  264.     c: WCHAR;
  265. BEGIN
  266.     c := Lines.getChar(line, pos);
  267.     IF (depth = 0) & (c = "/") THEN
  268.         IF cond = 3 THEN
  269.             cond := 0;
  270.             pos := n
  271.         ELSE
  272.             cond := 3
  273.         END
  274.     ELSIF (depth = 0) & ((c = "'") OR (c = '"')) THEN
  275.         SkipString(line, pos, n);
  276.         cond := 0
  277.     ELSIF c = "(" THEN
  278.         cond := 1
  279.     ELSIF c = "*" THEN
  280.         IF cond = 1 THEN
  281.             INC(depth);
  282.             cond := 0
  283.         ELSE
  284.             cond := 2
  285.         END
  286.     ELSIF c = ")" THEN
  287.         IF cond = 2 THEN
  288.             IF depth > 0 THEN
  289.                 DEC(depth)
  290.             END
  291.         END;
  292.         cond := 0
  293.     ELSE
  294.         cond := 0
  295.     END;
  296. END Oberon;
  297.  
  298.  
  299. PROCEDURE Ini (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER);
  300. VAR
  301.     c: WCHAR;
  302. BEGIN
  303.     cond := 0;
  304.     c := Lines.getChar(line, pos);
  305.     IF depth = 0 THEN
  306.         IF c = ";" THEN
  307.             pos := n
  308.         ELSIF c = '"' THEN
  309.             SkipString(line, pos, n)
  310.         ELSIF c = "[" THEN
  311.             depth := 1
  312.         END
  313.     ELSIF depth = 1 THEN
  314.         IF c = "]" THEN
  315.             depth := 0
  316.         END
  317.     END
  318. END Ini;
  319.  
  320.  
  321. PROCEDURE comments* (line: tLine; VAR depth, cond, pos: INTEGER; n: INTEGER; lang: INTEGER);
  322. BEGIN
  323.     CASE lang OF
  324.     |langText:
  325.     |langFasm:
  326.     |langC,
  327.      langJSON:    C(line, depth, cond, pos, n)
  328.     |langOberon:  Oberon(line, depth, cond, pos, n)
  329.     |langPascal:  Pascal(line, depth, cond, pos, n)
  330.     |langLua:     Lua(line, depth, cond, pos, n)
  331.     |langIni:     Ini(line, depth, cond, pos, n)
  332.     END
  333. END comments;
  334.  
  335.  
  336. PROCEDURE EnterKW (s: ARRAY OF CHAR; VAR KW: tKeyWords; CPrep: BOOLEAN);
  337. CONST
  338.     SPACE = 20X; CR = 0DX; LF = 0AX; TAB = 9X; COMMA = ",";
  339. VAR
  340.     i, j, k: INTEGER;
  341.  
  342.     PROCEDURE delim (c: CHAR): BOOLEAN;
  343.         RETURN (c = COMMA) OR (c = SPACE) OR (c = CR) OR (c = LF) OR (c = TAB)
  344.     END delim;
  345.  
  346. BEGIN
  347.     k := KW.cnt;
  348.     i := 0;
  349.     REPEAT
  350.         KW.words[k, 0] := "#";
  351.         j := ORD(CPrep);
  352.         WHILE (s[i] # 0X) & ~delim(s[i]) DO
  353.             KW.words[k, j] := WCHR(ORD(s[i]));
  354.             INC(i);
  355.             INC(j)
  356.         END;
  357.         KW.words[k, j] := 0X;
  358.         INC(k);
  359.         WHILE delim(s[i]) DO
  360.             INC(i)
  361.         END
  362.     UNTIL s[i] = 0X;
  363.     KW.cnt := k
  364. END EnterKW;
  365.  
  366.  
  367. PROCEDURE loadKW (VAR KW: ARRAY OF tKeyWords; VAR delim: tDelimiters; getStr: procGetStr; lang: ARRAY OF CHAR);
  368. VAR
  369.     s: ARRAY 16*1024 OF CHAR;
  370.     key: ARRAY 4 OF CHAR;
  371.     i: INTEGER;
  372. BEGIN
  373.         FOR i := 0 TO LEN(delim) - 1 DO
  374.                 delim[i] := FALSE
  375.         END;
  376.         getStr(lang, "delim", s);
  377.         i := 0;
  378.         WHILE s[i] # 0X DO
  379.                 delim[ORD(s[i])] := TRUE;
  380.                 INC(i)
  381.         END;
  382.     key := "KW1";
  383.     FOR i := 0 TO 2 DO
  384.         KW[i].cnt := 0;
  385.         key[2] := CHR(ORD("1") + i);
  386.         getStr(lang, key, s);
  387.         EnterKW(s, KW[i], (lang = "lang_C") & (i = 1))
  388.     END
  389. END loadKW;
  390.  
  391.  
  392. PROCEDURE setCurLang* (lang: INTEGER);
  393. BEGIN
  394.         currentLang := lang
  395. END setCurLang;
  396.  
  397.  
  398. PROCEDURE init* (getStr: procGetStr);
  399. BEGIN
  400.         currentLang := langText;
  401.         loadKW(KW[langText],   Delim[langText],   getStr, "lang_Text");
  402.     loadKW(KW[langOberon], Delim[langOberon], getStr, "lang_Oberon");
  403.     loadKW(KW[langC],      Delim[langC],      getStr, "lang_C");
  404.     loadKW(KW[langPascal], Delim[langPascal], getStr, "lang_Pascal");
  405.     loadKW(KW[langLua],    Delim[langLua],    getStr, "lang_Lua");
  406.     loadKW(KW[langIni],    Delim[langIni],    getStr, "lang_Ini");
  407.     loadKW(KW[langFasm],   Delim[langFasm],   getStr, "lang_Fasm");
  408.     loadKW(KW[langJSON],   Delim[langJSON],   getStr, "lang_JSON");
  409. END init;
  410.  
  411.  
  412. END Languages.