Пример #1
0
        public override Mode Match(string[] objs, ref MetaInfo meta, bool partial = true)
        {
            if (meta == null)
            {
                throw new ArgumentNullException(nameof(meta));
            }
            var res  = new Mode().SetName(Name);
            var left = objs.Length - meta.Count;

            if (left == 0)
            {
                return(_atleast == 0 ? res : null);
            }
            meta.Branch();
            Mode r;
            int  idx = 0;

            if (_atmost > 0)
            {
                while (true)
                {
                    if (idx >= _atmost)
                    {
                        break;
                    }
                    r = base.Match(objs, ref meta, true);
                    if (r == null)
                    {
                        break;
                    }
                    res.AddRange(r);
                    ++idx;
                }
            }
            else
            {
                while (true)
                {
                    r = base.Match(objs, ref meta, true);
                    if (r == null)
                    {
                        break;
                    }
                    res.AddRange(r);
                    ++idx;
                }
            }
#if DEBUG
            Console.WriteLine($"{name} <= {res.Dump()}");
#endif
            if (idx < _atleast)
            {
                meta.Rollback();
                return(null);
            }
            meta.Pull();
            return(res);
        }
Пример #2
0
        public override Mode Match(string[] objs, ref MetaInfo meta, bool partial = true)
        {
            if (meta == null)
            {
                throw new ArgumentNullException(nameof(meta));
            }
#if DEBUG
            Console.WriteLine($"{this.name} ");
#endif

            var res    = new Mode().SetName(Name);
            var hasRes = false;

            foreach (var possibility in Possibilities)
            {
                meta.Branch();                 // Make a branch in case of resetting.
                foreach (var thing in possibility)
                {
                    var  history = (meta.Count, thing.Name);
                    Mode r;

                    if (thing.HasRecur)
                    {
                        if (meta.Trace.Contains(history))
                        {
                            Console.WriteLine("Found Left Recursion. Dealed.");
                            r = null;
                        }
                        else
                        {
                            meta.Trace.Push(history);
                            r = thing.Match(objs, ref meta, true);
                        }
                    }
                    else
                    {
                        // DEBUG View: the trace of parsing.
#if DEBUG
                        meta.trace.Push(history);
#endif
                        r = thing.Match(objs, ref meta, true);
                    }

                    if (r == null)
                    {
                        // Do not match current possibility, then rollback.
                        res.Clear();
                        meta.Rollback();
                        goto ContinueForNewPossibility;
                    }

                    if (thing is Seq)
                    {
                        res.AddRange(r);
                    }
                    else
                    {
                        res.Add(r);
                    }

#if DEBUG
                    Console.WriteLine($"{thing.name} <= {r.Dump()}");
#endif
                }
#if DEBUG
                Console.WriteLine($"RETURN from {this.name} ");
#endif
                hasRes = true;
                break;
ContinueForNewPossibility:
                ;
            }
            if (!hasRes)
            {
#if DEBUG
                Console.WriteLine($"RETURN None from {this.name} ");
#endif
                return(null);
            }
            meta.Pull();
            var left = objs.Length - meta.Count;
            if (partial || left == 0)
            {
#if DEBUG
                Console.WriteLine($"RETURN Some from {this.name}");
#endif
                return(res);
            }
#if DEBUG
            Console.WriteLine($"RETURN None from {this.name} (No partial and do not match all)");
#endif
            return(null);
        }