#line 407 "/home/ubuntu/felix/src/packages/flx_doc.fdoc"
open Regdef;
regdef ident_r = perl("[A-Za-z_][A-Za-z_0-9]*");
regdef fkey_r = ident_r "." ident_r;
regdef cmd_name_r = perl("[A-Za-z_][A-Za-z_0-9]*| *");
regdef spc_r = " " *;
regdef any_r = perl(".*");
regdef cmd_r = "@" group(cmd_name_r) spc_r group(any_r);
regdef tangler_r = "@tangler" spc_r group(fkey_r) spc_r "=" spc_r group(any_r);
regdef url_r = group(any_r) '<a href="' group(any_r) '">' group(any_r) "</a>" group(any_r);
regdef class_r = ("open" spc_r)? ("class"|"module") spc_r group(ident_r) any_r;
regdef def_r ="ctor"|"fun"|"proc"|"gen"|"type"|"union"|"struct"|"cstruct"|"const"|"header"|"typedef";
regdef adj_r = "virtual" | "inline";
regdef fun_r = " " (adj_r spc_r)? group(def_r) spc_r group(ident_r) any_r;
var cmd_R = RE2 (render cmd_r);
var tangler_R = RE2 (render tangler_r);
var url_R = RE2 (render url_r);
var fun_R = RE2 (render fun_r);
var class_R = RE2 (render class_r);
typedef markup_t = (`Txt | `At | `Code | `Slosh | `Math | `MathSlosh);
fun code_fixer (a:string): string =
{
var out = "";
var mode = (#`Txt) :>> markup_t;
for ch in a do
match mode with
| `Txt =>
if ch == char "@" do
mode = (#`At) :>> markup_t;
elif ch == char "\\" do
mode = (#`Slosh) :>> markup_t;
else
out += ch;
done
| `Slosh =>
if ch == char "(" do
mode = (#`Math) :>> markup_t;
out += ":math:`";
else
out += "\\" + ch;
mode = (#`Txt) :>> markup_t;
done
| `Math =>
if ch == char "\\" do
mode = (#`MathSlosh) :>> markup_t;
else
out+= ch;
done
| `MathSlosh =>
if ch == ")" do
out+="` ";
mode = (#`Txt) :>> markup_t;
else
out+="\\" + ch;
mode = (#`Math) :>> markup_t;
done
| `At =>
if ch == char "{" do
out += " :code:`";
mode = (#`Code) :>> markup_t;
else
out += "@"+ch;
done
| `Code =>
if ch == char "}" do
out += "`";
mode = (#`Txt) :>> markup_t;
else
out += ch;
done
endmatch;
done
return out;
}
fun url_fixer (a:string) =>
match Match (url_R, a) with
| None => a
| Some grp => grp.1 + "`" + grp.3 + " <" + grp.2 + ">`_" + grp.4
;
fun code_markup(a:string) => code_fixer (url_fixer a);
fun lexer_from_filename (var s:string) : string =
{
s = strip s;
var lexer =
match s.Filename::get_extension with
| (".cpp" | ".cxx" | ".hpp") => "cpp"
| (".flx" | ".fdoc" | ".fsyn") => "felix"
| (".fpc") => "fpc"
| (".c" | ".h") => "c"
| (".py") => "python"
| _ => "text"
endmatch
;
return lexer;
}
typedef mode_t = (`Doc | `Code | `Tangler);
fun process_file (f: string): string =
{
var tanglers = Empty[string * string];
var code_buf = Empty[string];
var prefix = "";
var out = "";
proc emit_code () {
var b = unbox (rev code_buf);
for l in b do
var rc = Match (class_R, l);
var rf = Match (fun_R, l);
chainmatch rc with
| Some grp =>
out+= ".. index:: " + grp.1+"(class)" + "\n";
ormatch rf with
| Some grp =>
out+= ".. index:: " + grp.2+"("+grp.1+")" + "\n";
| None => ;
endmatch;
done
out += prefix;
for l in b perform out += " " + l + "\n";
code_buf = Empty[string];
mode = (#`Doc) :>> mode_t;
}
proc println[T with Str[T]] (x:T) => out += x.str + "\n";
var mode : mode_t = (#`Doc) :>> mode_t;
nextline: for line in split (f, char "\n") do
var cmd = Match (tangler_R, line);
match cmd with
| Some grp =>
mode = (#`Tangler) :>> mode_t;
tanglers = (grp.1,grp.2) ! tanglers;
continue nextline;
| None =>
match mode with
| `Tangler =>
var tab = unbox (rev tanglers);
tanglers = Empty[string * string];
var lkey,lfile = fold_left
(fun (lkey:int,lfile:int) (key:string,file:string) =>
max (lkey, key.len.int), max (lfile, file.len.int)
)
(10,20)
tab
;
var tabline = "=" * lkey + " " + "=" * lfile;
println$ tabline;
println$
("key" + " " * lkey).[0..lkey] +
("file" + " " * lfile).[0..lfile]
;
println$ tabline;
for item in tab do
var key,file = item;
println$
(key + " " * lkey).[0..lkey] +
(file + " " * lfile).[0..lfile]
;
done
println$ tabline;
mode = (#`Doc) :>> mode_t;
| _ => ;
endmatch;
endmatch;
cmd = Match (cmd_R, line);
match cmd with
| Some grp =>
var c = grp.1;
var a = grp.2;
if c == "title" do
println$ "";
match mode with
| `Code () => emit_code();
| _ => ;
endmatch;
a = code_markup a;
println$ "=" * a.len.int;
println$ a;
println$ "=" * a.len.int;
println$ "";
elif c == "h1" do
println$ "";
match mode with
| `Code () => emit_code();
| _ => ;
endmatch;
a = code_markup a;
println$ a;
println$ "=" * a.len.int;
println$ "";
elif c == "h2" do
a = code_markup a;
println$ "";
match mode with
| `Code => emit_code();
| _ => ;
endmatch;
println$ a;
println$ "-" * a.len.int;
println$ "";
elif c == "image" do
println$ "";
match mode with
| `Code => emit_code();
| _ => ;
endmatch;
println$ "";
println$ ".. image:: " + a;
println$ "";
elif c == "tangle" do
println$ "";
var lexer = lexer_from_filename a;
prefix = ".. code-block:: "+lexer + "\n\n";
prefix += "";
if lexer in ("c","cpp","felix","fpc") do
prefix += " //[" + a + "]\n";
elif lexer == "python" do
prefix += " #["+a+"]\n";
done
mode = (#`Code) :>> mode_t;
else
match mode with
| `Code => emit_code();
| _ => ;
endmatch;
done
| None =>
match mode with
| `Doc =>
println$ code_markup line;
| `Code => code_buf = line ! code_buf;
endmatch;
endmatch;
done
if not code_buf.is_empty call emit_code();
return out;
}
include "std/felix/flx_cp";
var dir = "src/packages";
var regex = "(.*).fdoc";
var target = "doc/packages/${1}.rst";
var live = true;
var verbose = true;
gen sandr (src: string, dst:string) =
{
var text = load src;
var result = process_file (text);
result = "Package: " + src + "\n\n"+result;
save (dst, result);
return true;
}
var filere = Re2::RE2 regex;
CopyFiles::processfiles sandr (dir, filere, target, live, verbose);
System::exit(0);