94 lines
2.4 KiB
Typst
94 lines
2.4 KiB
Typst
#import "uml.typ"
|
|
|
|
#let parse-args(data) = {
|
|
let args = data.split(",").map(a => a.trim()).filter(a => a.len() != 0)
|
|
let res
|
|
if ":" in data {
|
|
res = (:)
|
|
} else {
|
|
res = ()
|
|
}
|
|
|
|
for arg in args {
|
|
let parts = arg.split(":")
|
|
let arg-name = none
|
|
let arg-type
|
|
if parts.len() == 1 {
|
|
if type(res) == dictionary {
|
|
panic("Cannot mix named and unnamed arguments")
|
|
}
|
|
arg-type = parts.first().trim()
|
|
res.push(arg-type)
|
|
} else {
|
|
arg-name = parts.first().trim()
|
|
arg-type = parts.slice(1).join(":").trim()
|
|
res.insert(arg-name, arg-type)
|
|
}
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
#let parse(data) = {
|
|
let elements = ()
|
|
|
|
if type(data) == raw or type(data) == content {
|
|
data = data.text
|
|
}
|
|
|
|
let classes = data.matches(regex("(?ms)(abstract class|class|interface) (.*?)\s*\{(.*?)\}"))
|
|
|
|
for class in classes {
|
|
let family-name = class.captures.first()
|
|
let family = (
|
|
class: none,
|
|
"abstract class": uml.abstract,
|
|
"interface": uml.interface,
|
|
"enum": uml.enum,
|
|
).at(family-name)
|
|
|
|
let name = class.captures.at(1)
|
|
let class-data = class.captures.last().trim()
|
|
|
|
let members = class-data.matches(regex("(?m)^\s*(.*?)\s*(:\s*([^:]*?))?$")).filter(m => m.text.len() != 0)
|
|
let attributes = ()
|
|
let methods = ()
|
|
for member in members {
|
|
let member-name = member.captures.first()
|
|
let val-type = member.captures.last()
|
|
let visibility = none
|
|
|
|
if member-name.starts-with(regex("\+|-|~|#")) {
|
|
let vis = member-name.first()
|
|
member-name = member-name.slice(1)
|
|
visibility = (
|
|
"+": uml.public,
|
|
"-": uml.private,
|
|
"~": uml.package,
|
|
"#": uml.protected
|
|
).at(vis)
|
|
}
|
|
|
|
if member-name.ends-with(")") {
|
|
let func = member-name.match(regex("^(.*?)\((.*)\)$"))
|
|
member-name = func.captures.first()
|
|
let args = parse-args(func.captures.last())
|
|
methods += uml.method(member-name, visibility, val-type, args)
|
|
} else {
|
|
attributes += uml.attr(member-name, visibility, val-type)
|
|
}
|
|
}
|
|
|
|
elements += uml.class(name, family, attributes + methods)
|
|
}
|
|
|
|
let defaults = (:)
|
|
let params = data.matches(regex("(?m)^\s*@\s*(.*?)\s*=\s*(.*)\s*$"))
|
|
for param in params {
|
|
let key = param.captures.first()
|
|
let value = eval(param.captures.last(), scope: (uml: uml))
|
|
defaults.insert(key, value)
|
|
}
|
|
|
|
return uml.diagram(elements, defaults)
|
|
} |