Просмотр исходного кода

Автодок: исправлено распознавание VAR [nil]; поиск файла со стилем

Arthur Yefimov 2 лет назад
Родитель
Сommit
ef9e3037a8

+ 5 - 2
src/Autodoc/AutodocHtml.Mod

@@ -204,8 +204,11 @@ END WriteParagraphs;
 PROCEDURE WriteStyle;
 VAR T2: Texts.Text;
   buf: Texts.Buffer;
+  path: ARRAY 1024 OF CHAR;
 BEGIN
-  NEW(T2); Texts.Open(T2, styleFname);
+  Env.GetAppDir(path);
+  Strings.Append(styleFname, path);
+  NEW(T2); Texts.Open(T2, path);
   IF T2.len # 0 THEN
     WriteLn('<style>');
     Texts.Append(TX, W.buf);
@@ -214,7 +217,7 @@ BEGIN
     Texts.Append(TX, buf);
     WriteLn(''); WriteLn('</style>')
   ELSE Out.String('Could not find stylesheet file "');
-    Out.String(styleFname); Out.String('".'); Out.Ln
+    Out.String(path); Out.String('".'); Out.Ln
   END
 END WriteStyle;
 

+ 5 - 1
src/Autodoc/AutodocParser.Mod

@@ -1265,7 +1265,11 @@ VAR first, par: Param;
   T: Type;
   passed: INTEGER;
 BEGIN
-  IF (sym = var) OR (sym = in) OR (sym = out) THEN GetSym; passed := byVar
+  IF (sym = var) OR (sym = in) OR (sym = out) THEN GetSym; passed := byVar;
+    IF sym = lbrak THEN GetSym;
+      IF (sym = ident) OR (sym = int) THEN GetSym ELSE MarkExp('hint') END;
+      IF sym = rbrak THEN GetSym ELSE MarkExp(']') END
+    END
   ELSE passed := byValue
   END;
 

+ 179 - 0
src/Autodoc/Test2/Apples.Mod

@@ -0,0 +1,179 @@
+(*
+Файл -> модуль
+  (название)
+
+Объекты:
+  - константы
+  - типы
+  - переменные
+  - процедуры
+
+(только эспортированное)
+
+Комментарии вида (**...*):
+  - начинающиеся на той же строке, на которой заканчивается объект
+  - перед объектами (с одной звёздочкой на конце)
+  - перед группами объектов (с двумя звёздочками на конце), "заголовки"
+*)
+
+
+(** Module Apples helps count apples.
+    One can create a variable of type Apples.Apple,
+    call Init and other procedures on it *)
+MODULE Apples;
+(** Это тестовый модуль. *)
+IMPORT Out, F := Files, SYSTEM, Fruits;
+
+CONST
+  str4* = "В двойных кавычках.";
+  str5* = "Кавычки 'в' кавычках.";
+  str1* =  '';
+  appleJuice='сок';
+  appleLen=15;
+  appleLen2=15  ;
+  str2* = 'H';
+  str3* = 'Привет   Как  дела?';
+  str6* = 'Кавычки "в двойных" кавычках.';
+
+  (** Общие постоянные **)
+
+  (** Start amount of apples. Used in Reset *)
+  startApples =  0;
+
+  maxApples*  =  5; (** Maximum amount of apples*)
+  maxSeeds*   = 3; (** Currently not in use *)
+
+  (** Качество яблока **)
+  good*    = 1; (** Сносное качество *)
+  unknown* = 0; (** Неизвестное качество *)
+  bad*     = 2; (** Отвратное качество *)
+  
+  (** Литерные коды **)
+  (** Компьютер *)
+  computer*  = 'c';
+  (**Человек*)
+  human*     = 'H';
+  (**    Игрок    *)
+  player*    = 'i'; (** во что-то *)
+  rusLetter* = 'а'; (** Буква русская, а, маленькая! *)
+  engLetter* = 'a';
+  (** Игра       просто игра *)
+  game*      = 'I';
+  tableRow1* = '1';
+  tableRow2* = '2';
+
+TYPE
+
+  FL = F.File;
+
+  LetterA = CHAR;
+  LetterB = CHAR;
+
+  (** ФРУКТЫ **)
+
+  (**Тип яблоко *)
+  Apple* = RECORD(Fruits.Fruit) (** Represents an apple with some seeds *)
+    seeds*: INTEGER;   (** Amount of seeds in the apple *)
+    quality*: INTEGER; (** Качество продукта, см. @Качество яблока *)
+    added: BOOLEAN     (** Whether Add was called on this seed after Init *)
+  END;
+
+  (** - **)
+  LetterC* = CHAR;
+  LetterD = CHAR;
+
+  (** ВСЯКОЕ **)
+
+  INT32* = SYSTEM.INT32; (** Четырёхбайтовик *)
+  INT64 = LONGINT; (** Длинное целое *)
+  (** Просто массив *)
+  Array* = POINTER TO ARRAY OF RECORD i: INTEGER END;
+
+  Point = RECORD x, y: REAL (**Координаты!*) END; (** Точка? *)
+  
+  P1* = PROCEDURE; (** Процедура без ничего *)
+  P2* = PROCEDURE(); (** Процедура с пустыми скобками *)
+  P3* = PROCEDURE(): BOOLEAN; (** Булева процедура без параметров *)
+  P4* = PROCEDURE(a, b: INTEGER): BOOLEAN; (** Булева процедура *)
+  P5* = PROCEDURE(x: INTEGER; y: CHAR; z: CHAR); (** Процедура с параметрами *)
+
+VAR
+  applesCreated*: INTEGER; (** How many apples were created using Init *)
+  (** If FALSE, Show shows a welcome message and sets shown to TRUE *)
+  shown: BOOLEAN;
+  lastAdded*: INTEGER; (** How many seeds were added the last time, or -1 *)
+  (** ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ЗАПИСНЫХ ТИПОВ **)
+  R*: RECORD(F.Rider)
+    t, x: INTEGER; (** Время в секундах и мс *)
+    z, y: Array    (** Z-буфер, показатель светимости  *)
+  END;
+  T: RECORD END;
+
+
+  (*: PROCEDURE;
+  b*: PROCEDURE(): INTEGER;
+  y: ARRAY N, M OF PROCEDURE (VAR n: ARRAY OF BOOLEAN; VAR x, y: INTEGER): REAL;
+  p*: POINTER TO Bird;*)
+
+(** Sets the given amount of seeds to apple a. *)
+PROCEDURE Set(VAR a: Apple; seeds: INTEGER);
+BEGIN
+  a.seeds := seeds;
+  IF seeds >= 3 THEN a.quality := good
+  ELSIF seeds = 0 THEN a.quality := bad
+  ELSE a.quality := unknown
+  END
+END Set;
+
+PROCEDURE Init*(VAR a: Apple; seeds: INTEGER);
+(** Initializes apple a with the specified amount of seeds. *)
+BEGIN
+  INC(applesCreated);
+  Set(a, seeds);
+  a.added := FALSE
+END Init;
+
+(** Apple manipulation **)
+
+(** Adds n seeds to apple a. *)
+(*PROCEDURE Add*(VAR a: ARRAY 25 OF Fruits.Fruit23; VAR x, y, z, n: INTEGER);*)
+PROCEDURE Add*(VAR a: Apple; n: INTEGER);
+BEGIN
+  lastAdded := n;
+  Set(a, a.seeds + n);
+  a.added := TRUE
+END Add;
+
+PROCEDURE Show*(a: Apple);
+(** Dispalys a message about the apple. *)
+BEGIN
+  IF ~shown THEN
+    Out.String('Welcome to Apples!');
+    Out.Ln;
+    shown := TRUE
+  END;
+  IF a.added THEN
+    Out.String('Added apple with ')
+  ELSE
+    Out.String('Apple with ')
+  END;
+  Out.Int(a.seeds, 0);
+  Out.String(' seeds.');
+  Out.Ln
+END Show;
+
+(** - **)
+
+(** Resets internal apple counter. *)
+PROCEDURE Reset*;
+BEGIN
+  lastAdded := -1;
+  applesCreated := startApples;
+  shown := FALSE
+END Reset;
+
+PROCEDURE Shown*(): BOOLEAN; RETURN shown END Shown; (** Было ли приветствие *)
+
+BEGIN
+  Reset
+END Apples.

+ 4 - 0
src/Autodoc/Test2/Fruits.Mod

@@ -0,0 +1,4 @@
+MODULE Fruits;
+TYPE
+  Fruit* = RECORD END;
+END Fruits.

+ 235 - 0
src/Autodoc/Test2/style.css

@@ -0,0 +1,235 @@
+@font-face {
+  font-family: 'customfont';
+  src: url(font.ttf);
+}
+
+body, p, h1, h2, h3, h4, h5, h6 {
+  margin: 0;
+  padding: 0;
+}
+
+html {
+  height: 100%;
+}
+
+body {
+  font-family: customfont, monospace, sans-serif;
+  font-size: 14px;
+  background: #FBC5AA;
+  background: var(--main-bg);
+  color: #12365D;
+  color: var(--main-fg);
+  min-height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+
+a {
+  color: #D95D27;
+  color: var(--high-bg);
+  text-decoration: none;
+}
+
+a:hover {
+  color: #FF4D00;
+}
+
+.inner {
+  max-width: 1160px;
+  padding: 0 20px;
+  margin: 0 auto;
+}
+
+.header {
+  padding: 30px 0;
+  background: #12365D;
+  background: var(--head-bg);
+  color: #93B2D3;
+  color: var(--head2-bg);
+}
+
+.header h1 .module-name {
+  color: #FFF;
+  color: var(--head-fg);
+}
+
+.header h1 .subtitle {
+  display: block;
+  font-size: 16px;
+  color: #4D89C7;
+  color: var(--head2-fg);
+}
+
+.footer {
+  padding: 50px 0;
+  background: #2D5E90;
+  background: var(--head-bg);
+  color: #FFF;
+  color: var(--head-fg);
+}
+
+.footer p {
+  text-align: center;
+}
+
+.main {
+  padding: 20px 0;
+  flex: 1;
+}
+
+h2, h3, h4, h5, h6 {
+  margin: 1.2em 0 0.5em;
+}
+
+.heading {
+  background: #12365D;
+  background: var(--title-bg);
+  color: #FFF;
+  color: var(--title-fg);
+  margin: 20px -20px 15px;
+  width: max-content;
+  min-width: calc(min(250px, 100%));
+  box-sizing: border-box;
+  padding: 6px 60px 6px 40px;
+  text-transform: uppercase;
+  font-size: 16px;
+  box-shadow: 6px 6px 1px var(--box-bg);
+}
+
+.group-title {
+  padding: 0 2px;
+  margin: 18px 0 8px;
+}
+
+.ordinal-consts {
+  overflow-x: auto;
+  border: 1px solid #808080;
+  border-color: var(--box-fg);
+  box-shadow: 0 1px 3px var(--box-bg);
+}
+
+.ordinal-consts table {
+  background: #FFF;
+  background: var(--tab-bg);
+  min-width: 450px;
+  width: 100%;
+}
+
+.ordinal-consts th,
+.ordinal-consts td {
+  background: #FFBF44;
+  background: var(--tab-row-bg);
+  border: 1px solid var(--box-bg);
+  padding: 2px 5px;
+  vertical-align: top;
+}
+
+.ordinal-consts th {
+  text-align: left;
+  font-weight: normal;
+  background: #B91E0C;
+  background: var(--tab-head-bg);
+  border-color: #B91E0C;
+  border-color: var(--tab-head-bg);
+  color: #FFF;
+  color: var(--tab-head-fg);
+}
+
+.ordinal-consts .name {
+  width: 140px;
+}
+
+.ordinal-consts td.name {
+  color: #B91E0C;
+  color: var(--tab-row-fg);
+}
+
+.ordinal-consts .value {
+  width: 60px;
+}
+
+.ordinal-consts td.desc {
+  background: transparent;
+  border-color: transparent;
+  border-bottom-color: var(--box-bg);
+}
+
+.ordinal-consts tr:last-child td.desc {
+  border-color: transparent;
+}
+
+.ordinal-consts .desc .comment {
+  padding: 0;
+}
+
+.object {
+  background: #FFF;
+  background: var(--tab-bg);
+  border: 1px solid #808080;
+  border-color: var(--box-fg);
+  padding: 2px;
+  margin: 6px 0;
+  box-shadow: 0 1px 3px var(--box-bg);
+}
+
+.object .def {
+  background: #FFBF44;
+  background: var(--tab-row-bg);
+  border: 1px solid var(--box-bg);
+  padding: 2px 5px;
+}
+
+.object .name,
+.object .record-base {
+  color: #B91E0C;
+  color: var(--tab-row-fg);
+}
+
+.const .value {
+  color: #000;
+  color: var(--tab-fg);
+}
+
+.value i {
+  font-style: normal;
+  color: #277FC0;
+  color: var(--high-fg);
+}
+
+.comment {
+  padding: 10px 6px;
+  color: #2D5E90;
+  color: var(--comment-fg);
+}
+
+.object > .comment:empty {
+  display: none;
+}
+
+.record-fields .comment {
+  color: #C91E0C;
+  color: var(--tab-row-fg);
+}
+
+.comment .mark {
+  color: #D1702C;
+  color: var(--comment-bg);
+}
+
+.record-fields {
+  display: grid;
+  grid-template-columns: auto 1fr;
+}
+
+.record-fields .comment {
+  padding: 0;
+}
+
+.export {
+  color: #12365D;
+  color: var(--title-bg);
+}
+
+@media screen and (max-width: 500px) {
+
+}

+ 15 - 3
src/Env.Mod

@@ -1,5 +1,5 @@
 MODULE Env;
-IMPORT CmdArgs, Args, Platform, Utf8, SYSTEM;
+IMPORT CmdArgs, Args, Platform, Utf8, Strings, SYSTEM, Out;
 TYPE SHORTCHAR = Utf8.SHORTCHAR;
 
 VAR count: INTEGER;
@@ -76,9 +76,21 @@ PROCEDURE RemoveDoubleSlashes(VAR s: ARRAY OF CHAR);
 BEGIN (*!TODO*)
 END RemoveDoubleSlashes;
 
-(** Example: './' -> ''. *)
+(** Leaves '/' in the end. Example: './' -> ''. *)
 PROCEDURE RemoveDotDirs(VAR s: ARRAY OF CHAR);
-BEGIN (*!TODO*)
+VAR i: INTEGER;
+BEGIN
+  i := 0;
+  WHILE s[i] # 0X DO
+    WHILE (s[i] # 0X) & (s[i] # '.') DO INC(i) END;
+    IF s[i] # 0X THEN (* Found a dot *)
+      IF (s[i + 1] = '/') & ((i = 0) OR (s[i - 1] = '/')) THEN
+        Strings.Delete(s, i, 2)
+      ELSE INC(i)
+      END
+    END
+  END;
+  IF (i > 1) & (s[i - 2] = '/') & (s[i - 1] = '.') THEN s[i - 1] := 0X END
 END RemoveDotDirs;
 
 (** Example: 'dir/..' -> ''. *)

+ 2 - 2
src/Files.Mod

@@ -288,7 +288,7 @@ PROCEDURE HasDir(IN name: ARRAY OF CHAR): BOOLEAN;
 VAR i: INTEGER; ch: CHAR;
 BEGIN i := 0; ch := name[0];
   WHILE (ch # 0X) & (ch # PathDelimiter) DO INC(i); ch := name[i] END ;
-RETURN ch = PathDelimiter END HasDir;
+RETURN ch # 0X END HasDir;
 
 PROCEDURE CacheEntry(identity: Platform.FileIdentity): File;
 VAR f: File; i: INTEGER; error: Platform.ErrorCode; n: INT64;
@@ -323,7 +323,7 @@ VAR f: File;
 BEGIN
   IF name # '' THEN
     (* Replace all / with \ if required *)
-    IF Platform.PathDelimiter = '\' THEN i := 0;
+    IF PathDelimiter = '\' THEN i := 0;
       WHILE (i # LEN(name)) & (name[i] # 0X) DO
         IF name[i] = '/' THEN name[i] := '\' END;
         INC(i)