示例#1
0
        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();
        }
示例#2
0
        internal static void EmitFAPart(FA fa, IList <int[]> prog)
        {
            //fa = fa.ToDfa();
            //fa.TrimDuplicates();
            //fa = fa.ToGnfa();
            if (fa.IsNeutral)
            {
                foreach (var efa in fa.EpsilonTransitions)
                {
                    fa = efa;
                }
            }
            var acc = fa.FillAcceptingStates();

            foreach (var afa in acc)
            {
                if (!afa.IsFinal)
                {
                    var ffa = new FA(true, afa.AcceptSymbol);
                    afa.EpsilonTransitions.Add(ffa);
                    afa.IsAccepting = false;
                }
            }
            var rendered  = new Dictionary <FA, int>();
            var swFixups  = new Dictionary <FA, int>();
            var jmpFixups = new Dictionary <FA, int>();
            var l         = new List <FA>();

            fa.FillClosure(l);
            for (int ic = l.Count, i = 0; i < ic; ++i)
            {
                var reused = false;
                var cfa    = l[i];
                if (!cfa.IsFinal)
                {
                    rendered.Add(cfa, prog.Count);
                }
                else
                {
                    foreach (var r in rendered)
                    {
                        if (r.Key.IsFinal)
                        {
                            if (r.Key.IsAccepting && cfa.AcceptSymbol == r.Key.AcceptSymbol)
                            {
                                // we can reuse this
                                rendered.Add(cfa, r.Value);
                                reused = true;
                                break;
                            }
                        }
                    }
                    if (!reused)
                    {
                        rendered.Add(cfa, prog.Count);
                    }
                }

                if (!cfa.IsFinal)
                {
                    int swfixup = prog.Count;
                    prog.Add(null);                     // switch
                    swFixups.Add(cfa, swfixup);
                }
                else
                {
#if DEBUG
                    System.Diagnostics.Debug.Assert(cfa.IsAccepting);
#endif
                    if (!reused)
                    {
                        prog.Add(new int[] { Save, 1 });                         // save
                        prog.Add(new int[] { Match, cfa.AcceptSymbol });
                    }
                }
            }
            for (int ic = l.Count, i = 0; i < ic; ++i)
            {
                var cfa = l[i];

                if (!cfa.IsFinal)
                {
                    var sw = new List <int>();
                    sw.Add(Switch);

                    var rngGrps = cfa.FillInputTransitionRangesGroupedByState();
                    foreach (var grp in rngGrps)
                    {
                        var dst = rendered[grp.Key];
                        sw.AddRange(grp.Value);
                        sw.Add(-1);
                        sw.Add(dst);
                    }
                    if (1 < sw.Count)
                    {
                        if (0 < cfa.EpsilonTransitions.Count)
                        {
                            sw.Add(-2);
                            foreach (var efa in cfa.EpsilonTransitions)
                            {
                                var dst = rendered[efa];
                                sw.Add(dst);
                            }
                        }
                    }
                    else
                    {
                        // basically a NOP. Will get removed
                        sw[0] = Jmp;
                        sw.Add(swFixups[cfa] + 1);
                    }
                    prog[swFixups[cfa]] = sw.ToArray();
                }

                var jfi = -1;
                if (jmpFixups.TryGetValue(cfa, out jfi))
                {
                    var jmp = new int[2];
                    jmp[0]    = Jmp;
                    jmp[1]    = prog.Count;
                    prog[jfi] = jmp;
                }
            }
        }