private void SerializeIndex(List<string> output, IndexExpression index) { SerializeExpression(output, index.Root); output.Add("["); SerializeExpression(output, index.Index); output.Add("]"); }
private static Expression ParseEntityWithSuffix(TokenStream tokens) { Expression expression = ParseRootEntity(tokens); bool nextAllowed; bool keepGoing = true; string next = tokens.PeekValue(); while (keepGoing) { switch (next) { case "[": // indexing or slicing Token bracketToken = tokens.Pop(); List<Expression> sliceComponents = new List<Expression>(); nextAllowed = true; while (!tokens.PopIfPresent("]")) { if (!nextAllowed) tokens.PopExpected("]"); // throws if (tokens.IsNext(":")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens)); } nextAllowed = tokens.PopIfPresent(":"); } if (nextAllowed) { sliceComponents.Add(null); } if (sliceComponents.Count == 0) { throw new ParserException(bracketToken, "Unexpected token."); } else if (sliceComponents.Count == 1) { expression = new IndexExpression(expression, bracketToken, sliceComponents[0]); } else if (sliceComponents.Count <= 3) { expression = new SliceExpression(expression, bracketToken, sliceComponents); } else { throw new ParserException(bracketToken, "Slice expression has too many components."); } break; case "(": // function call Token openParen = tokens.Pop(); nextAllowed = true; List<Expression> args = new List<Expression>(); while (!tokens.PopIfPresent(")")) { if (!nextAllowed) tokens.PopExpected(")"); // throws args.Add(Parse(tokens)); nextAllowed = tokens.PopIfPresent(","); } expression = new FunctionInvocation(expression, args); break; case ".": // dot field Token dotToken = tokens.Pop(); Token fieldToken = tokens.Pop(); if (!Util.IsIdentifier(fieldToken)) { throw new ParserException(fieldToken, "Invalid field."); } expression = new DotField(expression, dotToken, fieldToken, fieldToken.Value); break; default: keepGoing = false; break; } next = tokens.PeekValue(); } return expression; }