예제 #1
0
        internal static ParsedObject <WeakAlias> Parse(ParseSession parser)
        {
            if (!parser.CheckToken(0, "alias"))
            {
                return(null);
            }

            var nametoken = parser.PeekToken(1);

            if (nametoken == null)
            {
                return(null);
            }

            if (!parser.CheckToken(2, "="))
            {
                return(null);
            }

            parser.ConsumeTokens(4);
            var aliastype = new WeakAlias {
            };

            return(new ParsedObject <WeakAlias> {
                Name = nametoken, Object = aliastype
            });
        }
예제 #2
0
        //
        // Factory method for producing an Expression object from a token stream.
        //
        // Returns a valid Expression if one could be parsed, otherwise returns null.
        //
        // Note that the parsed expression is content-less, i.e. we don't preserve
        // any details about it. This is intentional, since IntelliSense providers
        // don't need to care about the details of an expression (yet).
        //
        // As a consequence of this, we can safely ignore things (like the relative
        // precedences of operators) because the tokens will parse the same way for
        // all cases we care about supporting. Some things like unary operators are
        // handled specially in the helper functions, but these should be viewed as
        // supporting the general goal of not interpreting the expression.
        //
        internal static Expression Parse(ParseSession parser, int starttoken, out int consumedtokens)
        {
            int totaltokens = starttoken;

            consumedtokens = totaltokens;
            bool matchedstatement = false;

            if (!ParseExpressionTerm(parser, true, totaltokens, out totaltokens, out matchedstatement))
            {
                return(null);
            }

            if (matchedstatement && parser.CheckToken(totaltokens, ")"))
            {
            }
            else
            {
                while (ParseExpressionOperator(parser, totaltokens))
                {
                    ++totaltokens;
                    if (!ParseExpressionTerm(parser, false, totaltokens, out totaltokens, out matchedstatement))
                    {
                        return(null);
                    }
                }
            }

            consumedtokens = totaltokens;
            return(new Expression());
        }
예제 #3
0
        internal static Variable Parse(ParseSession parser, int starttoken, out int consumedtokens, Origins origin)
        {
            consumedtokens = starttoken;

            if (parser.CheckToken(starttoken + 1, "."))
            {
                return(null);
            }

            var basetypename = parser.PeekToken(starttoken);

            int totaltokens = starttoken + 1;

            if (parser.CheckToken(totaltokens, "<"))
            {
                ++totaltokens;
                if (!parser.ParseTemplateArguments(totaltokens, basetypename, out totaltokens))
                {
                    return(null);
                }
            }

            var varname = parser.PeekToken(totaltokens);

            if (!parser.CheckToken(totaltokens + 1, "="))
            {
                return(null);
            }

            var type     = TypeSignatureInstantiated.Construct(parser, starttoken, totaltokens);
            var variable = new Variable {
                Name = varname, Origin = origin, Type = type
            };

            totaltokens += 2;

            Expression.Parse(parser, totaltokens, out totaltokens);
            while (parser.CheckToken(totaltokens, ","))
            {
                ++totaltokens;
                Expression.Parse(parser, totaltokens, out totaltokens);
            }

            consumedtokens = totaltokens;

            return(variable);
        }
예제 #4
0
        //
        // Helper routine for parsing an assignment statement.
        //
        // Returns true if an assignment was seen in the token stream, false
        // otherwise. A false return does not indicate a syntax error. Also
        // passes back the index of the next unexamined token.
        //
        // Assignments can have associated operations, such as "a += b".
        // They can also be "chained" as in "a = b = c". However these two
        // features may not be used in conjunction with one another.
        //
        internal static bool ParseAssignment(ParseSession parser, int starttoken, out int consumedtokens)
        {
            consumedtokens = starttoken;
            int totaltokens = starttoken;

            ++totaltokens;
            while (parser.CheckToken(totaltokens, "."))
            {
                totaltokens += 2;
            }

            if (!parser.CheckToken(totaltokens, "=") &&
                !parser.CheckToken(totaltokens, "+=") &&
                !parser.CheckToken(totaltokens, "-="))
            {
                return(false);
            }

            var assignmenttoken = parser.PeekToken(totaltokens);

            ++totaltokens;

            bool haschain = true;

            while (haschain)
            {
                while (parser.CheckToken(totaltokens + 1, "."))
                {
                    totaltokens += 2;
                }

                if (parser.CheckToken(totaltokens + 1, "="))
                {
                    if (assignmenttoken.Text != "=")
                    {
                        throw new SyntaxError("Chained assignments must all use the = assignment operator.", parser.PeekToken(totaltokens + 1));
                    }

                    ++totaltokens;
                }
                else
                {
                    haschain = false;
                }
            }

            var expr = Expression.Parse(parser, totaltokens, out totaltokens);

            if (expr == null)
            {
                return(false);
            }

            consumedtokens = totaltokens;
            return(true);
        }
예제 #5
0
        internal static ParsedObject <SumType> Parse(ParseSession parser)
        {
            int totaltokens = 0;

            if (!parser.CheckToken(0, "type"))
            {
                return(null);
            }

            Token sumtypename = parser.PeekToken(1);

            if (sumtypename == null || string.IsNullOrEmpty(sumtypename.Text))
            {
                return(null);
            }

            if (parser.CheckToken(2, "<"))
            {
                if (!parser.ParseTemplateParameters(3, sumtypename, out totaltokens))
                {
                    return(null);
                }

                if (!parser.CheckToken(totaltokens, ":"))
                {
                    return(null);
                }
            }
            else if (!parser.CheckToken(2, ":"))
            {
                return(null);
            }
            else if (!parser.CheckToken(4, "|"))
            {
                return(null);
            }
            else
            {
                totaltokens = 2;
            }

            do
            {
                ++totaltokens;

                if (parser.CheckToken(totaltokens + 1, "<"))
                {
                    var token = parser.PeekToken(totaltokens);
                    if (token == null)
                    {
                        return(null);
                    }

                    if (!parser.ParseTemplateArguments(totaltokens + 2, token, out totaltokens))
                    {
                        return(null);
                    }
                }
                else
                {
                    ++totaltokens;
                }
            } while (parser.CheckToken(totaltokens, "|"));

            // Success! Consume everything and return the constructed result
            parser.ConsumeTokens(totaltokens);
            var sumtype = new SumType {
            };

            return(new ParsedObject <SumType> {
                Name = sumtypename, Object = sumtype
            });
        }
예제 #6
0
        //
        // Helper routine for parsing a code entity from a token stream.
        //
        // This terminology is mostly legacy from an older implementation of Epoch.
        // An entity is really just a branch/flow-control construct such as a loop
        // or an if/else statement. Typically there is an expression which controls
        // execution and an associated code block.
        //
        internal static bool ParseEntity(ParseSession parser, LexicalScope parentscope, int starttoken, out int consumedtokens)
        {
            consumedtokens = starttoken;
            int totaltokens = starttoken;

            if (parser.CheckToken(totaltokens, "if"))
            {
                if (!parser.CheckToken(totaltokens + 1, "("))
                {
                    return(false);
                }

                totaltokens += 2;

                var expr = Expression.Parse(parser, totaltokens, out totaltokens);
                if (expr == null)
                {
                    throw new SyntaxError("if() statement must be supplied with a valid Boolean-typed expression", parser.ReversePeekToken());
                }

                while (parser.CheckToken(totaltokens, ")"))
                {
                    ++totaltokens;
                }

                if (!parser.CheckToken(totaltokens, "{"))
                {
                    throw new SyntaxError("if() statement must be followed by a code block surrounded in braces { }", parser.PeekToken(totaltokens));
                }

                ++totaltokens;
                LexicalScope.Parse(parser, parentscope, totaltokens, out totaltokens);

                while (parser.CheckToken(totaltokens, "elseif"))
                {
                    totaltokens += 2;
                    var condexpr = Expression.Parse(parser, totaltokens, out totaltokens);
                    if (condexpr == null)
                    {
                        throw new SyntaxError("elseif() statement must be supplied with a valid Boolean-typed expression", parser.ReversePeekToken());
                    }

                    while (parser.CheckToken(totaltokens, ")"))
                    {
                        ++totaltokens;
                    }

                    if (!parser.CheckToken(totaltokens, "{"))
                    {
                        throw new SyntaxError("elseif() statement must be followed by a code block surrounded in braces { }", parser.PeekToken(totaltokens));
                    }

                    ++totaltokens;
                    LexicalScope.Parse(parser, parentscope, totaltokens, out totaltokens);
                }

                if (parser.CheckToken(totaltokens, "else"))
                {
                    ++totaltokens;
                    if (!parser.CheckToken(totaltokens, "{"))
                    {
                        throw new SyntaxError("else statement must be followed by a code block surrounded in braces { }", parser.PeekToken(totaltokens));
                    }

                    ++totaltokens;
                    LexicalScope.Parse(parser, parentscope, totaltokens, out totaltokens);
                }

                consumedtokens = totaltokens;
                return(true);
            }
            else if (parser.CheckToken(totaltokens, "while"))
            {
                if (!parser.CheckToken(totaltokens + 1, "("))
                {
                    throw new SyntaxError("while() statement must be supplied with a valid Boolean-typed expression", parser.ReversePeekToken());
                }

                totaltokens += 2;

                while (parser.CheckToken(totaltokens, ")"))
                {
                    ++totaltokens;
                }

                var expr = Expression.Parse(parser, totaltokens, out totaltokens);
                ++totaltokens;

                if (!parser.CheckToken(totaltokens, "{"))
                {
                    throw new SyntaxError("while() statement must be followed by a code block surrounded in braces { }", parser.PeekToken(totaltokens));
                }

                ++totaltokens;
                LexicalScope.Parse(parser, parentscope, totaltokens, out totaltokens);

                consumedtokens = totaltokens;
                return(true);
            }

            return(false);
        }
예제 #7
0
        //
        // Helper function to extract an expression term from a token stream.
        //
        // Returns true if a term was found, and passes out the index of the
        // next token to examine. No tokens should be popped if this helper
        // returns false.
        //
        // Note that in cases where a terminating token is present, such as
        // a closing parenthesis or a comma, this will return false; however
        // this does not indicate a syntax error.
        //
        private static bool ParseExpressionTerm(ParseSession parser, bool atstart, int starttoken, out int consumedtokens, out bool matchedstatement)
        {
            matchedstatement = false;
            int totaltokens = starttoken;

            consumedtokens = totaltokens;

            if (parser.PeekToken(totaltokens) == null)
            {
                return(false);
            }

            if (parser.CheckToken(totaltokens, ")"))
            {
                return(false);
            }

            if (parser.CheckToken(totaltokens, ","))
            {
                return(false);
            }

            if (parser.CheckToken(totaltokens, "("))
            {
                ++totaltokens;
                if (Parse(parser, totaltokens, out totaltokens) != null)
                {
                    ++totaltokens;
                    consumedtokens = totaltokens;
                    return(true);
                }

                return(false);
            }

            if (parser.CheckToken(totaltokens, "!"))
            {
                ++totaltokens;
                var ret = ParseExpressionTerm(parser, atstart, totaltokens, out totaltokens, out matchedstatement);

                if (matchedstatement && parser.CheckToken(totaltokens, ")"))
                {
                    ++totaltokens;
                }

                consumedtokens = totaltokens;

                return(ret);
            }

            // The following check is a tiny optimization. Instead of trying to parse
            // a statement first and then eventually giving up, we first try checking
            // for common literals. This makes code with literals parse a fractional,
            // almost insignificant amount faster. It's actually a relic from the way
            // the compiler implements this logic. Maybe it makes sense to remove it,
            // and aim for simplicity over ideal efficiency. Profiling data is so far
            // insufficient to decide for sure, so this stays in the interim.
            if (parser.CheckToken(totaltokens, "false") || parser.CheckToken(totaltokens, "true") || parser.CheckToken(totaltokens, "0") || parser.CheckToken(totaltokens, "0.0"))
            {
                ++totaltokens;
            }
            else if (parser.ParsePreopStatement(totaltokens, out totaltokens))
            {
                consumedtokens = totaltokens;
                return(true);
            }
            else if (parser.ParseStatement(totaltokens, out totaltokens))
            {
                matchedstatement = true;
                consumedtokens   = totaltokens;
                return(true);
            }
            else
            {
                ++totaltokens;
            }

            consumedtokens = totaltokens;
            return(true);
        }