Browse Source

Описание типов для Автодока

Arthur Yefimov 2 years ago
parent
commit
5a25672afc
2 changed files with 283 additions and 0 deletions
  1. 162 0
      src/Autodoc.Mod
  2. 121 0
      src/AutodocParser.Mod

+ 162 - 0
src/Autodoc.Mod

@@ -0,0 +1,162 @@
+MODULE Autodoc;
+IMPORT Files, Texts, Out, Args, Strings, Config, Platform, P := AutodocParser;
+
+CONST
+  delim = Platform.PathDelimiter;
+
+TYPE
+  Module* = P.Module;
+
+PROCEDURE SaveHtml*(module: Module; fname: ARRAY OF CHAR): BOOLEAN;
+VAR T: Texts.Text;
+  W: Texts.Writer;
+BEGIN
+  NEW(T); Texts.Open(T, '');
+  Texts.OpenWriter(W);
+  Texts.WriteString(W, '<h1>'); Texts.WriteString(W, fname);
+  Texts.WriteString(W, '</h1>'); Texts.WriteLn(W);
+  Texts.Append(T, W.buf);
+  Texts.Close(T, fname);
+RETURN TRUE END SaveHtml;
+
+PROCEDURE OpenFile(fname: ARRAY OF CHAR; VAR r: Files.Rider): BOOLEAN;
+VAR F: Files.File;
+BEGIN F := Files.Old(fname);
+  IF F # NIL THEN Files.Set(r, F, 0) END
+RETURN F # NIL END OpenFile;
+
+PROCEDURE HandleFile*(in, out: ARRAY OF CHAR);
+VAR err: ARRAY 1024 OF CHAR;
+  r: Files.Rider;
+  module: Module;
+BEGIN
+  IF OpenFile(in, r) THEN
+    module := P.ParseModule(r, err);
+    IF module # NIL THEN
+      IF SaveHtml(module, out) THEN
+        Out.String('Created "'); Out.String(out);
+        Out.String('".'); Out.Ln
+      ELSE
+        Out.String('Error saving file "'); Out.String(out);
+        Out.String('".'); Out.Ln
+      END
+    ELSE
+      Out.String('Error parsing file "');
+      Out.String(in); Out.String('": ');
+      Out.String(err); Out.Char('.'); Out.Ln
+    END
+  ELSE
+    Out.String('Error: Could not open file "');
+    Out.String(in); Out.String('".'); Out.Ln
+  END
+END HandleFile;
+
+(** Gets file name with out path or extension.
+    Example: 'a/b/c.txt' -> 'c' *)
+PROCEDURE GetBaseName(s: ARRAY OF CHAR; VAR name: ARRAY OF CHAR);
+VAR i, j, len: INTEGER;
+BEGIN
+  (* len := Length of s *)
+  len := 0; WHILE s[len] # 0X DO INC(len) END;
+  (* j := position of last '.' in s, or -1 *)
+  j := len; WHILE (j # -1) & (s[j] # '.') DO DEC(j) END;
+  (* i := position of last slash in s, or 0 *)
+  i := len; WHILE (i # 0) & (s[i] # '/') & (s[i] # '\') DO DEC(i) END;
+  IF j < i THEN j := len END;
+  Strings.Extract(s, i, j - i, name)
+END GetBaseName;
+
+PROCEDURE HandleFileToDir*(in, dir: ARRAY OF CHAR);
+VAR name, out: ARRAY 512 OF CHAR;
+  len: INTEGER;
+BEGIN
+  out := dir;
+  len := Strings.Length(out);
+  IF (len # 0) & (out[len - 1] # '/') & (out[len - 1] # '\') THEN
+    Strings.Append(delim, out)
+  END;
+  GetBaseName(in, name);
+  Strings.Append(name, out);
+  Strings.Append('.html', out);
+
+  Out.String('out="'); Out.String(out); Out.Char('"'); Out.Ln
+END HandleFileToDir;
+
+PROCEDURE Usage;
+VAR s: ARRAY 256 OF CHAR;
+BEGIN
+  Out.String('Free Oberon AutoDoc tool version ');
+  Out.String(Config.version); Out.Ln;
+  Out.String('Copyright (c) 2022-'); Out.Int(Config.year, 0);
+  Out.String(' by Arthur Yefimov and others.'); Out.Ln;
+  Out.String('Usage:'); Out.Ln; Args.Get(0, s);
+  Out.String('  '); Out.String(s);
+  Out.String(' { "-o" outputPath | sourceFile}'); Out.Ln; Out.Ln;
+  Out.String('outputPath is a file name if a single source file is given.');
+  Out.Ln;
+  Out.String('outputPath is a directory if many source files are given.');
+  Out.Ln; Out.Ln;
+  Out.String('Examples:'); Out.Ln;
+  Out.String('  '); Out.String(s);
+  Out.String(' -o Apples.Mod'); Out.Ln;
+  Out.String('  '); Out.String(s);
+  Out.String(' -o doc.html Apples.Mod'); Out.Ln;
+  Out.String('  '); Out.String(s);
+  Out.String(' -o docs Fruits.Mod Apples.Mod'); Out.Ln; Out.Ln
+END Usage;
+
+(** Changes extension of the file to '.html'. Puts result is out. *)
+PROCEDURE FnameToHtml(fname: ARRAY OF CHAR; VAR out: ARRAY OF CHAR);
+VAR i: INTEGER;
+BEGIN
+  i := Strings.Length(fname);
+  IF i # 0 THEN
+    (* Find last '.' in fname *)
+    DEC(i); WHILE (i # -1) & (fname[i] # '.') DO DEC(i) END;
+    IF i # -1 THEN Strings.Extract(fname, 0, i, out)
+    ELSE Strings.Copy(fname, out)
+    END;
+    Strings.Append('.html', out)
+  ELSE
+    out[0] := 0X
+  END
+END FnameToHtml;
+
+PROCEDURE Do;
+VAR i: INTEGER;
+  out, s: ARRAY 256 OF CHAR;
+  fnames: ARRAY 64, 256 OF CHAR;
+  fnameCount: INTEGER;
+BEGIN
+  IF Args.Count = 0 THEN
+    Usage
+  ELSE
+    out[0] := 0X;
+    i := 1; fnameCount := 0;
+    WHILE i <= Args.Count DO
+      Args.Get(i, s);
+      IF s = '-o' THEN
+        IF i + 1 <= Args.Count THEN
+          Args.Get(i + 1, out);
+          INC(i)
+        END
+      ELSE
+        Strings.Copy(s, fnames[fnameCount]);
+        INC(fnameCount)
+      END;
+      INC(i)
+    END;
+    IF fnameCount = 1 THEN
+      IF out[0] = 0X THEN FnameToHtml(fnames[0], out) END;
+      HandleFile(fnames[0], out)
+    ELSE
+      FOR i := 0 TO fnameCount - 1 DO
+        HandleFileToDir(fnames[i], out)
+      END
+    END
+  END
+END Do;
+
+BEGIN
+  Do
+END Autodoc.

+ 121 - 0
src/AutodocParser.Mod

@@ -0,0 +1,121 @@
+MODULE AutodocParser;
+IMPORT Files, Texts, Out, Args, Strings, Config, Platform;
+CONST
+  (** Lexer constants **)
+  null*    = 0;
+  comment* = 1;
+
+  ident*   = 1;
+  int*     = 2;
+  real*    = 3;
+  set*     = 4;
+  string*  = 5;
+
+  module*  = 10;
+  record*  = 11;
+  array*   = 12;
+  pointer* = 13;
+  to*      = 14;
+  of*      = 15;
+  begin*   = 16;
+  end*     = 17;
+
+  lparen*  = 30;
+  rparen*  = 31;
+  lbrak*   = 32;
+  rbrak*   = 33;
+  lbrace*  = 34;
+  rbrace*  = 35;
+  period*  = 36;
+  comma*   = 37;
+  upto*    = 38;
+  colon*   = 39;
+  semicol* = 40;
+  equals*  = 41;
+  plus*    = 42;
+  minus*   = 43;
+  times*   = 44;
+  div*     = 45;
+  mod*     = 46;
+  rdiv*    = 47;
+
+  eot*     = 70;
+
+  (** Forms of Types **)
+
+  undefType*     = 0;
+  namedType*     = 1;
+  recordType*    = 2;
+  arrayType*     = 3;
+  pointerType*   = 4;
+  procedureType* = 5;
+
+  (** See @Pass Kinds of Parameters *)
+  byValue* = 0;
+  byVar*   = 1;
+
+TYPE
+  Str* = ARRAY 256 OF CHAR;
+  LongStr* = ARRAY 40960 OF CHAR;
+
+  Object* = POINTER TO ObjectDesc;
+  ObjectDesc* = RECORD
+    name*: Str;
+    comment*: LongStr;
+    next: Object
+  END;
+
+  List* = POINTER TO ListDesc;
+  ListDesc* = RECORD
+    first*, last: Object
+  END;
+
+  Group* = POINTER TO GroupDesc;
+  GroupDesc* = RECORD(ObjectDesc)
+    body*: List
+  END;
+
+  Const* = POINTER TO ConstDesc;
+  ConstDesc* = RECORD(ObjectDesc)
+    value*: Str;
+    isOrdinal*: BOOLEAN; (** TRUE if type of const is integer or char *)
+    intVal*: INTEGER (** If isOrdinal, holds value in integer format *)
+  END;
+
+  Type* = POINTER TO TypeDesc;
+  TypeDesc* = RECORD(ObjectDesc)
+    form*: INTEGER; (** See @Form of Types *)
+    len*: INTEGER;
+    base*: Type; (** Base type of record, array or pointer *)
+    fields*: List
+  END;
+
+  Var* = POINTER TO VarDesc;
+  VarDesc* = RECORD(ObjectDesc)
+    type*: Type
+  END;
+
+  Param* = POINTER TO ParamDesc;
+  ParamDesc* = RECORD(ObjectDesc)
+    pass*: INTEGER; (** See @Pass Kinds of Parameters *)
+    type*: Type
+  END;
+
+  Procedure* = POINTER TO ProcedureDesc;
+  ProcedureDesc* = RECORD(ObjectDesc)
+    returnType*: Type;
+    params*: List
+  END;
+
+  Module* = POINTER TO ModuleDesc;
+  ModuleDesc* = RECORD(ObjectDesc)
+  END;
+
+PROCEDURE ParseModule*(VAR r: Files.Rider; VAR err: ARRAY OF CHAR): Module;
+VAR module: Module;
+BEGIN
+  NEW(module);
+  RETURN module
+END ParseModule;
+
+END AutodocParser.