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