public override Production Parse(List <Token> tokens) { var nonWhitespace = tokens.NextNonWhitespace(); if (nonWhitespace.TokenClass != TokenClass.Boolean && nonWhitespace.TokenClass != TokenClass.Float && nonWhitespace.TokenClass != TokenClass.Integer && nonWhitespace.TokenClass != TokenClass.ReplacementSymbol && nonWhitespace.TokenClass != TokenClass.StartScope && nonWhitespace.TokenClass != TokenClass.String && nonWhitespace.TokenClass != TokenClass.Symbol) { return(new Production(null, tokens)); } var remainder = tokens.ToList(); while (remainder.Any() && Constituents.Count < 3) // An operation must have exactly three items: value op value { var currentToken = remainder.First().TokenClass; Production current = null; //check whether the right hand side of the operation is another operation if (Constituents.Count == 2) { current = new OperationExpression().Parse(remainder); } if (Constituents.Count != 2 || current?.Expression == null) { switch (currentToken) { case TokenClass.StartScope: current = new ScopedExpression().Parse(remainder); break; case TokenClass.Whitespace: current = new WhitespaceExpression().Parse(remainder); break; case TokenClass.ReplacementSymbol: current = new ReplacementSymbolExpression().Parse(remainder); break; case TokenClass.Symbol: current = new FunctionExpression().Parse(remainder); if (current.Expression == null) { current = new SymbolExpression().Parse(remainder); } break; case TokenClass.Operator: if (Constituents.Count == 2) { current = NumericExpression.TryParseNumeric(remainder); break; } current = new OperatorExpression().Parse(remainder); break; case TokenClass.Integer: case TokenClass.Float: current = NumericExpression.TryParseNumeric(remainder); break; case TokenClass.String: current = new StringExpression().Parse(remainder); break; case TokenClass.Boolean: current = new BooleanExpression().Parse(remainder); break; default: return(new Production(null, tokens)); } } if (current == null || current.Expression == null) { return(new Production(null, tokens)); } remainder = current.RemainingTokens; if (!(current.Expression is WhitespaceExpression)) { Constituents.Add(current.Expression); } } if (Constituents.None(c => c is OperatorExpression)) { return(new Production(null, tokens)); } if (Constituents.Count != 3) { return(new Production(null, tokens)); } return(new Production(this, remainder)); }