private static TopLevelEntity ParseIndexProperty(
            ParserContext context,
            ClassLikeDefinition parent,
            Token firstToken,
            Dictionary <string, Token> modifiers,
            CSharpType type,
            TokenStream tokens)
        {
            tokens.PopExpected("[");
            CSharpType indexType         = CSharpType.Parse(tokens);
            Token      indexVariableName = tokens.PopWord();

            tokens.PopExpected("]");
            tokens.PopExpected("{");

            PropertyDefinition indexProperty = new PropertyDefinition(firstToken, modifiers, type, null, parent);

            PropertyBody getter = null;
            PropertyBody setter = null;

            while (tokens.IsNext("get") || tokens.IsNext("set"))
            {
                Token getOrSetToken = tokens.Peek();
                bool  isGet         = getOrSetToken.Value == "get";
                if (!isGet && setter != null)
                {
                    tokens.PopExpected("}");                           // intentionally throw
                }
                if (isGet && getter != null)
                {
                    tokens.PopExpected("set"); //intentionally throw
                }
                tokens.Pop();                  // get/set already fetched with Peek() above.
                PropertyBody body = new PropertyBody(getOrSetToken, new Dictionary <string, Token>(), isGet, indexProperty);
                Executable[] code = ExecutableParser.ParseCodeBlock(context, tokens, body, true);
                body.Code = code;
                if (isGet)
                {
                    getter = body;
                }
                else
                {
                    setter = body;
                }
            }

            indexProperty.IndexType         = indexType;
            indexProperty.IndexVariableName = indexVariableName;

            indexProperty.Getter = getter;
            indexProperty.Setter = setter;

            return(indexProperty);
        }
        private static TopLevelEntity ParseClassProperty(
            ParserContext context,
            ClassLikeDefinition parent,
            Token firstToken,
            Dictionary <string, Token> modifiers,
            CSharpType type,
            Token propertyName,
            TokenStream tokens)
        {
            tokens.PopExpected("{");

            PropertyDefinition propertyDefinition = new PropertyDefinition(firstToken, modifiers, type, propertyName, parent);

            PropertyBody getter = null;
            PropertyBody setter = null;

            while (!tokens.IsNext("}") && (getter == null || setter == null))
            {
                Token bodyFirstToken = tokens.Peek();
                Dictionary <string, Token> bodyModifiers = ParseModifiers(context, tokens);
                if (tokens.IsNext("get") && getter == null)
                {
                    Token getToken = tokens.Pop();
                    getter = new PropertyBody(bodyFirstToken, bodyModifiers, true, propertyDefinition);
                    if (!tokens.PopIfPresent(";"))
                    {
                        getter.Code = ExecutableParser.ParseCodeBlock(context, tokens, getter, true);
                    }
                }
                else if (tokens.IsNext("set") && setter == null)
                {
                    Token setToken = tokens.Pop();
                    setter = new PropertyBody(bodyFirstToken, bodyModifiers, false, propertyDefinition);
                    if (!tokens.PopIfPresent(";"))
                    {
                        setter.Code = ExecutableParser.ParseCodeBlock(context, tokens, setter, true);
                    }
                }
                else if (getter == null)
                {
                    tokens.PopExpected("get"); // intentionally throw
                }
                else
                {
                    tokens.PopExpected("set"); // intentionally throw
                }
            }
            tokens.PopExpected("}");

            propertyDefinition.Getter = getter;
            propertyDefinition.Setter = setter;

            return(propertyDefinition);
        }
Example #3
0
        private static Executable ParseTryStatement(ParserContext context, TokenStream tokens, TopLevelEntity parent)
        {
            Token tryToken = tokens.PopExpected("try");

            Executable[] tryCode = ExecutableParser.ParseCodeBlock(context, tokens, parent, true);

            List <Token>        catchTokens         = new List <Token>();
            List <CSharpType>   catchBlockTypes     = new List <CSharpType>();
            List <Token>        catchBlockVariables = new List <Token>();
            List <Executable[]> catchBlockCode      = new List <Executable[]>();
            Token finallyToken = null;

            Executable[] finallyCode = null;

            while (tokens.IsNext("catch"))
            {
                catchTokens.Add(tokens.Pop());
                tokens.PopExpected("(");
                catchBlockTypes.Add(CSharpType.Parse(tokens));
                if (!tokens.PopIfPresent(")"))
                {
                    catchBlockVariables.Add(tokens.PopWord());
                    tokens.PopExpected(")");
                }
                else
                {
                    catchBlockVariables.Add(null);
                }
                catchBlockCode.Add(ParseCodeBlock(context, tokens, parent, true));
            }

            if (tokens.IsNext("finally"))
            {
                finallyToken = tokens.Pop();
                finallyCode  = ParseCodeBlock(context, tokens, parent, true);
            }

            return(new TryStatement(
                       tryToken,
                       tryCode,
                       catchTokens,
                       catchBlockTypes,
                       catchBlockVariables,
                       catchBlockCode,
                       finallyToken,
                       finallyCode,
                       parent));
        }
        private static TopLevelEntity ParseClassConstructor(
            ParserContext context,
            ClassLikeDefinition classDef,
            Token firstToken,
            Dictionary <string, Token> modifiers,
            CSharpType type,
            TokenStream tokens)
        {
            List <CSharpType> argTypes     = new List <CSharpType>();
            List <Token>      argNames     = new List <Token>();
            List <Token>      argModifiers = new List <Token>();

            ParseArgList(argTypes, argNames, argModifiers, tokens);

            ConstructorDefinition constructorDef = new ConstructorDefinition(
                firstToken,
                modifiers,
                argTypes,
                argNames,
                argModifiers,
                classDef);

            if (tokens.PopIfPresent(":"))
            {
                if (!tokens.IsNext("base") && !tokens.IsNext("this"))
                {
                    tokens.PopExpected("base"); // intentionally throw
                }
                constructorDef.BaseConstructorInvocation = tokens.Pop();

                tokens.PopExpected("(");
                List <Expression> baseConstructorArgs = new List <Expression>();
                while (!tokens.PopIfPresent(")"))
                {
                    if (baseConstructorArgs.Count > 0)
                    {
                        tokens.PopExpected(",");
                    }
                    baseConstructorArgs.Add(ExpressionParser.Parse(context, tokens, constructorDef));
                }
                constructorDef.BaseConstructorArgs = baseConstructorArgs.ToArray();
            }

            constructorDef.Code = ExecutableParser.ParseCodeBlock(context, tokens, constructorDef, true);

            return(constructorDef);
        }
Example #5
0
        private static Executable ParseUsingStatement(ParserContext context, TokenStream tokens, TopLevelEntity parent)
        {
            Token usingToken = tokens.PopExpected("using");

            tokens.PopExpected("(");
            CSharpType type        = null;
            Token      variable    = null;
            Token      equalsToken = null;

            if (!tokens.IsNext("new"))
            {
                type        = CSharpType.Parse(tokens);
                variable    = tokens.PopWord();
                equalsToken = tokens.PopExpected("=");
            }
            Expression expression = ExpressionParser.Parse(context, tokens, parent);

            tokens.PopExpected(")");
            Executable[] code = ExecutableParser.ParseCodeBlock(context, tokens, parent, false);
            return(new UsingStatement(usingToken, type, variable, expression, code, parent));
        }
        private static TopLevelEntity ParseClassMethod(
            ClassLikeDefinition classDef,
            ParserContext context,
            Token firstToken,
            Dictionary <string, Token> modifiers,
            CSharpType returnType,
            Token methodName,
            TokenStream tokens)
        {
            List <CSharpType> argTypes     = new List <CSharpType>();
            List <Token>      argNames     = new List <Token>();
            List <Token>      argModifiers = new List <Token>();

            ParseArgList(argTypes, argNames, argModifiers, tokens);

            MethodDefinition methodDef = new MethodDefinition(
                firstToken,
                modifiers,
                returnType,
                methodName,
                argNames,
                argTypes,
                argModifiers,
                classDef);

            if (methodDef.IsAbstract || classDef is InterfaceDefinition)
            {
                tokens.PopExpected(";");
            }
            else
            {
                methodDef.Code = ExecutableParser.ParseCodeBlock(context, tokens, methodDef, true);
            }

            return(methodDef);
        }
Example #7
0
        private static Expression ParseAtom(ParserContext context, TokenStream tokens, TopLevelEntity parent)
        {
            string next = tokens.PeekValue();

            switch (next)
            {
            case "true":
            case "false":
                Token booleanToken = tokens.Pop();
                return(new BooleanConstant(booleanToken, booleanToken.Value == "true", parent));

            case "null":
                Token nullToken = tokens.Pop();
                return(new NullConstant(nullToken, parent));

            case "new":
                Token      newToken  = tokens.Pop();
                CSharpType className = CSharpType.TryParse(tokens);
                if (className == null)
                {
                    throw new ParserException(newToken, "'new' keyword must be followed by a className");
                }
                if (!tokens.IsNext("("))
                {
                    // could be a new array of which there are two ways to define it...
                    if (className.IsArray && tokens.IsNext("{"))
                    {
                        List <Expression> arrayItems = new List <Expression>();
                        tokens.PopExpected("{");
                        bool nextAllowed = true;
                        while (!tokens.PopIfPresent("}"))
                        {
                            if (!nextAllowed)
                            {
                                tokens.PopExpected("}");
                            }
                            arrayItems.Add(ExpressionParser.Parse(context, tokens, parent));
                            nextAllowed = tokens.PopIfPresent(",");
                        }
                        return(new ArrayInitialization(newToken, className.Generics[0], null, arrayItems, parent));
                    }

                    if (tokens.IsNext("["))
                    {
                        // a new array with specified length
                        tokens.PopExpected("[");
                        Expression arrayLength = ExpressionParser.Parse(context, tokens, parent);
                        tokens.PopExpected("]");
                        return(new ArrayInitialization(newToken, className, arrayLength, null, parent));
                    }

                    // if this isn't an array construction, then give a reasonable error message...
                    tokens.PopExpected("(");
                }
                return(new ConstructorInvocationFragment(newToken, className, parent));

            case "@":
                // raw string
                Token  rawStringAt       = tokens.Pop();
                Token  stringValue       = tokens.Pop();
                string stringValueActual = stringValue.Value;
                if (stringValueActual[0] != '"')
                {
                    throw new ParserException(stringValue, "Expected a string value");
                }
                return(new StringConstant(rawStringAt, stringValueActual.Substring(1, stringValueActual.Length - 2), parent));

            default: break;
            }

            Token token = tokens.Pop();
            char  c     = next[0];

            if (c == '"' || c == '\'')
            {
                string stringValue = StringUtil.ConvertStringTokenToValue(token);
                if (c == '"')
                {
                    return(new StringConstant(token, stringValue, parent));
                }
                else
                {
                    return(new CharConstant(token, stringValue, parent));
                }
            }

            if (c == '0' && next.Length > 2 && next[1] == 'x')
            {
                string hex         = next.Substring(2);
                int    parsedValue = 0;

                for (int i = 0; i < hex.Length; ++i)
                {
                    c = hex[i];
                    if (c >= '0' && c <= '9')
                    {
                        parsedValue = parsedValue * 16 + (c - '0');
                    }
                    else if (c >= 'a' && c <= 'f')
                    {
                        parsedValue = parsedValue * 16 + (10 + c - 'a');
                    }
                    else if (c >= 'A' && c <= 'F')
                    {
                        parsedValue = parsedValue * 16 + (10 + c - 'A');
                    }
                    else
                    {
                        throw new ParserException(token, "Invalid hexidecimal value: '" + hex + "'");
                    }
                }
                return(new IntegerConstant(token, parsedValue, parent));
            }

            if (c == '.' && next.Length > 1)
            {
                double value;
                if (!double.TryParse(next, out value))
                {
                    throw new ParserException(token, "Invalid double constant: '" + next + "'");
                }
                return(new DoubleConstant(token, value, parent));
            }

            if (c >= '0' && c <= '9')
            {
                if (next.Contains('.'))
                {
                    if (next.EndsWith("f") || next.EndsWith("F"))
                    {
                        throw new NotImplementedException();
                    }
                    double floatValue;
                    if (!double.TryParse(next, out floatValue))
                    {
                        throw new ParserException(token, "Invalid number: '" + next + "'");
                    }
                    return(new DoubleConstant(token, floatValue, parent));
                }
                else
                {
                    if (next.EndsWith("f") || next.EndsWith("F"))
                    {
                        throw new NotImplementedException();
                    }

                    int intValue;
                    if (!int.TryParse(next, out intValue))
                    {
                        throw new ParserException(token, "Invalid number: '" + next + "'");
                    }

                    return(new IntegerConstant(token, intValue, parent));
                }
            }

            if ((c >= 'a' && c <= 'z') ||
                (c >= 'A' && c <= 'Z') ||
                c == '_')
            {
                if (tokens.IsNext("=>"))
                {
                    List <Token> args = new List <Token>()
                    {
                        token
                    };
                    Token        arrowToken = tokens.Pop();
                    Executable[] lambdaBody;
                    if (tokens.IsNext("{"))
                    {
                        lambdaBody = ExecutableParser.ParseCodeBlock(context, tokens, parent, true);
                    }
                    else
                    {
                        Expression lambdaBodyExpr = Parse(context, tokens, parent);
                        lambdaBody = new Executable[] {
                            new ReturnStatement(lambdaBodyExpr.FirstToken, lambdaBodyExpr, parent),
                        };
                    }
                    return(new Lambda(token, args, arrowToken, lambdaBody, parent));
                }
                return(new Variable(token, parent));
            }

            throw new ParserException(token, "Unexpected token: '" + token.Value + "'");
        }
Example #8
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);
        }