Deve ser possível usar o Automa.jl para criar um DFA e percorrê-lo aleatoriamente. O Automa usa uma sintaxe mais simples que o PCRE, portanto, o idioma que você pode descrever deve ser regular.
Eu juntei rapidamente o seguinte, com base principalmente no código dot.jl
:
julia> function rand_re(machine::Automa.Machine)
out = IOBuffer()
node = machine.start
while true
if node.state ∈ machine.final_states
(rand() ≤ 1 / (length(node.edges) + 1)) && break
end
edge, node = rand(node.edges)
label = rand(collect(edge.labels))
print(out, Char(label))
end
return String(take!(out))
end
rand_re (generic function with 1 method)
julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a6bbb"
julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a9b"
julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a3aa"
julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a1a"
julia> rand_re(Automa.compile(re"a[0-9][ab]+"))
"a5ba"
A ressalva é que o Automa usa conjuntos codificados em bytes para etiquetas de borda, portanto, mais cuidados devem ser tomados onde eu apenas escrevo Char(label)
.
Como os estados finais ainda podem ter arestas de saída, optei por tratar a parada e cada aresta com probabilidade uniforme. Eu acho que isso provavelmente terá o efeito de que termos potencialmente infinitos serão muito curtos ou muito longos; google "amostradores Boltzmann" para saber como resolver isso (não confunda com amostragem de uma distribuição Boltzmann!), mas a solução está matematicamente envolvida.