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)); }
public override Production Parse(List <Token> tokens) { var firstParen = tokens.First(); if (firstParen.TokenClass != TokenClass.StartScope) { return(new Production(null, tokens)); } var current = new ScopeExpression().Parse(tokens); var remaining = current.RemainingTokens.ToList(); while (remaining.Any() && remaining.FirstOrDefault() != null && remaining[0].TokenClass != TokenClass.EndScope) { switch (remaining.First().TokenClass) { case TokenClass.ReplacementSymbol: if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression)) { return(new Production(null, tokens)); } current = new ReplacementSymbolExpression().Parse(remaining); break; case TokenClass.Integer: case TokenClass.Float: if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression)) { return(new Production(null, tokens)); } current = NumericExpression.TryParseNumeric(remaining); break; case TokenClass.String: if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression)) { return(new Production(null, tokens)); } current = new StringExpression().Parse(remaining); break; case TokenClass.Boolean: if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression)) { return(new Production(null, tokens)); } current = new BooleanExpression().Parse(remaining); break; case TokenClass.Symbol: if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression)) { return(new Production(null, tokens)); } current = new FunctionExpression().Parse(remaining);; if (current.Expression != null) { break; } current = new SymbolExpression().Parse(remaining); break; case TokenClass.StartScope: if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression)) { return(new Production(null, tokens)); } current = new SeparatedExpression().Parse(remaining); if (current.Expression != null) { break; } current = new ScopedExpression().Parse(remaining); if (current.Expression != null) { break; } break; case TokenClass.EndScope: current = new ScopeExpression().Parse(remaining); break; case TokenClass.Whitespace: current = new WhitespaceExpression().Parse(remaining); break; case TokenClass.Separator: current = new SeparatorExpression().Parse(remaining); break; case TokenClass.Operator: if (Constituents.Count < 1 || (Constituents.Last() is SeparatorExpression)) { return(new Production(null, remaining)); } current = new OperationExpression().Parse(Constituents.Last(), remaining); if (current.Expression == null) { break; } Constituents.RemoveAt(Constituents.Count - 1); break; default: return(new Production(null, remaining)); } if (current.Expression == null) { return(new Production(null, tokens)); } if (!(current.Expression is WhitespaceExpression)) { Constituents.Add(current.Expression); } remaining = current.RemainingTokens; } //parenthesis must be closed if (remaining.FirstOrDefault() == null || remaining.First().TokenClass != TokenClass.EndScope) { return(new Production(null, remaining)); } var separators = Constituents.Count(c => c is SeparatorExpression); var values = Constituents.Count(c => !(c is SeparatorExpression)); //cannot be a separated expression without separators if (separators == 0) { return(new Production(null, tokens)); } //separated expressions require exactly n - 1 separators to values if (separators != (values - 1)) { return(new Production(null, tokens)); } var valuesOnly = Constituents.ToList().Aggregate(new List <Expression>(), (acc, i) => { if (i is ScopeExpression || i is SeparatorExpression) { return(acc); } acc.Add(i); return(acc); }).ToList(); Constituents = valuesOnly; return(new Production(this, remaining.Skip(1).ToList())); }