using System.Collections.Generic;
public abstract record State(int Count);
public sealed record InitialState(int Count) : State(Count) { public InitialState() : this(0) {}}
public record StateA(int Count, string Token, int InnerCount) : State(Count) { }
public record StateB(int Count, string Token) : State(Count);
public sealed record FinalState(int Count) : State(Count);
public sealed record ErrorState(int Count) : State(Count);
const string terminalString = "stop";
IEnumerator<string> inputs = Enumerable.Range(1, 6).Select(i => "token " + i.ToString()).Concat(new [] {terminalString}).GetEnumerator();
string terminalString = "stop";
State state = new InitialState();
while (state is not FinalState && state is not ErrorState)
string token = GetNextToken();
Console.WriteLine("State = {0}", state);
var s when s.Count > maxIterations =>
new ErrorState(s.Count + 1),
new StateA(s.Count + 1, token, 0),
StateA s when s is { InnerCount : > 3 } =>
new StateB (s.Count + 1, token),
s with { Count = s.Count + 1, Token = token, InnerCount = s.InnerCount + 1 },
StateB s when s.Token == terminalString =>
new FinalState(s.Count + 1),
s with { Count = s.Count + 1, Token = token },
_ => throw new Exception($"Unknown state {state}"),
Console.WriteLine("State = {0}", state);
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}\n", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);