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 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(); }