static void Main(string[] args) { string expr = "1+a*3"; Dictionary <string, double> variables = new(); List <ITokenAcceptor <IToken> > constantAcceptors = new(); constantAcceptors.Add(new ConstantToken.Acceptor()); constantAcceptors.Add(new VariableToken.Acceptor()); List <ITokenAcceptor <IToken> > binaryAcceptors = new(); binaryAcceptors.Add(new AddToken.Acceptor()); binaryAcceptors.Add(new SubtractToken.Acceptor()); binaryAcceptors.Add(new MultiplyToken.Acceptor()); int index = 0; ITokenBuilder <IToken>? root = null; IBinaryTokenBuilder <IBinaryToken>?lastBinary = null; ITokenBuilder <IToken>? _left = null; List <ITokenAcceptor <IToken> > acceptors = constantAcceptors; while (index < expr.Length) { bool foundAcceptor = false; foreach (ITokenAcceptor <IToken> acceptor in acceptors) { ITokenBuilder <IToken>?builder = acceptor.Accept(expr, ref index); if (builder != null) { IBinaryTokenBuilder <IBinaryToken>?builderAsBinary = builder as IBinaryTokenBuilder <IBinaryToken>; if (root == null) { if (builderAsBinary != null) { throw new Exception("First token cannot be a binary token"); } root = builder; } if (builderAsBinary != null) { if (lastBinary == null || lastBinary.IsMultiply || !builderAsBinary.IsMultiply) { if (lastBinary != null) { lastBinary.Right = _left; } builderAsBinary.Left = root; root = builder; } else { builderAsBinary.Left = _left; lastBinary.Right = builder; } lastBinary = builderAsBinary; _left = null; acceptors = constantAcceptors; } else { _left = builder; acceptors = binaryAcceptors; if (builder is VariableToken variableToken) { variables[variableToken.Name] = 0; } } foundAcceptor = true; break; } } if (!foundAcceptor) { Console.WriteLine($"Cannot determine token '{expr[index]}'"); Console.WriteLine(expr); Console.WriteLine($"{new string(' ', index)}^{new string('-', expr.Length - index + 2)}"); root = null; break; } } if (_left != null && lastBinary != null) { lastBinary.Right = _left; } if (root != null) { foreach (string key in variables.Keys) { Console.WriteLine($"Define the value for {key}:"); while (true) { string answer = Console.ReadLine() ?? ""; if (double.TryParse(answer, out double result)) { variables[key] = result; break; } else { Console.WriteLine("Not a double!"); } } } IToken rootToken = root.Build(); PrintToken(rootToken, 0, variables); Console.WriteLine($"Calculated: {expr} = {rootToken.Calculate(variables)}"); } else { Console.WriteLine("No token defined!"); } }