Subversion Repositories Kolibri OS

Rev

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