public void IndexShouldIncreaseWhenMoveNext() { var tokens = new List <Token> { new Token("1", TokenType.Decimal), new Token("2", TokenType.Decimal) }; var navigator = new TokenNavigator(tokens); navigator.MoveNext(); Assert.AreEqual(1, navigator.Index, "Index was not 1 but " + navigator.Index); }
public void MoveToNextAndReturnPrevToken() { var tokens = new List <Token> { new Token("1", TokenType.Decimal), new Token("2", TokenType.Decimal) }; var navigator = new TokenNavigator(tokens); navigator.MoveNext(); Assert.AreEqual("1", navigator.PreviousToken.Value.Value); }
public void NumberOfRemainingTokensShouldBeCorrect() { var tokens = new List <Token> { new Token("1", TokenType.Decimal), new Token("2", TokenType.Decimal), new Token("3", TokenType.Decimal) }; var navigator = new TokenNavigator(tokens); Assert.AreEqual(2, navigator.NbrOfRemainingTokens); navigator.MoveNext(); Assert.AreEqual(1, navigator.NbrOfRemainingTokens); }
/// <summary> /// This will never return null nor a set containing any nulls /// </summary> private static IEnumerable <Expression> Generate(TokenNavigator tokenNavigator, int depth, IToken directedWithReferenceIfAny, Action <string> warningLogger) { if (tokenNavigator == null) { throw new ArgumentNullException("tokenNavigator"); } if (depth < 0) { throw new ArgumentOutOfRangeException("depth", "must be zero or greater"); } if (warningLogger == null) { throw new ArgumentNullException("warningLogger"); } var expressions = new List <Expression>(); var expressionSegments = new List <IExpressionSegment>(); var accessorBuffer = new List <IToken>(); while (true) { var token = tokenNavigator.Value; if (token == null) { if (depth > 0) { throw new ArgumentException("Expected CloseBrace and didn't encounter one - invalid content"); } break; } if (token is CloseBrace) { if (depth == 0) { throw new ArgumentException("Unexpected CloseBrace - invalid content"); } tokenNavigator.MoveNext(); // Move on since this token has been processed if (expressionSegments.Count == 1) { var callExpressionSegment = expressionSegments[0] as CallExpressionSegment; if ((callExpressionSegment != null) && (callExpressionSegment.MemberAccessTokens.Count() == 1) && !callExpressionSegment.Arguments.Any()) { // VBScript gives special meaning to a reference wrapped in brackets when passing it to a function (or property); if // the argument would otherwise be passed ByRef, it will be passed ByVal. If this close bracket terminates a section // containing only a single CallExpressionSegment without property accesses or arguments, then the brackets have // significance and the content must be represented by a BracketedExpressionSegment. (If it's a variable access with // function / property accesses - meaning there would be multiple MemberAccessTokens - or if there are arguments - // meaning that it's a function or property call - then the value would not be elligible for being passed ByRef anyway, // so the extra brackets need not be maintained). There is chance that ths single token represents a non-argument call // to a function, but we don't have enough information at this point to know that, so we have to presume the worst and // keep the brackets here. expressionSegments[0] = new BracketedExpressionSegment(new[] { callExpressionSegment }); } } break; } if (token is ArgumentSeparatorToken) { if (depth == 0) { throw new ArgumentException("Encountered ArgumentSeparatorToken in top-level content - invalid"); } if (accessorBuffer.Any()) { expressionSegments.Add( GetCallOrNewOrValueExpressionSegment( accessorBuffer, new Expression[0], directedWithReferenceIfAny, argumentsAreBracketed: false, willBeFirstSegmentInCallExpression: WillBeFirstSegmentInCallExpression(expressionSegments), warningLogger: warningLogger ) ); accessorBuffer.Clear(); } if (!expressionSegments.Any()) { throw new ArgumentException("Unexpected ArgumentSeparatorToken - invalid content"); } expressions.Add(GetExpression(expressionSegments)); expressionSegments.Clear(); tokenNavigator.MoveNext(); // Move on since this token has been processed continue; } if (token is OpenBrace) { tokenNavigator.MoveNext(); // Move on since this token has been processed // Get the content from inside the brackets (using a TokenNavigator here that is passed again into the Generate // method means that when the below call returns, the tokenNavigator here will have been moved along to after // the bracketed content that is about to be processed) var bracketedExpressions = Generate(tokenNavigator, depth + 1, directedWithReferenceIfAny, warningLogger); // If the accessorBuffer isn't empty then the bracketed content should be arguments, if not then it's just a bracketed expression if (accessorBuffer.Any()) { expressionSegments.Add( GetCallOrNewOrValueExpressionSegment( accessorBuffer, bracketedExpressions, directedWithReferenceIfAny, argumentsAreBracketed: true, willBeFirstSegmentInCallExpression: WillBeFirstSegmentInCallExpression(expressionSegments), warningLogger: warningLogger ) ); accessorBuffer.Clear(); } else if (bracketedExpressions.Any()) { if (expressionSegments.Any() && (expressionSegments.Last() is CallSetItemExpressionSegment)) { // If the previous expression segment was a CallExpressionSegment or CallSetItemExpressionSegment (the first // is derived from the second so only a single type check is required) then this bracketed content should // be considered a continuation of the call (these segments will later be grouped into a single // CallSetExpression) expressionSegments.Add( new CallSetItemExpressionSegment( new IToken[0], bracketedExpressions, null // ArgumentBracketPresenceOptions ) ); } else { if (bracketedExpressions.Count() > 1) { throw new ArgumentException("If bracketed content is not for an argument list then it's invalid for there to be multiple expressions within it"); } expressionSegments.Add( WrapExpressionSegments(bracketedExpressions.Single().Segments, unwrapSingleBracketedTerm: false) ); } } continue; } var operatorToken = token as OperatorToken; if (operatorToken != null) { if (accessorBuffer.Any()) { expressionSegments.Add( GetCallOrNewOrValueExpressionSegment( accessorBuffer, new Expression[0], directedWithReferenceIfAny, argumentsAreBracketed: false, // zero-argument content not bracketed willBeFirstSegmentInCallExpression: WillBeFirstSegmentInCallExpression(expressionSegments), warningLogger: warningLogger ) ); accessorBuffer.Clear(); } expressionSegments.Add( new OperationExpressionSegment(operatorToken) ); tokenNavigator.MoveNext(); continue; } accessorBuffer.Add(token); tokenNavigator.MoveNext(); } if (accessorBuffer.Any()) { expressionSegments.Add( GetCallOrNewOrValueExpressionSegment( accessorBuffer, new Expression[0], directedWithReferenceIfAny, argumentsAreBracketed: false, // zero-argument content not bracketed willBeFirstSegmentInCallExpression: WillBeFirstSegmentInCallExpression(expressionSegments), warningLogger: warningLogger ) ); accessorBuffer.Clear(); } if (expressionSegments.Any()) { expressions.Add(GetExpression(expressionSegments)); expressionSegments.Clear(); } return(expressions); }