コード例 #1
0
        // 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);
        }