diff --git a/src/ast.h b/src/ast.h index 81e7a48..ad40435 100644 --- a/src/ast.h +++ b/src/ast.h @@ -3,6 +3,7 @@ #include "codegen.h" #include "types.h" +#include "tokens.h" #include #include @@ -11,17 +12,22 @@ namespace AST { class Node { public: + token::Metadata m_meta; + + Node(token::Metadata meta) : m_meta{ meta } {} virtual std::string formatted() = 0; virtual ~Node() = default; }; class Expression : public Node { public: + Expression(token::Metadata meta) : Node{ meta } {} virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; }; class Statement : public Node { public: + Statement(token::Metadata meta) : Node{ meta } {} virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; }; @@ -29,7 +35,7 @@ namespace AST { private: int m_value; public: - IntLiteralExpression(int value) : m_value{ value } {} + IntLiteralExpression(token::Metadata meta, int value) : Expression{ meta }, m_value{ value } {} virtual ~IntLiteralExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; @@ -39,7 +45,7 @@ namespace AST { private: std::string m_name; public: - ValueReferenceExpression(std::string name) : m_name{ name } {} + ValueReferenceExpression(token::Metadata meta, std::string name) : Expression{ meta }, m_name{ name } {} virtual ~ValueReferenceExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; @@ -51,8 +57,15 @@ namespace AST { types::BinOp m_binop; std::unique_ptr m_rhs; public: - BinaryOperationExpression(std::unique_ptr lhs, types::BinOp op, std::unique_ptr rhs) - : m_lhs{ std::move(lhs) }, m_binop{ op }, m_rhs{ std::move(rhs) } { + BinaryOperationExpression( + token::Metadata meta, + std::unique_ptr lhs, + types::BinOp op, + std::unique_ptr rhs) + : Expression{ meta } + , m_lhs{ std::move(lhs) } + , m_binop{ op } + , m_rhs{ std::move(rhs) } { } virtual ~BinaryOperationExpression() override = default; virtual std::string formatted() override; @@ -64,8 +77,13 @@ namespace AST { std::unique_ptr m_fn_expr; std::vector> m_args; public: - FunctionCallExpression(std::unique_ptr fn_expr, std::vector> args) - : m_fn_expr{ std::move(fn_expr) }, m_args{ std::move(args) } { + FunctionCallExpression( + token::Metadata meta, + std::unique_ptr fn_expr, + std::vector> args) + : Expression{ meta } + , m_fn_expr{ std::move(fn_expr) } + , m_args{ std::move(args) } { } virtual ~FunctionCallExpression() override = default; virtual std::string formatted() override; @@ -77,7 +95,9 @@ namespace AST { private: std::unique_ptr m_expr; public: - ReturnStatement(std::unique_ptr expr) : m_expr{ std::move(expr) } {} + ReturnStatement(token::Metadata meta, std::unique_ptr expr) + : Statement{ meta }, m_expr{ std::move(expr) } { + } virtual ~ReturnStatement() override = default; virtual std::string formatted() override; virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override; @@ -89,8 +109,15 @@ namespace AST { std::string m_name; std::optional> m_expr; public: - InitializationStatement(std::unique_ptr ty, std::string name, std::optional> expr) - : m_type{ std::move(ty) }, m_name{ name }, m_expr{ std::move(expr) } { + InitializationStatement( + token::Metadata meta, + std::unique_ptr ty, + std::string name, + std::optional> expr) + : Statement{ meta } + , m_type{ std::move(ty) } + , m_name{ name } + , m_expr{ std::move(expr) } { } virtual ~InitializationStatement() override = default; virtual std::string formatted() override; @@ -101,8 +128,8 @@ namespace AST { private: std::unique_ptr m_expr; public: - ExpressionStatement(std::unique_ptr expr) - : m_expr{ std::move(expr) } { + ExpressionStatement(token::Metadata meta, std::unique_ptr expr) + : Statement{ meta }, m_expr{ std::move(expr) } { } virtual ~ExpressionStatement() override = default; virtual std::string formatted() override; @@ -115,10 +142,12 @@ namespace AST { std::unique_ptr m_then; std::optional> m_else; public: - IfStatement(std::unique_ptr condition, + IfStatement(token::Metadata meta, + std::unique_ptr condition, std::unique_ptr then_statement, std::optional> else_statement) - : m_condition{ std::move(condition) } + : Statement{ meta } + , m_condition{ std::move(condition) } , m_then{ std::move(then_statement) } , m_else{ std::move(else_statement) } { } @@ -129,6 +158,7 @@ namespace AST { class TopLevelStatement : public Node { public: + TopLevelStatement(token::Metadata meta) : Node{ meta } {} virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; }; @@ -140,11 +170,13 @@ namespace AST { std::vector> m_statements; public: Function( + token::Metadata meta, std::unique_ptr return_ty, std::vector>> params, std::string name, std::vector> statements) - : m_return_ty{ std::move(return_ty) } + : TopLevelStatement{ meta } + , m_return_ty{ std::move(return_ty) } , m_params{ std::move(params) } , m_name{ name } , m_statements{ std::move(statements) } { diff --git a/src/parsing.cpp b/src/parsing.cpp index e824801..6ab34a6 100644 --- a/src/parsing.cpp +++ b/src/parsing.cpp @@ -1,5 +1,6 @@ #include "types.h" #include "parsing.h" +#include "tokens.h" namespace parsing { @@ -28,13 +29,13 @@ namespace parsing { if (token.type == token::Type::LiteralInt) { stream.m_position = inner.m_position; - auto expr = new AST::IntLiteralExpression{ std::stoi(token.content) }; + auto expr = new AST::IntLiteralExpression{ token.metadata, std::stoi(token.content) }; return new std::unique_ptr{ expr }; } else if (token.type == token::Type::Ident) { stream.m_position = inner.m_position; - auto expr = new AST::ValueReferenceExpression{ token.content }; + auto expr = new AST::ValueReferenceExpression{ token.metadata, token.content }; return new std::unique_ptr{ expr }; } else { @@ -49,6 +50,7 @@ namespace parsing { Result, std::string> parse_primary_expression(token::TokenStream& stream) { token::TokenStream inner{ stream }; try { + auto before_meta = inner.metadata(); auto plain_expr = parse_plain_expression(inner); while (inner.peek().content == "(") { inner.next(); @@ -64,7 +66,7 @@ namespace parsing { inner.expect(token::Type::Symbol, ")"); - auto fn_call = new AST::FunctionCallExpression{ plain_expr.unwrap(), std::move(args) }; + auto fn_call = new AST::FunctionCallExpression{ before_meta + inner.metadata(), plain_expr.unwrap(), std::move(args) }; plain_expr = new std::unique_ptr{ fn_call }; } @@ -115,6 +117,8 @@ namespace parsing { std::unique_ptr parse_rhs( token::TokenStream& stream, std::unique_ptr lhs, int prev_precedence) { + auto before = stream.metadata(); + auto binop_res = parse_binop(stream); while (binop_res.ok()) { auto binop = binop_res.unwrap(); @@ -124,7 +128,7 @@ namespace parsing { rhs = parse_rhs(stream, std::move(rhs), types::operator_precedence(binop)); } - auto binop_expr = new AST::BinaryOperationExpression{ std::move(lhs), binop, std::move(rhs) }; + auto binop_expr = new AST::BinaryOperationExpression{ before + stream.metadata(), std::move(lhs), binop, std::move(rhs) }; lhs = std::unique_ptr{ binop_expr }; binop_res = parse_binop(stream); @@ -147,6 +151,9 @@ namespace parsing { Result, std::string> parse_init_statement(token::TokenStream& stream) { token::TokenStream inner{ stream }; + + auto before_meta = inner.metadata(); + try { auto ty = parse_type(inner).unwrap(); auto name = inner.expect(token::Type::Ident); @@ -160,7 +167,7 @@ namespace parsing { inner.expect(token::Type::Symbol, ";"); stream.m_position = inner.m_position; - auto init = new AST::InitializationStatement{ std::move(ty), name.content, std::move(expr) }; + auto init = new AST::InitializationStatement{ before_meta + inner.metadata(), std::move(ty), name.content, std::move(expr) }; return new std::unique_ptr{ init }; } catch (std::runtime_error& error) { @@ -170,6 +177,7 @@ namespace parsing { Result, std::string> parse_statement(token::TokenStream& stream) { token::TokenStream inner{ stream }; + auto before_meta = inner.metadata(); try { if (inner.peek().type == token::Type::ReturnKeyword) { inner.next(); @@ -178,7 +186,7 @@ namespace parsing { stream.m_position = inner.m_position; - auto ret = new AST::ReturnStatement{ std::move(expression) }; + auto ret = new AST::ReturnStatement{ before_meta + stream.metadata(),std::move(expression) }; return new std::unique_ptr{ ret }; } else if (inner.peek().type == token::Type::IfKeyword) { @@ -197,6 +205,7 @@ namespace parsing { stream.m_position = inner.m_position; auto statement = new AST::IfStatement{ + before_meta + stream.metadata(), std::move(expression), std::move(then_statement), std::move(else_statement) @@ -210,7 +219,7 @@ namespace parsing { else if (auto expr = parse_expression(inner); expr.ok()) { stream.m_position = inner.m_position; stream.expect(token::Type::Symbol, ";"); - auto expr_statement = new AST::ExpressionStatement{ expr.unwrap() }; + auto expr_statement = new AST::ExpressionStatement{ before_meta + stream.metadata(), expr.unwrap() }; return new std::unique_ptr{ expr_statement }; } else { @@ -226,6 +235,7 @@ namespace parsing { Result, std::string> parse_top_level_statement(token::TokenStream& stream) { token::TokenStream inner{ stream }; + auto before_meta = inner.metadata(); try { auto type = parse_type(inner).unwrap(); auto name_token = inner.expect(token::Type::Ident); @@ -257,7 +267,7 @@ namespace parsing { stream.m_position = inner.m_position; - auto fun = new AST::Function{ std::move(type), std::move(params), name_token.content, std::move(statements) }; + auto fun = new AST::Function{ before_meta + stream.metadata(), std::move(type), std::move(params), name_token.content, std::move(statements) }; return new std::unique_ptr{ fun }; } catch (std::runtime_error& error) { diff --git a/src/tokens.cpp b/src/tokens.cpp index 9710f51..3c1518e 100644 --- a/src/tokens.cpp +++ b/src/tokens.cpp @@ -57,6 +57,14 @@ namespace token { return stream; } + Position operator+(Position pos, Position other) { + return Position{ std::min(pos.line, other.line), std::min(pos.col, other.col) }; + } + + Metadata operator+(Metadata meta, Metadata other) { + return Metadata{ meta.position + other.position, meta.filename }; + } + TokenStream::TokenStream(std::vector& tokens) : m_tokens{ tokens }, m_position{ 0 } { }; @@ -95,6 +103,10 @@ namespace token { throw std::runtime_error("Expected " + type_name(type) + "(" + std::string{ content } + "), got " + next.formatted()); } + Metadata TokenStream::metadata() { + return this->peek(0).metadata; + } + std::vector tokenize(std::string_view text, std::string filename) { std::vector tokens{}; diff --git a/src/tokens.h b/src/tokens.h index c2fdb6d..abfcd1c 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -33,6 +33,8 @@ namespace token { std::string filename; }; + Metadata operator+(Metadata meta, Metadata other); + struct Token { Type type; std::string content; @@ -52,6 +54,7 @@ namespace token { Token next(); Token expect(Type type); Token expect(Type type, std::string_view content); + Metadata metadata(); }; std::ostream& operator<<(std::ostream& stream, Token& token);