private AstItem ReadExpression(TokenIterator tokens, List <TokenKind> terminators) { var expTokens = new List <Token>(); if (terminators == null) { expTokens.AddRange(tokens.ToList()); } else { var inArray = false; var tok = tokens.Current(); while (tok != null) { if (!inArray && terminators.Contains(tok.Kind)) { break; } if (tok.Kind == TokenKind.SquareBracketOpen) { inArray = true; } if (tok.Kind == TokenKind.SquareBracketClose) { inArray = false; } expTokens.Add(tok); tokens.Step(); tok = tokens.Current(); } } if (expTokens.Count == 0) { throw new Exception("Expected expression, found " + tokens.Current()); } AstItem result = null; var tokenIter = new TokenIterator(expTokens); if (expTokens.Count == 1) { //Single immediate, vector or variable result = ReadSingleAstItem(tokenIter); } else { var token = tokenIter.Current(); var next = tokenIter.Next(); if (token.Kind == TokenKind.New) { result = ReadNewPointer(tokenIter); } else { //Math Expression var expItemsInfix = new List <AstItem>(); var expectOperand = true; while (token != null) { switch (token.Kind) { case TokenKind.Word: case TokenKind.Number: case TokenKind.True: case TokenKind.False: case TokenKind.VectorConstructor: case TokenKind.Char: case TokenKind.String: case TokenKind.SquareBracketOpen: var operandItem = ReadSingleAstItem(tokenIter); expItemsInfix.Add(operandItem); expectOperand = false; //Next we want an operator break; case TokenKind.RoundBracketOpen: case TokenKind.RoundBracketClose: expItemsInfix.Add(AstItem.AsOperator(ParseOperator(token.Value))); break; case TokenKind.ExpressionOperator: if (expectOperand) { expItemsInfix.Add(AstItem.AsUnaryOperator(ParseUnaryOperator(token.Value))); } else { expItemsInfix.Add(AstItem.AsOperator(ParseOperator(token.Value))); expectOperand = true; //Next we want an operand } break; default: throw new Exception("Unexpected expression token: " + token); } tokenIter.Step(); token = tokenIter.Current(); } //Convert to postfix if (expItemsInfix.Count > 1) { result = InfixToPostfix(expItemsInfix); } else { result = expItemsInfix[0]; } } } return(result); }