83 lines
1.8 KiB
Julia
83 lines
1.8 KiB
Julia
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
|
|
|
const InnerConfig = Dict{Char, Vector{Function}}
|
|
|
|
mutable struct Config
|
|
breaking::Vector{Function}
|
|
regular::Vector{Function}
|
|
inner::InnerConfig
|
|
end
|
|
|
|
Config() = Config(Function[], Function[], InnerConfig())
|
|
|
|
const META = Dict{Function, Dict{Symbol, Any}}()
|
|
|
|
getset(coll, key, default) = coll[key] = get(coll, key, default)
|
|
|
|
meta(f) = getset(META, f, Dict{Symbol, Any}())
|
|
|
|
breaking!(f) = meta(f)[:breaking] = true
|
|
breaking(f) = get(meta(f), :breaking, false)
|
|
|
|
triggers!(f, ts) = meta(f)[:triggers] = Set{Char}(ts)
|
|
triggers(f) = get(meta(f), :triggers, Set{Char}())
|
|
|
|
# Macros
|
|
|
|
isexpr(x::Expr, ts...) = x.head in ts
|
|
isexpr(x::T, ts...) where {T} = T in ts
|
|
|
|
macro breaking(ex)
|
|
isexpr(ex, :->) || error("invalid @breaking form, use ->")
|
|
b, def = ex.args
|
|
if b
|
|
quote
|
|
f = $(esc(def))
|
|
breaking!(f)
|
|
f
|
|
end
|
|
else
|
|
esc(def)
|
|
end
|
|
end
|
|
|
|
macro trigger(ex)
|
|
isexpr(ex, :->) || error("invalid @triggers form, use ->")
|
|
ts, def = ex.args
|
|
quote
|
|
f = $(esc(def))
|
|
triggers!(f, $ts)
|
|
f
|
|
end
|
|
end
|
|
|
|
# Construction
|
|
|
|
function config(parsers::Function...)
|
|
c = Config()
|
|
for parser in parsers
|
|
ts = triggers(parser)
|
|
if breaking(parser)
|
|
push!(c.breaking, parser)
|
|
elseif !isempty(ts)
|
|
for t in ts
|
|
push!(getset(c.inner, t, Function[]), parser)
|
|
end
|
|
else
|
|
push!(c.regular, parser)
|
|
end
|
|
end
|
|
return c
|
|
end
|
|
|
|
# Flavour definitions
|
|
|
|
const flavors = Dict{Symbol, Config}()
|
|
|
|
macro flavor(name, features)
|
|
quote
|
|
const $(esc(name)) = config($(map(esc,features.args)...))
|
|
flavors[$(Expr(:quote, name))] = $(esc(name))
|
|
end
|
|
end
|