// something.someValue // something[i] // something(*).x(*).y private bool ParseAccessExpression(ref ASTNode retn) { if (tokenStream.Current != ExpressionTokenType.Identifier) { return(false); } string identifier = tokenStream.Current.value; tokenStream.Save(); LightList <ASTNode> parts = LightList <ASTNode> .Get(); tokenStream.Advance(); while (tokenStream.HasMoreTokens) { if (tokenStream.Current == ExpressionTokenType.Dot || tokenStream.Current == ExpressionTokenType.Elvis) { if (tokenStream.Next != ExpressionTokenType.Identifier) { break; } tokenStream.Advance(); parts.Add(ASTNode.DotAccessNode(tokenStream.Current.value, tokenStream.Previous == ExpressionTokenType.Elvis)); tokenStream.Advance(); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.ArrayAccessOpen || tokenStream.Current == ExpressionTokenType.QuestionMark && tokenStream.NextTokenIs(ExpressionTokenType.ArrayAccessOpen)) { bool isElvis = false; if (tokenStream.Current == ExpressionTokenType.QuestionMark) { isElvis = true; tokenStream.Advance(); } int advance = tokenStream.FindMatchingIndex(ExpressionTokenType.ArrayAccessOpen, ExpressionTokenType.ArrayAccessClose); if (advance == -1) { Abort("Unmatched array bracket"); } ExpressionParser subParser = CreateSubParser(advance); parts.Add(ASTNode.IndexExpressionNode(subParser.ParseLoop(), isElvis)); subParser.Release(); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.ParenOpen) { LightList <ASTNode> parameters = null; if (!ParseListExpression(ref parameters, ExpressionTokenType.ParenOpen, ExpressionTokenType.ParenClose)) { Abort(); } parts.Add(ASTNode.InvokeNode(parameters)); if (tokenStream.HasMoreTokens) { continue; } } else if (tokenStream.Current == ExpressionTokenType.LessThan) { // shortcut the << operator since we can't have a << in a generic type node. List<<string>> is invalid for example if (tokenStream.HasMoreTokens && tokenStream.Next == ExpressionTokenType.LessThan) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } TypeLookup typePath = new TypeLookup(); if (!(ParseTypePathGenerics(ref typePath))) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } parts.Add(ASTNode.GenericTypePath(typePath)); if (tokenStream.HasMoreTokens) { continue; } } if (parts.Count == 0) { tokenStream.Restore(); LightList <ASTNode> .Release(ref parts); return(false); } retn = ASTNode.MemberAccessExpressionNode(identifier, parts).WithLocation(tokenStream.Peek()); return(true); } ReleaseList(parts); tokenStream.Restore(); return(false); }