Example #1
0
        private static Expression ParseAtomWithSuffix(ParserContext context, TokenStream tokens, TopLevelEntity parent)
        {
            Expression root;

            if (tokens.IsNext("("))
            {
                Token openParen = tokens.Pop();

                switch (IdentifyParenthesisSituation(tokens))
                {
                case ParenthesisSituation.CAST:
                    CSharpType castType = CSharpType.Parse(tokens);
                    tokens.PopExpected(")");
                    Expression castValue = ParseAtomWithSuffix(context, tokens, parent);
                    return(new CastExpression(openParen, castType, castValue, parent));

                case ParenthesisSituation.LAMBDA_ARG:
                    List <Token> lambdaArgs = new List <Token>()
                    {
                        tokens.PopWord()
                    };

                    while (tokens.PopIfPresent(","))
                    {
                        lambdaArgs.Add(tokens.PopWord());
                    }
                    tokens.PopExpected(")");
                    Token        arrowToken = tokens.PopExpected("=>");
                    Executable[] lambdaBody;
                    if (tokens.IsNext("{"))
                    {
                        lambdaBody = ExecutableParser.ParseCodeBlock(context, tokens, parent, true);
                    }
                    else
                    {
                        Expression expr = Parse(context, tokens, parent);
                        lambdaBody = new Executable[] {
                            new ReturnStatement(expr.FirstToken, expr, parent)
                        };
                    }
                    return(new Lambda(openParen, lambdaArgs, arrowToken, lambdaBody, parent));

                case ParenthesisSituation.WRAPPED_EXPRESSION:
                    root = Parse(context, tokens, parent);
                    tokens.PopExpected(")");
                    break;

                default:
                    throw new Exception();     // not valid
                }
            }
            else
            {
                root = ParseAtom(context, tokens, parent);
            }
            bool   anythingInteresting = true;
            string next = tokens.PeekValue();

            while (anythingInteresting)
            {
                switch (next)
                {
                case ".":
                    Token dotToken  = tokens.Pop();
                    Token fieldName = tokens.PopWord();
                    root = new DotField(root.FirstToken, root, dotToken, fieldName, parent);
                    break;

                case "[":
                    Token      openBracket = tokens.Pop();
                    Expression index       = Parse(context, tokens, parent);
                    tokens.PopExpected("]");
                    root = new BracketIndex(root, openBracket, index, parent);
                    break;

                case "<":
                    if (root is DotField)
                    {
                        CSharpType[] functionInvocationTypeSpecification = MaybeParseOutOneOfThoseInlineTypeSpecificationsForFunctionInvocations(tokens);
                        if (functionInvocationTypeSpecification != null)
                        {
                            ((DotField)root).InlineTypeSpecification = functionInvocationTypeSpecification;
                        }
                        else
                        {
                            anythingInteresting = false;
                        }
                    }
                    else
                    {
                        anythingInteresting = false;
                    }
                    break;

                case "(":
                    Token             openParen = tokens.Pop();
                    List <Expression> args      = new List <Expression>();
                    List <Token>      outTokens = new List <Token>();
                    while (!tokens.PopIfPresent(")"))
                    {
                        if (args.Count > 0)
                        {
                            tokens.PopExpected(",");
                        }
                        if (tokens.IsNext("out"))
                        {
                            outTokens.Add(tokens.Pop());
                        }
                        else
                        {
                            outTokens.Add(null);
                        }
                        args.Add(Parse(context, tokens, parent));
                    }
                    root = new FunctionInvocation(root.FirstToken, root, openParen, args, outTokens, parent);
                    break;

                case "{":     // e.g. new List<int>() { 1, 2, 3 }. This only follows a constructor.
                    FunctionInvocation            fi  = root as FunctionInvocation;
                    ConstructorInvocationFragment cif = fi == null ? null : (ConstructorInvocationFragment)fi.Root;
                    if (root is FunctionInvocation && ((FunctionInvocation)root).Root is ConstructorInvocationFragment)
                    {
                        tokens.Pop();     // {

                        ConstructorSuffixData format = DetermineConstructorSuffixDataFormat(tokens);

                        bool nextAllowed                = true;
                        List <Expression> values        = new List <Expression>();
                        List <Expression> kvpKeys       = new List <Expression>();
                        List <Token>      propertyNames = new List <Token>();
                        while (!tokens.PopIfPresent("}"))
                        {
                            if (!nextAllowed)
                            {
                                tokens.PopExpected("}");                   // intentionally throw
                            }
                            switch (format)
                            {
                            case ConstructorSuffixData.KVP_ENTRIES:
                                tokens.PopExpected("{");
                                kvpKeys.Add(Parse(context, tokens, parent));
                                tokens.PopExpected(",");
                                values.Add(Parse(context, tokens, parent));
                                tokens.PopExpected("}");
                                break;

                            case ConstructorSuffixData.PROPERTIES:
                                propertyNames.Add(tokens.PopWord());
                                tokens.PopExpected("=");
                                values.Add(Parse(context, tokens, parent));
                                break;

                            case ConstructorSuffixData.SEQUENTIAL_ITEMS:
                                values.Add(Parse(context, tokens, parent));
                                break;
                            }
                            nextAllowed = tokens.PopIfPresent(",");
                        }
                        cif.InitialDataValues = values.ToArray();
                        int t = cif.InitialDataValues.Length;
                        if (kvpKeys.Count == t)
                        {
                            cif.InitialDataKeys = kvpKeys.ToArray();
                        }
                        if (propertyNames.Count == t)
                        {
                            cif.InitialDataPropertyNames = propertyNames.ToArray();
                        }
                    }
                    else
                    {
                        throw new ParserException(tokens.Peek(), "Unexpected '{'");
                    }
                    break;

                default:
                    anythingInteresting = false;
                    break;
                }
                next = tokens.PeekValue();
            }

            if (next == "++" || next == "--")
            {
                Token incrementToken = tokens.Pop();
                root = new InlineIncrement(root.FirstToken, incrementToken, false, root, parent);
            }

            return(root);
        }
Example #2
0
 public ConstructorInvocationFragmentWrapper(ConstructorInvocationFragment fragment)
     : base(fragment.FirstToken, fragment.Parent)
 {
     this.InnerFragment = fragment;
 }