Parse if-statements

This commit is contained in:
Sofia 2026-04-10 17:39:38 +03:00
parent f59b5db29b
commit 97745ffbb0
7 changed files with 73 additions and 2 deletions

View File

@ -28,6 +28,15 @@ namespace AST {
return out.str(); return out.str();
} }
std::string IfStatement::formatted() {
std::stringstream out{ "if " };
out << this->m_condition->formatted();
out << "\n then " << this->m_then->formatted();
if (this->m_else.has_value())
out << "\n else " << (*this->m_else)->formatted();
return out.str();
}
std::string ReturnStatement::formatted() { std::string ReturnStatement::formatted() {
std::stringstream out{ "" }; std::stringstream out{ "" };
out << "return "; out << "return ";

View File

@ -96,6 +96,24 @@ namespace AST {
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override;
}; };
class IfStatement : public Statement {
private:
std::unique_ptr<Expression> m_condition;
std::unique_ptr<Statement> m_then;
std::optional<std::unique_ptr<Statement>> m_else;
public:
IfStatement(std::unique_ptr<Expression> condition,
std::unique_ptr<Statement> then_statement,
std::optional<std::unique_ptr<Statement>> else_statement)
: m_condition{ std::move(condition) }
, m_then{ std::move(then_statement) }
, m_else{ std::move(else_statement) } {
}
virtual ~IfStatement() override = default;
virtual std::string formatted() override;
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override;
};
class TopLevelStatement : public Node { class TopLevelStatement : public Node {
public: public:
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) = 0;

View File

@ -110,6 +110,14 @@ namespace AST {
scope.values[this->m_name] = codegen::StackValue{ ptr, std::move(this->m_type) }; scope.values[this->m_name] = codegen::StackValue{ ptr, std::move(this->m_type) };
} }
void IfStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
if (!builder.block)
return;
// TODO
}
void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) { void Function::codegen(codegen::Builder& builder, codegen::Scope& scope) {
codegen::Scope inner_scope{ scope }; codegen::Scope inner_scope{ scope };

View File

@ -148,6 +148,28 @@ namespace parsing {
auto ret = new AST::ReturnStatement{ std::move(expression) }; auto ret = new AST::ReturnStatement{ std::move(expression) };
return new std::unique_ptr<AST::Statement>{ ret }; return new std::unique_ptr<AST::Statement>{ ret };
} }
else if (inner.peek().type == token::Type::IfKeyword) {
inner.next();
inner.expect(token::Type::Symbol, "(");
auto expression = parse_expression(inner).unwrap();
inner.expect(token::Type::Symbol, ")");
auto then_statement = parse_statement(inner).unwrap();
std::optional<std::unique_ptr<AST::Statement>> else_statement{};
if (inner.peek().type == token::Type::ElseKeyword) {
inner.next();
else_statement = parse_statement(inner).unwrap();
}
stream.m_position = inner.m_position;
auto statement = new AST::IfStatement{
std::move(expression),
std::move(then_statement),
std::move(else_statement)
};
return new std::unique_ptr<AST::Statement>{ statement };
}
else if (auto init = parse_init_statement(inner); init.ok()) { else if (auto init = parse_init_statement(inner); init.ok()) {
stream.m_position = inner.m_position; stream.m_position = inner.m_position;
return new std::unique_ptr<AST::Statement>{ init.unwrap() }; return new std::unique_ptr<AST::Statement>{ init.unwrap() };

View File

@ -26,6 +26,10 @@ namespace token {
case token::Type::ReturnKeyword: case token::Type::ReturnKeyword:
return "Return"; return "Return";
case token::Type::IfKeyword:
return "If";
case token::Type::ElseKeyword:
return "Else";
case token::Type::Whitespace: case token::Type::Whitespace:
return "Whitespace"; return "Whitespace";
@ -110,6 +114,12 @@ namespace token {
if (content == "return") { if (content == "return") {
type = token::Type::ReturnKeyword; type = token::Type::ReturnKeyword;
} }
else if (content == "if") {
type = token::Type::IfKeyword;
}
else if (content == "else") {
type = token::Type::ElseKeyword;
}
tokens.push_back(token::Token{ type, content }); tokens.push_back(token::Token{ type, content });
} }
else if (iswhitespace(c)) { else if (iswhitespace(c)) {

View File

@ -12,6 +12,8 @@ namespace token {
LiteralInt, LiteralInt,
ReturnKeyword, ReturnKeyword,
IfKeyword,
ElseKeyword,
Whitespace, Whitespace,

6
test.c
View File

@ -1,5 +1,7 @@
int fibonacci(int n, int b) { int fibonacci(int n) {
return 0; if (n < 2)
return 0;
return 1;
} }
int main() { int main() {