Пример #1
0
        private Expr Unary()
        {
            if (Match(TokenType.NOT, TokenType.MINUS))
            {
                Token op    = Previous;
                Expr  right = Cast();

                if (right is Expr.Literal lit)
                {
                    var type = new TypeSpecifier {
                        Type = lit.Type, Dimensions = 0
                    };

                    if (op.Type == TokenType.NOT)
                    {
                        if (type.IsBool())
                        {
                            bool value = (bool)lit.Value;

                            return(new Expr.Literal(lit.Type, !value));
                        }
                        else
                        {
                            throw Error("Trying to invert a non-boolean value");
                        }
                    }
                    else
                    {
                        if (type.IsInt())
                        {
                            long value = (long)lit.Value;

                            return(new Expr.Literal(lit.Type, -value));
                        }
                        else if (type.IsFloat())
                        {
                            double value = (double)lit.Value;

                            return(new Expr.Literal(lit.Type, -value));
                        }
                        else
                        {
                            throw Error("Trying to negate a non-numeric value");
                        }
                    }
                }

                return(new Expr.Unary(op, right));
            }

            return(Invoke());
        }
Пример #2
0
        private Expr Relational()
        {
            var expr = Additive();

            while (Match(TokenType.GREATER, TokenType.GREATER_EQUAL, TokenType.LESS, TokenType.LESS_EQUAL))
            {
                Token op    = Previous;
                Expr  right = Additive();

                if (expr is Expr.Literal l && right is Expr.Literal r)
                {
                    var typel = new TypeSpecifier {
                        Type = l.Type, Dimensions = 0
                    };
                    var typer = new TypeSpecifier {
                        Type = r.Type, Dimensions = 0
                    };

                    if (typer.ImplicitCastableTo(typel))
                    {
                        if (typel.Type == TypeEnum.BOOL)
                        {
                            throw Error($"Boolean values are not comparable with '{op.Type}'");
                        }

                        if (typel.IsInt())
                        {
                            return(CompareLiterals <long>(op.Type, l.Value, r.Value));
                        }
                        else if (typel.IsFloat())
                        {
                            return(CompareLiterals <double>(op.Type, l.Value, r.Value));
                        }
                        else
                        {
                            throw Error("Something wrong with literal comparison");
                        }
                    }
                    else
                    {
                        throw Error($"'{typer}' not implicitly castable to '{typel}'");
                    }
                }

                expr = new Expr.Binary(expr, op, right);
            }

            return(expr);
        }
Пример #3
0
        private Stmt ForStatement()
        {
            Consume(TokenType.LEFT_PARENTH, "Expect '(' after 'for'");
            TypeSpecifier type       = TypeSpec("Must declare loop variable type");
            Token         identifier = Consume(TokenType.IDENTIFIER, "Expect identifier after type specifier");

            Consume(TokenType.IN, "Expect 'in' after loop variable identifier");

            bool istart;
            bool iend;

            if (Match(TokenType.LEFT_BRACKET))
            {
                istart = true;
            }
            else if (Match(TokenType.LEFT_PARENTH))
            {
                istart = false;
            }
            else
            {
                throw Error("Expected '[' or '(' at range start");
            }

            Expr start = Expression();

            Consume(TokenType.RANGE, "Expect '..' after range start expression");

            Expr end = Expression();

            if (Match(TokenType.RIGHT_BRACKET))
            {
                iend = true;
            }
            else if (Match(TokenType.RIGHT_PARENTH))
            {
                iend = false;
            }
            else
            {
                throw Error("Expected ']' or ')' at range end");
            }

            Consume(TokenType.RIGHT_PARENTH, "Expect ')' to finish for loop header");

            var block = Block();

            return(new Stmt.For(type, identifier, new Expr.Range(istart, iend, start, end), block));
        }
Пример #4
0
        private Stmt FunctionDeclaration()
        {
            try
            {
                TypeSpecifier typeSpecifier = TypeSpec("Function declarations must begin with a type specifier");
                Token         name          = Consume(TokenType.IDENTIFIER, "Functions must have names");
                var           paramList     = ParameterList(name.Source);
                var           functBody     = Block();

                return(new Stmt.FunctionDeclaration(typeSpecifier, name, paramList, functBody));
            }
            catch (Exception)
            {
                return(null);
            }
        }
Пример #5
0
        private Stmt VariableDeclaration()
        {
            TypeSpecifier type        = TypeSpec("");
            Token         identifier  = Consume(TokenType.IDENTIFIER, "No identifier for variable declaration");
            Binding       binding     = null;
            Expr          initializer = null;

            if (Match(TokenType.ON))
            {
                binding = Binding();
            }
            if (Match(TokenType.ASSIGN))
            {
                initializer = VariableInitializer();
            }

            Consume(TokenType.SEMICOLON, "Variable declarations end with a ';'");

            return(new Stmt.VariableDeclaration(type, identifier, binding, initializer));
        }
Пример #6
0
        private Expr Equality()
        {
            var expr = Relational();

            while (Match(TokenType.NOT_EQUAL, TokenType.EQUAL))
            {
                Token op    = Previous;
                Expr  right = Relational();

                if (expr is Expr.Literal l && right is Expr.Literal r)
                {
                    var typel = new TypeSpecifier {
                        Type = l.Type, Dimensions = 0
                    };
                    var typer = new TypeSpecifier {
                        Type = r.Type, Dimensions = 0
                    };

                    if (typer.ImplicitCastableTo(typel))
                    {
                        if (op.Type == TokenType.NOT_EQUAL)
                        {
                            return(new Expr.Literal(TypeEnum.BOOL, !l.Value.Equals(r.Value)));
                        }
                        else
                        {
                            return(new Expr.Literal(TypeEnum.BOOL, l.Value.Equals(r.Value)));
                        }
                    }
                    else
                    {
                        throw Error($"'{typer}' not implicitly castable to '{typel}'");
                    }
                }

                expr = new Expr.Binary(expr, op, right);
            }

            return(expr);
        }
Пример #7
0
        private Expr Primary()
        {
            if (Match(TokenType.TRUE))
            {
                return(new Expr.Literal(TypeEnum.BOOL, true));
            }
            if (Match(TokenType.FALSE))
            {
                return(new Expr.Literal(TypeEnum.BOOL, false));
            }
            if (Match(TokenType.INTEGER))
            {
                long num = (long)Previous.Value;

                return(new Expr.Literal(TypeSpecifier.IntFromConst(num), num));
            }
            if (Match(TokenType.FLOAT))
            {
                double num = (double)Previous.Value;

                return(new Expr.Literal(TypeSpecifier.FloatFromConst(num), num));
            }
            if (Match(TokenType.STRING))
            {
                string value = (string)Previous.Value;

                return(new Expr.Literal(TypeEnum.STRING, Regex.Unescape(value)));
            }
            if (Match(TokenType.CHAR))
            {
                return(new Expr.Literal(TypeEnum.I8, Previous.Value));
            }
            if (Match(TokenType.IDENTIFIER))
            {
                Token identifier = Previous;

                if (NextIsType(TokenType.LEFT_BRACKET))
                {
                    List <Expr> expressions = new List <Expr>();

                    while (Match(TokenType.LEFT_BRACKET))
                    {
                        var expr = Expression();
                        Consume(TokenType.RIGHT_BRACKET, "Expect ']' after array access expression");

                        expressions.Add(expr);
                    }

                    return(new Expr.IndexAccess(identifier, expressions));
                }

                return(new Expr.Variable(identifier));
            }
            if (Match(TokenType.LEFT_PARENTH))
            {
                var expr = Expression();
                Consume(TokenType.RIGHT_PARENTH, "Expect ')' after grouping expression");
                return(new Expr.Grouping(expr));
            }

            throw Error("Expect expression");
        }
Пример #8
0
        private Expr Multiplicative()
        {
            var expr = Cast();

            while (Match(TokenType.DIV, TokenType.MULT))
            {
                Token op    = Previous;
                Expr  right = Cast();

                if (expr is Expr.Literal l && right is Expr.Literal r)
                {
                    var typel = new TypeSpecifier {
                        Type = l.Type, Dimensions = 0
                    };
                    var typer = new TypeSpecifier {
                        Type = r.Type, Dimensions = 0
                    };

                    if (typer.ImplicitCastableTo(typel))
                    {
                        if (typel.IsInt())
                        {
                            long one = (long)l.Value;
                            long two = (long)r.Value;

                            if (op.Type == TokenType.DIV)
                            {
                                return(new Expr.Literal(typel.Type, one / two));
                            }
                            else
                            {
                                return(new Expr.Literal(typel.Type, one * two));
                            }
                        }
                        else if (typel.IsFloat())
                        {
                            double one = (double)l.Value;
                            double two = (double)r.Value;

                            if (op.Type == TokenType.DIV)
                            {
                                return(new Expr.Literal(typel.Type, one / two));
                            }
                            else
                            {
                                return(new Expr.Literal(typel.Type, one * two));
                            }
                        }
                        else
                        {
                            throw Error("Something wrong on Multiplicative");
                        }
                    }
                    else
                    {
                        throw Error($"'{typer}' not implicitly castable to '{typel}'");
                    }
                }

                expr = new Expr.Binary(expr, op, right);
            }

            return(expr);
        }