public override Parser <TInput> VisitBest(BestParser <TInput> parser) { if (state.State == 0) { int minLength = -1; int maxLength = -1; int bestParser = -1; // figure out which parser will consume most input for (int i = 0; i < parser.Parsers.Count; i++) { var p = parser.Parsers[i]; var length = scanner.Scan(p, state.InputStart); if (length > maxLength) { maxLength = length; bestParser = i; } else if (length < minLength) { minLength = length; } } if (maxLength >= 0) { state.State = 1; state.NextOutputStart = state.OutputStart; return(parser.Parsers[bestParser]); } else { state.InputLength = -1; return(null); } } else { state.InputLength = state.LastResult; return(null); } }
/// <summary> /// Parse using a state machine, does not use the call stack. /// </summary> public SearchResult Search(Parser <TInput> parser, int start, bool initialPrevWasMissing) { this.state = default(SearchState); this.stackPosition = -1; this.prevWasMissing = initialPrevWasMissing; Push(parser, start, initialPrevWasMissing); Parser <TInput> nextParser = null; while (true) { if (this.state.Parser.IsHidden) { this.state.InputLength = scanner.Scan(this.state.Parser, this.state.InputStart); nextParser = null; } else { if (this.state.State == 0) { beforeAction(this.state.Parser, source, this.state.InputStart, this.prevWasMissing); } nextParser = this.state.Parser.Accept(this); } if (nextParser != null) { Push(nextParser, inputStart: this.state.InputStart + this.state.InputLength, prevWasMissing: this.prevWasMissing); } else { var length = this.state.InputLength; this.afterAction?.Invoke(this.state.Parser); if (this.stackPosition == 0) { return(new SearchResult(length, this.prevWasMissing)); } else { Pop(); this.state.LastResult = length; } } } }