Created
March 1, 2019 10:56
-
-
Save acple/9f511d5e6474111e42b4d54cdeae97c7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using ParsecSharp; | |
namespace ParsecSharp.Utils | |
{ | |
public class DebugOutputStream<TToken> : IParsecStateStream<TToken> | |
{ | |
public enum MoveState { Backward, Stay, Forward } | |
private class Cursor | |
{ | |
private IPosition position; | |
public Cursor(IPosition position) | |
{ | |
this.position = position; | |
} | |
public MoveState MoveTo(IPosition next) | |
{ | |
var compare = next.CompareTo(this.position); | |
this.position = next; | |
return (compare < 0) ? MoveState.Backward : (0 < compare) ? MoveState.Forward : MoveState.Stay; | |
} | |
} | |
private readonly IParsecStateStream<TToken> _state; | |
private readonly Action<IParsecState<TToken>, MoveState> _getCurrent; | |
private readonly Action<IParsecState<TToken>, bool> _getNext; | |
private readonly Lazy<IParsecStateStream<TToken>> _next; | |
private readonly Cursor cursor; // mutable | |
public TToken Current => this.GetCurrent(); | |
public bool HasValue => this._state.HasValue; | |
public IPosition Position => this._state.Position; | |
public IParsecStateStream<TToken> Next => this.GetNext(); | |
public DebugOutputStream(IParsecStateStream<TToken> state) : this(state, StdOutGetCurrent, StdOutGetNext) | |
{ } | |
public DebugOutputStream(IParsecStateStream<TToken> state, Action<IParsecState<TToken>, MoveState> getCurrent) : this(state, getCurrent, getNext: null) | |
{ } | |
public DebugOutputStream(IParsecStateStream<TToken> state, Action<IParsecState<TToken>, bool> getNext) : this(state, getCurrent: null, getNext) | |
{ } | |
public DebugOutputStream(IParsecStateStream<TToken> state, Action<IParsecState<TToken>, MoveState> getCurrent, Action<IParsecState<TToken>, bool> getNext) : this(state, getCurrent, getNext, new Cursor(state.Position)) | |
{ } | |
private DebugOutputStream(IParsecStateStream<TToken> state, Action<IParsecState<TToken>, MoveState> getCurrent, Action<IParsecState<TToken>, bool> getNext, Cursor cursor) | |
{ | |
this._state = state; | |
this._getCurrent = getCurrent; | |
this._getNext = getNext; | |
this.cursor = cursor; | |
this._next = new Lazy<IParsecStateStream<TToken>>(() => new DebugOutputStream<TToken>(this._state.Next, this._getCurrent, this._getNext, cursor)); | |
} | |
private TToken GetCurrent() | |
{ | |
this._getCurrent?.Invoke(this._state, this.cursor.MoveTo(this._state.Position)); | |
return this._state.Current; | |
} | |
private IParsecStateStream<TToken> GetNext() | |
{ | |
this._getNext?.Invoke(this._state.Next, !this._next.IsValueCreated); | |
return this._next.Value; | |
} | |
public bool Equals(IParsecState<TToken> other) | |
=> ReferenceEquals(this, other); | |
public void Dispose() | |
=> this._state.Dispose(); | |
public static void StdOutGetCurrent(IParsecState<TToken> state, MoveState move) | |
=> Console.WriteLine(DefaultGetCurrentToString(state, move)); | |
public static string DefaultGetCurrentToString(IParsecState<TToken> state, MoveState move) | |
=> $"{((move is MoveState.Backward) ? "<<<" : (move is MoveState.Forward) ? ">>>" : "===")} GetCurrent ({state.Position}): {{ Current = '{state.Current?.ToString() ?? "null"}' }}"; | |
public static void StdOutGetNext(IParsecState<TToken> state, bool isFirstCall) | |
=> Console.WriteLine(DefaultGetNextToString(state, isFirstCall)); | |
public static string DefaultGetNextToString(IParsecState<TToken> state, bool isFirstCall) | |
=> $"GetNext ({state.Position}): {{ IsFirstCall = {isFirstCall}, EndOfInput = {!state.HasValue} }}"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment