Example #1
0
        public SExpr ParseExpr()
        {
            Next();
            if (next.IsRight)
            {
                return(next.Right);
            }

            if (tok.Type == TokenType.ParenOpen)
            {
                var start = tok;

                // NOTE(jsd): Built-in identifier expression parser here. Probably should extract this for general purpose usage.

                // Expect function name:
                ExpectOr(TokenType.Identifier, TokenType.Dot);
                if (next.IsRight)
                {
                    return(next.Right);
                }

                var            identStart = tok;
                IdentifierExpr ident;

                // "memberName"
                // ".memberName"
                // "namespace.Type/memberName"

                if (next.Left.Type == TokenType.Dot)
                {
                    // ".memberName":
                    Expect(TokenType.Identifier);
                    if (next.IsRight)
                    {
                        return(next.Right);
                    }

                    ident = new InstanceMemberIdentifierExpr(identStart, next.Left);

                    Next();
                    if (next.IsRight)
                    {
                        return(next.Right);
                    }
                }
                else
                {
                    // "memberName"

                    var typeNameParts = new List <Token>(5);
                    typeNameParts.Add(next.Left);

                    // "namespace.typeName" ?
                    Next();
                    while (!next.IsRight && next.Left.Type == TokenType.Dot)
                    {
                        Next();
                        if (next.Left.Type == TokenType.Slash)
                        {
                            break;
                        }
                        if (next.Left.Type != TokenType.Identifier)
                        {
                            break;
                        }

                        typeNameParts.Add(next.Left);

                        Next();
                    }
                    ;
                    if (next.IsRight)
                    {
                        return(next.Right);
                    }

                    // Determine what type of identifier:
                    if (next.Left.Type == TokenType.Slash)
                    {
                        // "namespace.typeName/memberName"
                        Expect(TokenType.Identifier);
                        if (next.IsRight)
                        {
                            return(next.Right);
                        }

                        ident = new StaticMemberIdentifierExpr(typeNameParts.ToArray(), next.Left);

                        Next();
                        if (next.IsRight)
                        {
                            return(next.Right);
                        }
                    }
                    else
                    {
                        if (typeNameParts.Count != 1)
                        {
                            return(new ParserError(tok, "Scoped identifier expression must have only one identifier part"));
                        }

                        ident = new ScopedIdentifierExpr(typeNameParts[0]);
                    }
                }

                // Parse parameters:
                List <SExpr> parameters;
                if (tok.Type == TokenType.ParenClose)
                {
                    // No parameters:
                    parameters = new List <SExpr>(0);
                }
                else
                {
                    // At least one parameter:
                    parameters = new List <SExpr>();

                    do
                    {
                        Hold();
                        var expr = ParseExpr();
                        Debug.Assert(expr != null);
                        if (expr.Kind == SExprKind.Error)
                        {
                            return(expr);
                        }

                        parameters.Add(expr);
                        Next();
                    } while (tok.Type != TokenType.ParenClose);
                }

                var end = tok;

                return(new InvocationExpr(start, end, ident, parameters.ToArray()));
            }
            else if (tok.Type == TokenType.BracketOpen)
            {
                var start = tok;

                // Parse items:
                List <SExpr> items;

                Next();
                if (next.IsRight)
                {
                    return(next.Right);
                }
                if (tok.Type == TokenType.BracketClose)
                {
                    // No items:
                    items = new List <SExpr>(0);
                }
                else
                {
                    // At least one item:
                    items = new List <SExpr>();

                    do
                    {
                        Hold();
                        var expr = ParseExpr();
                        Debug.Assert(expr != null);
                        if (expr.Kind == SExprKind.Error)
                        {
                            return(expr);
                        }

                        items.Add(expr);
                        Next();
                    } while (tok.Type != TokenType.BracketClose);
                }

                var end = tok;

                return(new ListExpr(start, end, items.ToArray()));
            }
            else if (tok.Type == TokenType.Quote)
            {
                var start = tok;

                var expr = ParseExpr();
                if (expr.Kind == SExprKind.Error)
                {
                    return(expr);
                }

                var end = tok;

                return(new QuoteExpr(start, end, expr));
            }
            else if (tok.Type == TokenType.Identifier)
            {
                var expr = new ScopedIdentifierExpr(tok);
                return(expr);
            }
            else if (tok.Type == TokenType.Integer)
            {
                long val;

                if (!Int64.TryParse(tok.Text, out val))
                {
                    return(new ParserError(tok, "Could not parse '{0}' as an Int64".F(tok.Text)));
                }

                var expr = new IntegerExpr(tok, val);
                return(expr);
            }
            else if (tok.Type == TokenType.String)
            {
                var expr = new StringExpr(tok);
                return(expr);
            }
            else if (tok.Type == TokenType.Boolean)
            {
                bool val;
                if (!Boolean.TryParse(tok.Text, out val))
                {
                    return(new ParserError(tok, "Could not parse '{0}' as a boolean".F(tok.Text)));
                }

                var expr = new BooleanExpr(tok, val);
                return(expr);
            }
            else if (tok.Type == TokenType.Null)
            {
                var expr = new NullExpr(tok);
                return(expr);
            }
            else if (tok.Type == TokenType.Decimal)
            {
                decimal val;

                if (!Decimal.TryParse(tok.Text, out val))
                {
                    return(new ParserError(tok, "Could not parse '{0}' as a decimal".F(tok.Text)));
                }

                var expr = new DecimalExpr(tok, val);
                return(expr);
            }
            else if (tok.Type == TokenType.Double)
            {
                double val;

                if (!Double.TryParse(tok.Text, out val))
                {
                    return(new ParserError(tok, "Could not parse '{0}' as a double".F(tok.Text)));
                }

                var expr = new DoubleExpr(tok, val);
                return(expr);
            }
            else if (tok.Type == TokenType.Float)
            {
                float val;

                if (!Single.TryParse(tok.Text, out val))
                {
                    return(new ParserError(tok, "Could not parse '{0}' as a float".F(tok.Text)));
                }

                var expr = new FloatExpr(tok, val);
                return(expr);
            }

            return(new ParserError(tok, "Unexpected token '{0}'".F(tok.Type)));
        }
Example #2
0
        public SExpr ParseExpr()
        {
            Next();
            if (next.IsRight) return next.Right;

            if (tok.Type == TokenType.ParenOpen)
            {
                var start = tok;

                // NOTE(jsd): Built-in identifier expression parser here. Probably should extract this for general purpose usage.

                // Expect function name:
                ExpectOr(TokenType.Identifier, TokenType.Dot);
                if (next.IsRight) return next.Right;

                var identStart = tok;
                IdentifierExpr ident;

                // "memberName"
                // ".memberName"
                // "namespace.Type/memberName"

                if (next.Left.Type == TokenType.Dot)
                {
                    // ".memberName":
                    Expect(TokenType.Identifier);
                    if (next.IsRight) return next.Right;

                    ident = new InstanceMemberIdentifierExpr(identStart, next.Left);

                    Next();
                    if (next.IsRight) return next.Right;
                }
                else
                {
                    // "memberName"

                    var typeNameParts = new List<Token>(5);
                    typeNameParts.Add(next.Left);

                    // "namespace.typeName" ?
                    Next();
                    while (!next.IsRight && next.Left.Type == TokenType.Dot)
                    {
                        Next();
                        if (next.Left.Type == TokenType.Slash)
                            break;
                        if (next.Left.Type != TokenType.Identifier)
                            break;

                        typeNameParts.Add(next.Left);

                        Next();
                    };
                    if (next.IsRight) return next.Right;

                    // Determine what type of identifier:
                    if (next.Left.Type == TokenType.Slash)
                    {
                        // "namespace.typeName/memberName"
                        Expect(TokenType.Identifier);
                        if (next.IsRight) return next.Right;

                        ident = new StaticMemberIdentifierExpr(typeNameParts.ToArray(), next.Left);

                        Next();
                        if (next.IsRight) return next.Right;
                    }
                    else
                    {
                        if (typeNameParts.Count != 1)
                            return new ParserError(tok, "Scoped identifier expression must have only one identifier part");

                        ident = new ScopedIdentifierExpr(typeNameParts[0]);
                    }
                }

                // Parse parameters:
                List<SExpr> parameters;
                if (tok.Type == TokenType.ParenClose)
                {
                    // No parameters:
                    parameters = new List<SExpr>(0);
                }
                else
                {
                    // At least one parameter:
                    parameters = new List<SExpr>();

                    do
                    {
                        Hold();
                        var expr = ParseExpr();
                        Debug.Assert(expr != null);
                        if (expr.Kind == SExprKind.Error) return expr;

                        parameters.Add(expr);
                        Next();
                    } while (tok.Type != TokenType.ParenClose);
                }

                var end = tok;

                return new InvocationExpr(start, end, ident, parameters.ToArray());
            }
            else if (tok.Type == TokenType.BracketOpen)
            {
                var start = tok;

                // Parse items:
                List<SExpr> items;

                Next();
                if (next.IsRight) return next.Right;
                if (tok.Type == TokenType.BracketClose)
                {
                    // No items:
                    items = new List<SExpr>(0);
                }
                else
                {
                    // At least one item:
                    items = new List<SExpr>();

                    do
                    {
                        Hold();
                        var expr = ParseExpr();
                        Debug.Assert(expr != null);
                        if (expr.Kind == SExprKind.Error) return expr;

                        items.Add(expr);
                        Next();
                    } while (tok.Type != TokenType.BracketClose);
                }

                var end = tok;

                return new ListExpr(start, end, items.ToArray());
            }
            else if (tok.Type == TokenType.Quote)
            {
                var start = tok;

                var expr = ParseExpr();
                if (expr.Kind == SExprKind.Error) return expr;

                var end = tok;

                return new QuoteExpr(start, end, expr);
            }
            else if (tok.Type == TokenType.Identifier)
            {
                var expr = new ScopedIdentifierExpr(tok);
                return expr;
            }
            else if (tok.Type == TokenType.Integer)
            {
                long val;

                if (!Int64.TryParse(tok.Text, out val))
                    return new ParserError(tok, "Could not parse '{0}' as an Int64".F(tok.Text));

                var expr = new IntegerExpr(tok, val);
                return expr;
            }
            else if (tok.Type == TokenType.String)
            {
                var expr = new StringExpr(tok);
                return expr;
            }
            else if (tok.Type == TokenType.Boolean)
            {
                bool val;
                if (!Boolean.TryParse(tok.Text, out val))
                    return new ParserError(tok, "Could not parse '{0}' as a boolean".F(tok.Text));

                var expr = new BooleanExpr(tok, val);
                return expr;
            }
            else if (tok.Type == TokenType.Null)
            {
                var expr = new NullExpr(tok);
                return expr;
            }
            else if (tok.Type == TokenType.Decimal)
            {
                decimal val;

                if (!Decimal.TryParse(tok.Text, out val))
                    return new ParserError(tok, "Could not parse '{0}' as a decimal".F(tok.Text));

                var expr = new DecimalExpr(tok, val);
                return expr;
            }
            else if (tok.Type == TokenType.Double)
            {
                double val;

                if (!Double.TryParse(tok.Text, out val))
                    return new ParserError(tok, "Could not parse '{0}' as a double".F(tok.Text));

                var expr = new DoubleExpr(tok, val);
                return expr;
            }
            else if (tok.Type == TokenType.Float)
            {
                float val;

                if (!Single.TryParse(tok.Text, out val))
                    return new ParserError(tok, "Could not parse '{0}' as a float".F(tok.Text));

                var expr = new FloatExpr(tok, val);
                return expr;
            }

            return new ParserError(tok, "Unexpected token '{0}'".F(tok.Type));
        }