/// <summary> /// Accepts between <code>min</code> and <code>max</code> (including both) concatenated /// repetitions of the language of the given automaton. /// </summary> /// <param name="a">The automaton.</param> /// <param name="min">The minimum concatenated repetitions of the language of the given /// automaton.</param> /// <param name="max">The maximum concatenated repetitions of the language of the given /// automaton.</param> /// <returns> /// Returns an automaton that accepts between <code>min</code> and <code>max</code> /// (including both) concatenated repetitions of the language of the given automaton. /// </returns> /// <remarks> /// Complexity: linear in number of states and in <code>min</code> and <code>max</code>. /// </remarks> 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 = a.Clone(); } else { var @as = new List <Automaton>(); while (min-- > 0) { @as.Add(a); } b = BasicOperations.Concatenate(@as); } if (max > 0) { Automaton d = a.Clone(); while (--max > 0) { Automaton c = 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.IsDeterministic = false; b.ClearHashCode(); b.CheckMinimizeAlways(); } return(b); }
private Automaton ToAutomaton( IDictionary <string, Automaton> automata, IAutomatonProvider automatonProvider, bool minimize) { IList <Automaton> list; Automaton a = null; switch (kind) { case Kind.RegexpUnion: list = new List <Automaton>(); this.FindLeaves(exp1, Kind.RegexpUnion, list, automata, automatonProvider, minimize); this.FindLeaves(exp2, Kind.RegexpUnion, list, automata, automatonProvider, minimize); a = BasicOperations.Union(list); a.Minimize(); break; case Kind.RegexpConcatenation: list = new List <Automaton>(); this.FindLeaves(exp1, Kind.RegexpConcatenation, list, automata, automatonProvider, minimize); this.FindLeaves(exp2, Kind.RegexpConcatenation, list, automata, automatonProvider, minimize); a = BasicOperations.Concatenate(list); a.Minimize(); break; case Kind.RegexpIntersection: a = exp1.ToAutomaton(automata, automatonProvider, minimize) .Intersection(exp2.ToAutomaton(automata, automatonProvider, minimize)); a.Minimize(); break; case Kind.RegexpOptional: a = exp1.ToAutomaton(automata, automatonProvider, minimize).Optional(); a.Minimize(); break; case Kind.RegexpRepeat: a = exp1.ToAutomaton(automata, automatonProvider, minimize).Repeat(); a.Minimize(); break; case Kind.RegexpRepeatMin: a = exp1.ToAutomaton(automata, automatonProvider, minimize).Repeat(min); a.Minimize(); break; case Kind.RegexpRepeatMinMax: a = exp1.ToAutomaton(automata, automatonProvider, minimize).Repeat(min, max); a.Minimize(); break; case Kind.RegexpComplement: a = exp1.ToAutomaton(automata, automatonProvider, minimize).Complement(); a.Minimize(); break; case Kind.RegexpChar: a = BasicAutomata.MakeChar(c); break; case Kind.RegexpCharRange: a = BasicAutomata.MakeCharRange(from, to); break; case Kind.RegexpAnyChar: { a = this.anyCharAlphabet != null?BasicAutomata.MakeCharSet(this.anyCharAlphabet) : BasicAutomata.MakeAnyChar(); break; } case Kind.RegexpEmpty: a = BasicAutomata.MakeEmpty(); break; case Kind.RegexpString: a = BasicAutomata.MakeString(s); break; case Kind.RegexpAnyString: a = BasicAutomata.MakeAnyString(); break; case Kind.RegexpAutomaton: Automaton aa = null; if (automata != null) { automata.TryGetValue(s, out aa); } if (aa == null && automatonProvider != null) { try { aa = automatonProvider.GetAutomaton(s); } catch (IOException e) { throw new ArgumentException(string.Empty, e); } } if (aa == null) { throw new ArgumentException("'" + s + "' not found"); } a = aa.Clone(); // Always clone here (ignore allowMutate). break; case Kind.RegexpInterval: a = BasicAutomata.MakeInterval(min, max, digits); break; } return(a); }
/// <summary> /// Accepts between <code>min</code> and <code>max</code> (including both) concatenated /// repetitions of the language of the given automaton. /// </summary> /// <param name="a">The automaton.</param> /// <param name="min">The minimum concatenated repetitions of the language of the given /// automaton.</param> /// <param name="max">The maximum concatenated repetitions of the language of the given /// automaton.</param> /// <returns> /// Returns an automaton that accepts between <code>min</code> and <code>max</code> /// (including both) concatenated repetitions of the language of the given automaton. /// </returns> /// <remarks> /// Complexity: linear in number of states and in <code>min</code> and <code>max</code>. /// </remarks> 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 = a.Clone(); } else { var @as = new List<Automaton>(); while (min-- > 0) { @as.Add(a); } b = BasicOperations.Concatenate(@as); } if (max > 0) { Automaton d = a.Clone(); while (--max > 0) { Automaton c = 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.IsDeterministic = false; b.ClearHashCode(); b.CheckMinimizeAlways(); } return b; }
private Automaton ToAutomaton( IDictionary <string, Automaton> automata, IAutomatonProvider automatonProvider, bool minimize) { IList <Automaton> list; Automaton a = null; switch (this.Kind) { case Kind.RegexpUnion: list = new List <Automaton>(); this.FindLeaves(Expr1, Kind.RegexpUnion, list, automata, automatonProvider, minimize); this.FindLeaves(Expr2, Kind.RegexpUnion, list, automata, automatonProvider, minimize); a = BasicOperations.Union(list); a.Minimize(); break; case Kind.RegexpConcatenation: list = new List <Automaton>(); this.FindLeaves(Expr1, Kind.RegexpConcatenation, list, automata, automatonProvider, minimize); this.FindLeaves(Expr2, Kind.RegexpConcatenation, list, automata, automatonProvider, minimize); a = BasicOperations.Concatenate(list); a.Minimize(); break; case Kind.RegexpIntersection: a = Expr1.ToAutomaton(automata, automatonProvider, minimize) .Intersection(Expr2.ToAutomaton(automata, automatonProvider, minimize)); a.Minimize(); break; case Kind.RegexpOptional: a = Expr1.ToAutomaton(automata, automatonProvider, minimize).Optional(); a.Minimize(); break; case Kind.RegexpRepeat: a = Expr1.ToAutomaton(automata, automatonProvider, minimize).Repeat(); a.Minimize(); break; case Kind.RegexpRepeatMin: a = Expr1.ToAutomaton(automata, automatonProvider, minimize).Repeat(Min); a.Minimize(); break; case Kind.RegexpRepeatMinMax: a = Expr1.ToAutomaton(automata, automatonProvider, minimize).Repeat(Min, Max); a.Minimize(); break; case Kind.RegexpComplement: a = Expr1.ToAutomaton(automata, automatonProvider, minimize).Complement(); a.Minimize(); break; case Kind.RegexpChar: a = BasicAutomata.MakeChar(this.Char); break; case Kind.RegexpCharRange: a = BasicAutomata.MakeCharRange(FromChar, ToChar); break; case Kind.RegexpAnyChar: a = BasicAutomata.MakeAnyChar(); break; case Kind.RegexpEmpty: a = BasicAutomata.MakeEmpty(); break; case Kind.RegexpString: a = BasicAutomata.MakeString(SourceRegExpr); break; case Kind.RegexpAnyString: a = BasicAutomata.MakeAnyString(); break; case Kind.RegexpAutomaton: Automaton aa = null; if (automata != null) { automata.TryGetValue(SourceRegExpr, out aa); } if (aa == null && automatonProvider != null) { try { aa = automatonProvider.GetAutomaton(SourceRegExpr); } catch (IOException e) { throw new ArgumentException(string.Empty, e); } } if (aa == null) { throw new ArgumentException("'" + SourceRegExpr + "' not found"); } a = aa.Clone(); // Always clone here (ignore allowMutate). break; case Kind.RegexpInterval: a = BasicAutomata.MakeInterval(Min, Max, Digits); break; } return(a); }