/// <summary> /// Returns an automaton that accepts between <paramref name="min"/> and /// <paramref name="max"/> (including both) concatenated repetitions of the language /// of the given automaton. /// <para/> /// Complexity: linear in number of states and in <paramref name="min"/> and /// <paramref name="max"/>. /// </summary> public static Automaton Repeat(Automaton a, int min, int max) { if (min > max) { return(BasicAutomata.MakeEmpty()); } max -= min; a.ExpandSingleton(); Automaton b; if (min == 0) { b = BasicAutomata.MakeEmptyString(); } else if (min == 1) { b = (Automaton)a.Clone(); } else { IList <Automaton> @as = new List <Automaton>(); while (min-- > 0) { @as.Add(a); } b = Concatenate(@as); } if (max > 0) { Automaton d = (Automaton)a.Clone(); while (--max > 0) { Automaton c = (Automaton)a.Clone(); foreach (State p in c.GetAcceptStates()) { p.AddEpsilon(d.initial); } d = c; } foreach (State p in b.GetAcceptStates()) { p.AddEpsilon(d.initial); } b.deterministic = false; //b.clearHashCode(); b.ClearNumberedStates(); b.CheckMinimizeAlways(); } return(b); }
/// <summary> /// Returns the longest string that is a suffix of all accepted strings and /// visits each state at most once. /// </summary> /// <returns> Common suffix. </returns> public static string GetCommonSuffix(Automaton a) { if (a.IsSingleton) // if singleton, the suffix is the string itself. { return(a.singleton); } // reverse the language of the automaton, then reverse its common prefix. Automaton r = (Automaton)a.Clone(); Reverse(r); r.Determinize(); return((new StringBuilder(SpecialOperations.GetCommonPrefix(r))).Reverse().ToString()); }
public static BytesRef GetCommonSuffixBytesRef(Automaton a) { if (a.IsSingleton) // if singleton, the suffix is the string itself. { return(new BytesRef(a.singleton)); } // reverse the language of the automaton, then reverse its common prefix. Automaton r = (Automaton)a.Clone(); Reverse(r); r.Determinize(); BytesRef @ref = SpecialOperations.GetCommonPrefixBytesRef(r); ReverseBytes(@ref); return(@ref); }
private Automaton ToAutomaton(IDictionary <string, Automaton> automata, IAutomatonProvider automaton_provider) { IList <Automaton> list; Automaton a = null; switch (kind) { case Kind.REGEXP_UNION: list = new List <Automaton>(); FindLeaves(exp1, Kind.REGEXP_UNION, list, automata, automaton_provider); FindLeaves(exp2, Kind.REGEXP_UNION, list, automata, automaton_provider); a = BasicOperations.Union(list); MinimizationOperations.Minimize(a); break; case Kind.REGEXP_CONCATENATION: list = new List <Automaton>(); FindLeaves(exp1, Kind.REGEXP_CONCATENATION, list, automata, automaton_provider); FindLeaves(exp2, Kind.REGEXP_CONCATENATION, list, automata, automaton_provider); a = BasicOperations.Concatenate(list); MinimizationOperations.Minimize(a); break; case Kind.REGEXP_INTERSECTION: a = exp1.ToAutomaton(automata, automaton_provider).Intersection(exp2.ToAutomaton(automata, automaton_provider)); MinimizationOperations.Minimize(a); break; case Kind.REGEXP_OPTIONAL: a = exp1.ToAutomaton(automata, automaton_provider).Optional(); MinimizationOperations.Minimize(a); break; case Kind.REGEXP_REPEAT: a = exp1.ToAutomaton(automata, automaton_provider).Repeat(); MinimizationOperations.Minimize(a); break; case Kind.REGEXP_REPEAT_MIN: a = exp1.ToAutomaton(automata, automaton_provider).Repeat(min); MinimizationOperations.Minimize(a); break; case Kind.REGEXP_REPEAT_MINMAX: a = exp1.ToAutomaton(automata, automaton_provider).Repeat(min, max); MinimizationOperations.Minimize(a); break; case Kind.REGEXP_COMPLEMENT: a = exp1.ToAutomaton(automata, automaton_provider).Complement(); MinimizationOperations.Minimize(a); break; case Kind.REGEXP_CHAR: a = BasicAutomata.MakeChar(c); break; case Kind.REGEXP_CHAR_RANGE: a = BasicAutomata.MakeCharRange(from, to); break; case Kind.REGEXP_ANYCHAR: a = BasicAutomata.MakeAnyChar(); break; case Kind.REGEXP_EMPTY: a = BasicAutomata.MakeEmpty(); break; case Kind.REGEXP_STRING: a = BasicAutomata.MakeString(s); break; case Kind.REGEXP_ANYSTRING: a = BasicAutomata.MakeAnyString(); break; case Kind.REGEXP_AUTOMATON: Automaton aa = null; if (automata != null) { aa = automata[s]; } if (aa == null && automaton_provider != null) { try { aa = automaton_provider.GetAutomaton(s); } catch (System.IO.IOException e) { throw new System.ArgumentException(e.ToString(), e); } } if (aa == null) { throw new System.ArgumentException("'" + s + "' not found"); } a = (Automaton)aa.Clone(); // always clone here (ignore allow_mutate) break; case Kind.REGEXP_INTERVAL: a = BasicAutomata.MakeInterval(min, max, digits); break; } return(a); }