diff --git a/src/nfa.jl b/src/nfa.jl index 8678abd7..be35a69f 100644 --- a/src/nfa.jl +++ b/src/nfa.jl @@ -177,6 +177,18 @@ function remove_dead_nodes(nfa::NFA) push!(get!(() -> Set{NFANode}(), backrefs, t), s) end + # Automa could support null regex like `re"A" & re"B"`, but it's trouble, + # and it's useless for the user, who would probably prefer an error. + # We throw this error here and not on NFA construction so the user can visualise + # the NFA and find the error in their regex + if !haskey(backrefs, nfa.final) + error( + "NFA matches the empty set Ø, and therefore consists of only dead nodes. " * + "Automa currently does not support converting null NFAs to DFAs. " * + "Double check your regex, or inspect the NFA." + ) + end + alive = Set{NFANode}() unvisited = [nfa.final] while !isempty(unvisited) diff --git a/test/runtests.jl b/test/runtests.jl index 03cbbf47..7abe54a6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -58,6 +58,18 @@ end @test occursin(r"^Automa\.Node\(.*\)$", repr(machine.start)) end +@testset "Null Regex" begin + re = Automa.RegExp + for null_regex in [ + re"A" & re"B", + (re"B" | re"C") \ re"[A-D]", + !re.rep(re.any()), + !re"[\x00-\xff]*", + ] + @test_throws ErrorException Automa.compile(null_regex) + end +end + @testset "Determinacy" begin # see https://github.com/BioJulia/Automa.jl/issues/19 notmach(re) = Automa.machine2dot(Automa.compile(re)) != Automa.machine2dot(Automa.compile(re)) @@ -78,7 +90,7 @@ include("test09.jl") include("test10.jl") include("test11.jl") include("test12.jl") -# test13 tested functionality now removed. +include("test13.jl") include("test14.jl") include("test15.jl") include("test16.jl") diff --git a/test/test13.jl b/test/test13.jl new file mode 100644 index 00000000..6e6554d7 --- /dev/null +++ b/test/test13.jl @@ -0,0 +1,26 @@ +module Test13 + +using Automa +using Test + +# Some cases of regex I've seen fail +@testset "Test13" begin + for (regex, good_strings, bad_strings) in [ + (re"[AB]" & re"A", ["A"], ["B", "AA", "AB"]), + (re"(A|B|C|D)" \ re"[A-C]", ["D"], ["AC", "A", "B", "DD"]), + (!re"A[BC]D?E", ["ABCDE", "ABCE"], ["ABDE", "ACE", "ABE"]) + ] + for goto in (false, true) + machine = Automa.compile(regex) + @eval $(Automa.generate_validator_function(:validate, machine, goto)) + for string in good_strings + @test validate(string) === nothing + end + for string in bad_strings + @test validate(string) !== nothing + end + end + end +end + +end # module