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.