public static FA Optional(FA expr, int accept = -1) { var result = expr.Clone(); var f = result.FirstAcceptingState; f.AcceptSymbol = accept; result.EpsilonTransitions.Add(f); return(result); }
public static FA Concat(IEnumerable <FA> exprs, int accept = -1) { FA result = null, left = null, right = null; foreach (var val in exprs) { if (null == val) { continue; } //Debug.Assert(null != val.FirstAcceptingState); var nval = val.Clone(); //Debug.Assert(null != nval.FirstAcceptingState); if (null == left) { if (null == result) { result = nval; } left = nval; //Debug.Assert(null != left.FirstAcceptingState); continue; } if (null == right) { right = nval; } //Debug.Assert(null != left.FirstAcceptingState); nval = right.Clone(); _Concat(left, nval); right = null; left = nval; //Debug.Assert(null != left.FirstAcceptingState); } if (null != right) { right.FirstAcceptingState.AcceptSymbol = accept; } else { result.FirstAcceptingState.AcceptSymbol = accept; } return(result); }
public static FA CaseInsensitive(FA expr, int accept = -1) { var result = expr.Clone(); var closure = new List <FA>(); result.FillClosure(closure); for (int ic = closure.Count, i = 0; i < ic; ++i) { var fa = closure[i]; var t = new List <KeyValuePair <KeyValuePair <int, int>, FA> >(fa.InputTransitions); fa.InputTransitions.Clear(); foreach (var trns in t) { var f = char.ConvertFromUtf32(trns.Key.Key); var l = char.ConvertFromUtf32(trns.Key.Value); if (char.IsLower(f, 0)) { if (!char.IsLower(l, 0)) { throw new NotSupportedException("Attempt to make an invalid range case insensitive"); } fa.InputTransitions.Add(trns.Key, trns.Value); f = f.ToUpperInvariant(); l = l.ToUpperInvariant(); fa.InputTransitions.Add(new KeyValuePair <int, int>(char.ConvertToUtf32(f, 0), char.ConvertToUtf32(l, 0)), trns.Value); } else if (char.IsUpper(f, 0)) { if (!char.IsUpper(l, 0)) { throw new NotSupportedException("Attempt to make an invalid range case insensitive"); } fa.InputTransitions.Add(trns.Key, trns.Value); f = f.ToLowerInvariant(); l = l.ToLowerInvariant(); fa.InputTransitions.Add(new KeyValuePair <int, int>(char.ConvertToUtf32(f, 0), char.ConvertToUtf32(l, 0)), trns.Value); } else { fa.InputTransitions.Add(trns.Key, trns.Value); } } } return(result); }
public static FA Repeat(FA expr, int minOccurs = -1, int maxOccurs = -1, int accept = -1) { expr = expr.Clone(); if (minOccurs > 0 && maxOccurs > 0 && minOccurs > maxOccurs) { throw new ArgumentOutOfRangeException(nameof(maxOccurs)); } FA result; switch (minOccurs) { case -1: case 0: switch (maxOccurs) { case -1: case 0: //return Repeat(Optional(expr, accept),1,0,accept); result = new FA(); var final = new FA(true, accept); final.EpsilonTransitions.Add(result); foreach (var afa in expr.FillAcceptingStates()) { afa.IsAccepting = false; afa.EpsilonTransitions.Add(final); } result.EpsilonTransitions.Add(expr); result.EpsilonTransitions.Add(final); //Debug.Assert(null != result.FirstAcceptingState); return(result); case 1: result = Optional(expr, accept); //Debug.Assert(null != result.FirstAcceptingState); return(result); default: var l = new List <FA>(); expr = Optional(expr); l.Add(expr); for (int i = 1; i < maxOccurs; ++i) { l.Add(expr.Clone()); } result = Concat(l, accept); //Debug.Assert(null != result.FirstAcceptingState); return(result); } case 1: switch (maxOccurs) { case -1: case 0: result = new FA(); var final = new FA(true, accept); final.EpsilonTransitions.Add(result); foreach (var afa in expr.FillAcceptingStates()) { afa.IsAccepting = false; afa.EpsilonTransitions.Add(final); } result.EpsilonTransitions.Add(expr); //Debug.Assert(null != result.FirstAcceptingState); return(result); case 1: //Debug.Assert(null != expr.FirstAcceptingState); return(expr); default: result = Concat(new FA[] { expr, Repeat(expr.Clone(), 0, maxOccurs - 1) }, accept); //Debug.Assert(null != result.FirstAcceptingState); return(result); } default: switch (maxOccurs) { case -1: case 0: result = Concat(new FA[] { Repeat(expr, minOccurs, minOccurs, accept), Repeat(expr, 0, 0, accept) }, accept); //Debug.Assert(null != result.FirstAcceptingState); return(result); case 1: throw new ArgumentOutOfRangeException(nameof(maxOccurs)); default: if (minOccurs == maxOccurs) { var l = new List <FA>(); l.Add(expr); //Debug.Assert(null != expr.FirstAcceptingState); for (int i = 1; i < minOccurs; ++i) { var e = expr.Clone(); //Debug.Assert(null != e.FirstAcceptingState); l.Add(e); } result = Concat(l, accept); //Debug.Assert(null != result.FirstAcceptingState); return(result); } result = Concat(new FA[] { Repeat(expr.Clone(), minOccurs, minOccurs, accept), Repeat(Optional(expr.Clone()), maxOccurs - minOccurs, maxOccurs - minOccurs, accept) }, accept); //Debug.Assert(null != result.FirstAcceptingState); return(result); } } // should never get here throw new NotImplementedException(); }