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) { Expression parsed; switch (remaining.First().TokenClass) { case TokenClass.ReplacementSymbol: current = new OperationExpression().Parse(remaining); if (current.Expression != null) { break; } if (Constituents.Count > 0) { return(new Production(null, tokens)); //cannot have multiple value types in a row } current = new ReplacementSymbolExpression().Parse(remaining); break; case TokenClass.Integer: case TokenClass.Float: current = new OperationExpression().Parse(remaining); if (current.Expression != null) { break; } if (Constituents.Count > 0) { return(new Production(null, tokens)); } current = NumericExpression.TryParseNumeric(remaining); break; case TokenClass.String: current = new OperationExpression().Parse(remaining); if (current.Expression != null) { break; } if (Constituents.Count > 0) { return(new Production(null, tokens)); } current = new StringExpression().Parse(remaining); break; case TokenClass.Boolean: current = new OperationExpression().Parse(remaining); if (current.Expression != null) { break; } if (Constituents.Count > 0) { return(new Production(null, tokens)); } current = new BooleanExpression().Parse(remaining); break; case TokenClass.Symbol: current = new FunctionExpression().Parse(remaining); if (current.Expression != null) { break; } if (Constituents.Count > 0) { return(new Production(null, tokens)); } current = new SymbolExpression().Parse(remaining); break; case TokenClass.StartScope: current = new SeparatedExpression().Parse(remaining); if (current.Expression != null) { break; } if (Constituents.Count > 0) { return(new Production(null, tokens)); } current = new ScopedExpression().Parse(remaining); break; case TokenClass.Whitespace: current = new WhitespaceExpression().Parse(remaining); break; case TokenClass.Operator: if (Constituents.Count != 1) { return(new Production(null, remaining)); } current = new OperationExpression().Parse(Constituents.First(), remaining); if (current.Expression == null) { break; } Constituents.Clear(); break; default: return(new Production(null, remaining)); break; } if (current.Expression == null) { return(new Production(null, tokens)); } if (!(current.Expression is WhitespaceExpression)) { Constituents.Add(current.Expression); } remaining = current.RemainingTokens; } if (remaining.None()) { return(new Production(null, tokens)); } if (remaining[0].TokenClass != TokenClass.EndScope) { return(new Production(null, tokens)); } return(new Production(this, remaining.Skip(1).ToList())); }
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)); }
//constant: // Integer // Float // String // Boolean //symbol: // ReplacementSymbol // Symbol //value: // constant // symbol // operation // scope //operation: value Operator value //list-expression: value-source , value-source //scope: StartScope value-source EndScope //value-source: // value // scope // function // operation //function: symbol StartScope list-expression EndScope | symbol StartScope value-source EndScope public static Expression Parse(List <Token> tokens) { if (tokens == null || tokens.None()) { return(new NullExpression()); } var remainder = tokens.ToList(); Expression program = null; while (remainder.Any()) { Production parsed = null; var current = remainder.First(); switch (current.TokenClass) { case TokenClass.StartScope: parsed = new ScopedExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = new SeparatedExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = new ErrorExpression().Parse(program, remainder); break; case TokenClass.Whitespace: parsed = new WhitespaceExpression().Parse(remainder); break; case TokenClass.Symbol: parsed = new OperationExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = new FunctionExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = new SymbolExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = new ErrorExpression().Parse(program, remainder); break; case TokenClass.ReplacementSymbol: parsed = new OperationExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = new ReplacementSymbolExpression().Parse(remainder); break; case TokenClass.Float: case TokenClass.Integer: parsed = new OperationExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = NumericExpression.TryParseNumeric(remainder); break; case TokenClass.String: parsed = new OperationExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = new StringExpression().Parse(remainder); break; case TokenClass.Boolean: parsed = new OperationExpression().Parse(remainder); if (parsed.Expression != null) { break; } parsed = new BooleanExpression().Parse(remainder); break; case TokenClass.Operator: parsed = NumericExpression.TryParseNumeric(remainder); if (parsed.Expression != null) { break; } parsed = new OperationExpression().Parse(program, remainder); if (parsed.Expression != null) { break; } parsed = new ErrorExpression().Parse(program, remainder); break; case TokenClass.Error: throw new Exception("Unexpected sequence: " + remainder.First().Lexeme); default: throw new ArgumentOutOfRangeException(); } if (parsed.Expression != null && !(parsed.Expression is WhitespaceExpression)) { program = parsed.Expression; } remainder = parsed.RemainingTokens; } if (program == null || remainder.Any()) { throw new ParserException(remainder.Select(c => c.Lexeme).StringConcat()); } return(program); }
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())); }