mirror of https://github.com/marrub--/zscript-doc
add glossary tree generator
parent
2a712d6933
commit
d9758b1879
|
@ -0,0 +1,50 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
## Distributed under the CC0 public domain license.
|
||||||
|
## Originally by Alison Sanderson.
|
||||||
|
## <https://creativecommons.org/publicdomain/zero/1.0/legalcode>
|
||||||
|
## TreeGen: Generates the glossary files for classes.
|
||||||
|
|
||||||
|
require "./tools/zsclasstree.rb"
|
||||||
|
|
||||||
|
DIR = ARGV.shift
|
||||||
|
VER = ARGV.shift
|
||||||
|
|
||||||
|
si = ClassSiphon.new DIR
|
||||||
|
|
||||||
|
f = open "glossary-classes.md", "wb"
|
||||||
|
f.puts <<_end_
|
||||||
|
# Classes
|
||||||
|
|
||||||
|
Here is a full tree of all classes in ZScript as of GZDoom #{VER}. There are #{si.classes.count + 1} classes total.
|
||||||
|
|
||||||
|
```
|
||||||
|
Object
|
||||||
|
_end_
|
||||||
|
|
||||||
|
si.print_classes f
|
||||||
|
|
||||||
|
f.puts <<_end_
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- EOF -->
|
||||||
|
_end_
|
||||||
|
|
||||||
|
f = open "glossary-structures.md", "wb"
|
||||||
|
f.puts <<_end_
|
||||||
|
# Structures
|
||||||
|
|
||||||
|
Here is a full list of all structures in ZScript as of GZDoom #{VER}. There are #{si.structs.count} structures total. Note that some of these are merely implementation details and should not be used in code.
|
||||||
|
|
||||||
|
```
|
||||||
|
Struct
|
||||||
|
_end_
|
||||||
|
|
||||||
|
si.print_structs f
|
||||||
|
|
||||||
|
f.puts <<_end_
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- EOF -->
|
||||||
|
_end_
|
||||||
|
|
||||||
|
## EOF
|
|
@ -6,84 +6,102 @@
|
||||||
|
|
||||||
require 'set'
|
require 'set'
|
||||||
|
|
||||||
$c = {}
|
class ClassSiphon
|
||||||
$s = Set[]
|
attr_reader :structs, :classes, :clstree, :strtree, :caps
|
||||||
$st = Set[]
|
|
||||||
$cap = {}
|
|
||||||
|
|
||||||
def procm m
|
def initialize dirs
|
||||||
k = (m[1] or "Object").strip
|
@subcls = {}
|
||||||
v = m[0].strip
|
@classes = Set[]
|
||||||
|
@structs = Set[]
|
||||||
|
@caps = {}
|
||||||
|
|
||||||
$cap[k.upcase] = k; k = k.upcase
|
Dir.glob dirs do |f| proc_file File.read f end
|
||||||
$cap[v.upcase] = v; v = v.upcase
|
|
||||||
|
|
||||||
return if k == v
|
@clstree = make_tree "OBJECT", @subcls["OBJECT"]
|
||||||
$c[k] ? $c[k] << v : $c[k] = [v]
|
@strtree = @structs.map {|type| [type, nil]}
|
||||||
raise "duplicate class #{v}" if $s === v
|
|
||||||
$s << v
|
|
||||||
end
|
|
||||||
|
|
||||||
def procs m
|
@classes.freeze
|
||||||
cl = m[0]
|
@structs.freeze
|
||||||
$cap[cl.upcase] = cl
|
@clstree.freeze
|
||||||
$st << [cl.upcase]
|
@strtree.freeze
|
||||||
end
|
@caps.freeze
|
||||||
|
end
|
||||||
|
|
||||||
def procf fp
|
def print_classes out, filter = []
|
||||||
t = fp.read
|
print_tree out, filter, "OBJECT", clstree
|
||||||
t.gsub! /\/\*(?!\*\/)+\*\//m, ''
|
end
|
||||||
t.gsub! /\/\/.+/, ''
|
|
||||||
sc = t.scan /^class\s*(\w*)[\s\w]+(?::\s+(\w*))?/
|
|
||||||
sc.each do |cl| procm cl end unless sc.empty?
|
|
||||||
sc = t.scan /^struct\s*(\w*)/
|
|
||||||
sc.each do |cl| procs cl end unless sc.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
dir = ARGV.shift
|
def print_structs out, filter = []
|
||||||
|
print_tree out, filter, "STRUCT", strtree
|
||||||
|
end
|
||||||
|
|
||||||
Dir.glob dir do |item|
|
private
|
||||||
procf open item, "rt"
|
def add_class m
|
||||||
end
|
ctype = m[0] .strip
|
||||||
|
cbase = (m[1] or "Object").strip
|
||||||
|
type = ctype.upcase
|
||||||
|
base = cbase.upcase
|
||||||
|
@caps[type] = ctype
|
||||||
|
@caps[base] = cbase
|
||||||
|
|
||||||
$s1 = Set[]
|
if base != type
|
||||||
|
if @subcls[base]
|
||||||
|
@subcls[base] << type
|
||||||
|
else
|
||||||
|
@subcls[base] = [type]
|
||||||
|
end
|
||||||
|
raise "duplicate class #{type}" if @classes === type
|
||||||
|
@classes << type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def procc bcl, t
|
def add_struct m
|
||||||
raise "duplicate class #{bcl}" if $s1 === bcl
|
ctype = m[0]
|
||||||
$s1 << bcl
|
type = ctype.upcase
|
||||||
return nil unless t
|
@caps[type] = ctype
|
||||||
m = {}
|
@structs << type
|
||||||
for cl in t do m[cl] = procc cl, $c[cl] end
|
end
|
||||||
m
|
|
||||||
end
|
|
||||||
|
|
||||||
ft = procc("OBJECT", $c["OBJECT"])
|
def proc_file f
|
||||||
|
f.gsub! /\/\*(?!\*\/)+\*\//m, ""
|
||||||
|
f.gsub! /\/\/.+/, ""
|
||||||
|
f.scan(/^class\s*(\w*)[\s\w]+(?::\s+(\w*))?/).each {|m| add_class m}
|
||||||
|
f.scan(/^struct\s*(\w*)/) .each {|m| add_struct m}
|
||||||
|
end
|
||||||
|
|
||||||
def printc bcl, t, tab = ""
|
# work our way down the subclasses recursively, making them into a tree structure
|
||||||
return unless t
|
def make_tree bcl, subs
|
||||||
return if ARGV.include? bcl
|
return nil unless subs
|
||||||
|
node = {}
|
||||||
|
subs.each do |cl| node[cl] = make_tree cl, @subcls[cl] end
|
||||||
|
node
|
||||||
|
end
|
||||||
|
|
||||||
t = t.map do |k, v| [k, v] end
|
def print_tree out, filter, base, tree, tab = ""
|
||||||
t.sort!
|
return if !tree or filter.include? base
|
||||||
|
|
||||||
for k, v in t
|
tree = tree.map do |type, base| [type, base] end
|
||||||
l = k == t[-1][0]
|
tree.sort!
|
||||||
|
|
||||||
s = tab.clone
|
for type, base in tree
|
||||||
s << (l ? "└" : "├")
|
last = type == tree[-1][0]
|
||||||
s << " "
|
sep = last ? "└ " : "├ "
|
||||||
s << $cap[k]
|
nxt = last ? " " : "│ "
|
||||||
|
|
||||||
puts s
|
out.puts tab + sep + @caps[type]
|
||||||
|
|
||||||
printc k, v, l ? tab + " " : tab + "│ "
|
print_tree out, filter, type, base, tab + nxt
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
raise "missing classes: #{($s - $s1).to_a}" unless ($s - $s1).empty?
|
if __FILE__ == $0
|
||||||
|
in_dirs = ARGV.shift
|
||||||
|
filters = ARGV
|
||||||
|
|
||||||
puts "Object"
|
si = ClassSiphon.new in_dirs
|
||||||
printc "OBJECT", ft
|
puts "Object"; si.print_classes STDOUT, filters
|
||||||
|
puts "Struct"; si.print_structs STDOUT, filters
|
||||||
|
end
|
||||||
|
|
||||||
puts "Struct"
|
## EOF
|
||||||
printc "STRUCT", $st
|
|
||||||
|
|
Loading…
Reference in New Issue