Beispiel #1
0
        private static CSharpType[] MaybeParseOutOneOfThoseInlineTypeSpecificationsForFunctionInvocations(TokenStream tokens)
        {
            int state = tokens.CurrentState;

            if (!tokens.PopIfPresent("<"))
            {
                return(null);
            }

            List <CSharpType> types = new List <CSharpType>();
            CSharpType        type  = CSharpType.TryParse(tokens);

            if (type == null)
            {
                tokens.RestoreState(state);
                return(null);
            }
            types.Add(type);
            while (tokens.PopIfPresent(","))
            {
                type = CSharpType.TryParse(tokens);
                if (type == null)
                {
                    tokens.RestoreState(state);
                    return(null);
                }
                types.Add(type);
            }
            if (tokens.PopIfPresent(">") && tokens.IsNext("("))
            {
                return(types.ToArray());
            }
            tokens.RestoreState(state);
            return(null);
        }
        public static TopLevelEntity ParseClassMember(
            ClassLikeDefinition classDef,
            Token className,
            ParserContext context,
            TokenStream tokens)
        {
            Token firstToken = tokens.Peek();
            Dictionary <string, Token> modifiers = ParseModifiers(context, tokens);

            if (tokens.IsNext("enum"))
            {
                return(ParseEnumDefinition(context, classDef, firstToken, modifiers, tokens));
            }

            if (tokens.IsNext("class"))
            {
                return(ParseClass(context, classDef, firstToken, modifiers, tokens));
            }

            if (tokens.IsNext("const"))
            {
                return(ParseConstDefinition(context, classDef, firstToken, modifiers, tokens));
            }

            CSharpType type = CSharpType.TryParse(tokens);

            if (tokens.IsNext("(") && type.SimpleTypeName == className.Value)
            {
                return(ParseClassConstructor(context, classDef, firstToken, modifiers, type, tokens));
            }

            Token memberName = tokens.PopWord();

            if (tokens.IsNext(";") || tokens.IsNext("="))
            {
                return(ParseClassField(context, classDef, firstToken, modifiers, type, memberName, tokens));
            }

            if (tokens.IsNext("[") && memberName.Value == "this")
            {
                return(ParseIndexProperty(context, classDef, firstToken, modifiers, type, tokens));
            }

            if (tokens.IsNext("{"))
            {
                return(ParseClassProperty(context, classDef, firstToken, modifiers, type, memberName, tokens));
            }

            if (tokens.IsNext("("))
            {
                return(ParseClassMethod(classDef, context, firstToken, modifiers, type, memberName, tokens));
            }

            throw new ParserException(tokens.Peek(), "Not implemented");
        }
Beispiel #3
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 + "'");
        }
Beispiel #4
0
        // this function is called after the first ( is popped off the token stream.
        // It is destructive to the token stream.
        private static ParenthesisSituation IdentifyParenthesisSituationImpl(TokenStream tokens)
        {
            int state = tokens.CurrentState;

            // if any of these cause an EOF exception, it's a legit EOF exception.
            // The }'s alone for any body of code that an expression can appear in would be enough padding
            // to avoid non-legit errors.
            Token t1 = tokens.Pop();
            Token t2 = tokens.Pop();
            Token t3 = tokens.Pop();

            if (!t1.IsIdentifier)
            {
                return(ParenthesisSituation.WRAPPED_EXPRESSION);
            }
            if (t2.Value == ",")
            {
                return(ParenthesisSituation.LAMBDA_ARG);
            }
            if (t2.Value == ")" && t3.Value == "=>")
            {
                return(ParenthesisSituation.LAMBDA_ARG);
            }

            if (t2.Value == ")")
            {
                switch (t1.Value)
                {
                case "string":
                case "int":
                case "float":
                case "double":
                case "bool":
                case "object":
                case "byte":
                case "char":
                case "long":
                    return(ParenthesisSituation.CAST);
                }
            }

            tokens.RestoreState(state);

            CSharpType type = CSharpType.TryParse(tokens);

            if (type == null || !tokens.IsNext(")"))
            {
                return(ParenthesisSituation.WRAPPED_EXPRESSION);
            }
            if (type.Generics.Length > 0)
            {
                return(ParenthesisSituation.CAST);
            }
            if (!tokens.PopIfPresent(")"))
            {
                return(ParenthesisSituation.WRAPPED_EXPRESSION);
            }
            if (!tokens.HasMore)
            {
                return(ParenthesisSituation.WRAPPED_EXPRESSION);
            }
            // At this point you have a sequence words and dots in parentheses.
            Token next = tokens.Peek();

            if (next.IsIdentifier || next.IsNumber)
            {
                return(ParenthesisSituation.CAST);
            }
            char c = next.Value[0];

            if (c == '(')
            {
                return(ParenthesisSituation.CAST);
            }
            if (c == '@')
            {
                return(ParenthesisSituation.CAST);
            }
            if (c == '.')
            {
                return(ParenthesisSituation.WRAPPED_EXPRESSION);
            }
            if (c == '!')
            {
                return(ParenthesisSituation.CAST);
            }
            return(ParenthesisSituation.WRAPPED_EXPRESSION);
        }
Beispiel #5
0
        public static Executable Parse(ParserContext context, TokenStream tokens, TopLevelEntity parent, bool enableSemicolon)
        {
            switch (tokens.PeekValue())
            {
            case "for": return(ParseForLoop(context, tokens, parent));

            case "foreach": return(ParseForEachLoop(context, tokens, parent));

            case "if": return(ParseIfStatement(context, tokens, parent));

            case "while": return(ParseWhileLoop(context, tokens, parent));

            case "do": return(ParseDoWhileLoop(context, tokens, parent));

            case "switch": return(ParseSwitchStatement(context, tokens, parent));

            case "throw": return(ParseThrowStatement(context, tokens, parent));

            case "return": return(ParseReturnStatement(context, tokens, parent));

            case "using": return(ParseUsingStatement(context, tokens, parent));

            case "try": return(ParseTryStatement(context, tokens, parent));

            default:
                break;
            }

            // check for variable declaration
            int        state = tokens.CurrentState;
            CSharpType variableDeclarationType = CSharpType.TryParse(tokens);

            if (variableDeclarationType != null)
            {
                Token variableName = tokens.PopWordIfPresent();
                if (variableName != null && (tokens.IsNext(";") || tokens.IsNext("=") || tokens.IsNext(",")))
                {
                    // This is a variable declaration.
                    Executable varDecl = ParseVariableDeclaration(context, tokens, variableDeclarationType, variableName, parent);
                    if (enableSemicolon)
                    {
                        tokens.PopExpected(";");
                    }
                    return(varDecl);
                }

                tokens.RestoreState(state);
            }

            Expression expr = ExpressionParser.Parse(context, tokens, parent);

            Executable exec;

            string nextToken = tokens.PeekValue();

            switch (nextToken)
            {
            case "=":
            case "+=":
            case "-=":
            case "*=":
            case "/=":
            case "%=":
            case "|=":
            case "&=":
            case "^=":
            case "<<=":
            case ">>=":
                Token      assignmentOpToken = tokens.Pop();
                Expression assignmentValue   = ExpressionParser.Parse(context, tokens, parent);
                exec = new AssignmentStatement(expr.FirstToken, expr, assignmentOpToken, assignmentValue, parent);
                break;

            default:
                exec = new ExpressionAsExecutable(expr, parent);
                break;
            }

            if (enableSemicolon)
            {
                tokens.PopExpected(";");
            }
            return(exec);
        }