diff --git a/src/ast.cpp b/src/ast.cpp index 64e179e..e1978d6 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -3,6 +3,37 @@ #include namespace AST { + int operator_precedence(BinOp& op) { + return 0; + } + + std::string format_operator(BinOp& op) { + switch (op) { + case BinOp::Assignment: + return "="; + default: + return "??"; + } + } + + std::string IntLiteralExpression::formatted() { + std::stringstream out{ "" }; + out << this->m_value; + return out.str(); + } + + std::string ValueReferenceExpression::formatted() { + return this->m_name; + } + + std::string BinaryOperationExpression::formatted() { + std::stringstream out{ "" }; + out << this->m_lhs->formatted(); + out << " " << format_operator(this->m_binop) << " "; + out << this->m_rhs->formatted(); + return out.str(); + } + std::string ExpressionStatement::formatted() { std::stringstream out{ "" }; out << this->m_expr->formatted(); @@ -28,16 +59,6 @@ namespace AST { return out.str(); } - std::string IntLiteralExpression::formatted() { - std::stringstream out{ "" }; - out << this->m_value; - return out.str(); - } - - std::string ValueReferenceExpression::formatted() { - return this->m_name; - } - std::string Function::formatted() { std::stringstream out{ "" }; out << this->m_name; diff --git a/src/ast.h b/src/ast.h index e32a6c8..537b77f 100644 --- a/src/ast.h +++ b/src/ast.h @@ -8,6 +8,13 @@ #include namespace AST { + enum class BinOp { + Assignment, + }; + + int operator_precedence(BinOp& op); + std::string format_operator(BinOp& op); + class Node { public: virtual std::string formatted() = 0; @@ -51,6 +58,20 @@ namespace AST { virtual llvm::Value* codegen(codegen::Builder& builder, codegen::Scope& scope) override; }; + class BinaryOperationExpression : public Expression { + private: + std::unique_ptr m_lhs; + BinOp m_binop; + std::unique_ptr m_rhs; + public: + BinaryOperationExpression(std::unique_ptr lhs, BinOp op, std::unique_ptr rhs) + : m_lhs{ std::move(lhs) }, m_binop{ op }, m_rhs{ std::move(rhs) } { + } + virtual ~BinaryOperationExpression() override = default; + virtual std::string formatted() override; + virtual llvm::Value* codegen(codegen::Builder& builder, codegen::Scope& scope) override; + }; + class ReturnStatement : public Statement { private: diff --git a/src/codegen.cpp b/src/codegen.cpp index f213dbc..c7e406c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -22,6 +22,11 @@ namespace AST { } } + llvm::Value* BinaryOperationExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { + auto ty = builder.builder->getInt32Ty(); + return llvm::ConstantInt::get(ty, 0); + } + void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) { if (!builder.block) return; diff --git a/src/parsing.cpp b/src/parsing.cpp index c20a4eb..f03903d 100644 --- a/src/parsing.cpp +++ b/src/parsing.cpp @@ -18,7 +18,7 @@ namespace parsing { } } - Result, std::string> parse_expression(token::TokenStream& stream) { + Result, std::string> parse_primary_expression(token::TokenStream& stream) { token::TokenStream inner{ stream }; try { auto token = inner.next(); @@ -43,6 +43,58 @@ namespace parsing { } } + Result parse_binop(token::TokenStream& stream) { + token::TokenStream inner{ stream }; + try { + auto token = inner.next(); + if (token.type != token::Type::Symbol) { + throw std::runtime_error("Expected binop"); + } + if (token.content == "=") { + stream.m_position = inner.m_position; + return new AST::BinOp{ AST::BinOp::Assignment }; + } + + throw std::runtime_error("Expected binop"); + } + catch (std::runtime_error error) { + return new std::string{ error.what() }; + } + } + + std::unique_ptr parse_rhs( + token::TokenStream& stream, std::unique_ptr lhs, int prev_precedence) { + + auto binop_res = parse_binop(stream); + while (binop_res.ok()) { + auto binop = binop_res.unwrap(); + auto rhs = parse_primary_expression(stream).unwrap(); + + if (AST::operator_precedence(binop) > prev_precedence) { + rhs = parse_rhs(stream, std::move(rhs), AST::operator_precedence(binop)); + } + + auto binop_expr = new AST::BinaryOperationExpression{ std::move(lhs), binop, std::move(rhs) }; + lhs = std::unique_ptr{ binop_expr }; + + binop_res = parse_binop(stream); + } + + return lhs; + } + + Result, std::string> parse_expression(token::TokenStream& stream) { + try { + auto lhs = parse_primary_expression(stream).unwrap(); + return new std::unique_ptr{ parse_rhs(stream, std::move(lhs), 0) }; + } + catch (std::runtime_error error) { + return new std::string{ error.what() }; + } + } + + + Result, std::string> parse_init_statement(token::TokenStream& stream) { token::TokenStream inner{ stream }; try { diff --git a/test.c b/test.c index 4e45ea1..fec75fc 100644 --- a/test.c +++ b/test.c @@ -1,5 +1,5 @@ int main() { int a = 5; - a; + a = 15; return a; } \ No newline at end of file