Skip to content
Snippets Groups Projects
Commit 29f10592 authored by Ludwig Moström's avatar Ludwig Moström
Browse files

adding declared and initilized variables to scope

parent 6afb4f1c
No related branches found
No related tags found
1 merge request!2Adds variable declaration
1+1;
numb test = 10;
2+2;
3+3;
#pragma once
#include "ast/Node.h"
#include "ast/declaration/VariableNode.h"
#include "ast/expression/LiteralNode.h"
#include "parser/Scope.h"
#include "token/Token.h"
namespace funk
{
class DeclarationNode : public Node
{
public:
DeclarationNode(const SourceLocation& location, bool is_mutable, TokenType type, const String& identifier,
ExpressionNode* initializer);
DeclarationNode(const SourceLocation& location, bool is_mutable, TokenType type, const String& identifier);
~DeclarationNode() override;
String get_identifier() const;
Node* get_initializer() const;
String to_s() const override;
String get_type() const;
Node* evaluate() const override;
private:
bool is_mutable;
TokenType type;
String identifier;
ExpressionNode* initializer;
bool has_initializer;
};
} // namespace funk
#pragma once
#include "ast/Node.h"
#include "ast/expression/ExpressionNode.h"
#include "token/TokenType.h"
namespace funk
{
class VariableNode : public ExpressionNode
{
public:
VariableNode(const SourceLocation& location, const String& identifier, bool is_mutable, TokenType type,
ExpressionNode* value);
~VariableNode() override;
Node* evaluate() const override;
String to_s() const override;
NodeValue get_value() const override;
bool get_mutable() const;
TokenType get_type() const;
const String& get_identifier() const;
ExpressionNode* get_value_node() const;
void set_value(ExpressionNode* new_value);
private:
String identifier;
bool is_mutable;
TokenType type;
ExpressionNode* value;
};
} // namespace funk
\ No newline at end of file
......@@ -13,6 +13,7 @@
#include "ast/BlockNode.h"
#include "ast/Node.h"
#include "ast/declaration/DeclarationNode.h"
#include "ast/expression/BinaryOpNode.h"
#include "ast/expression/LiteralNode.h"
#include "ast/expression/UnaryOpNode.h"
......@@ -108,6 +109,12 @@ private:
*/
Node* parse_statement();
/**
* @brief Parses a declaration
* @return Node* The AST node representing the declaration
*/
Node* parse_declaration();
/**
* @brief Parses an expression
* @return Node* The AST node representing the expression
......
#include "ast/declaration/DeclarationNode.h"
namespace funk
{
DeclarationNode::DeclarationNode(const SourceLocation& location, bool is_mutable, TokenType type,
const String& identifier, ExpressionNode* initializer) :
Node{location}, is_mutable{is_mutable}, type{type}, identifier{identifier}, initializer{initializer},
has_initializer{true}
{
}
DeclarationNode::DeclarationNode(
const SourceLocation& location, bool is_mutable, TokenType type, const String& identifier) :
Node{location}, is_mutable{is_mutable}, type{type}, identifier{identifier}, initializer{nullptr},
has_initializer{false}
{
}
DeclarationNode::~DeclarationNode()
{
if (initializer) { delete initializer; }
}
String DeclarationNode::get_identifier() const
{
return identifier;
}
Node* DeclarationNode::get_initializer() const
{
return initializer;
}
String DeclarationNode::to_s() const
{
if (has_initializer) { return "Declaration: " + identifier + " = " + initializer->to_s(); }
return "Declaration: " + identifier;
}
String DeclarationNode::get_type() const
{
return token_type_to_s(type);
}
Node* DeclarationNode::evaluate() const
{
Node* result = has_initializer ? initializer->evaluate() : new LiteralNode(get_location(), NodeValue{});
ExpressionNode* initial_value = dynamic_cast<ExpressionNode*>(result);
if (!initial_value)
{
if (result) { delete result; }
throw RuntimeError(get_location(), "Failed to evaluate initializer for '" + identifier + "'");
}
VariableNode* var = new VariableNode(get_location(), identifier, is_mutable, type, initial_value);
Scope::instance().add(identifier, var);
return var;
}
} // namespace funk
#include "ast/declaration/VariableNode.h"
namespace funk
{
VariableNode::VariableNode(
const SourceLocation& location, const String& identifier, bool is_mutable, TokenType type, ExpressionNode* value) :
ExpressionNode{location}, identifier{identifier}, is_mutable{is_mutable}, type{type}, value{value}
{
}
VariableNode::~VariableNode()
{
if (value) { delete value; }
value = nullptr;
}
Node* VariableNode::evaluate() const
{
return new VariableNode(get_location(), identifier, is_mutable, type, value);
}
String VariableNode::to_s() const
{
return "Variable: " + identifier + " = " + value->to_s();
}
NodeValue VariableNode::get_value() const
{
if (value)
{
NodeValue val = value->get_value();
return val;
}
return NodeValue{};
}
bool VariableNode::get_mutable() const
{
return is_mutable;
}
TokenType VariableNode::get_type() const
{
return type;
}
const String& VariableNode::get_identifier() const
{
return identifier;
}
ExpressionNode* VariableNode::get_value_node() const
{
return value;
}
void VariableNode::set_value(ExpressionNode* new_value)
{
if (is_mutable)
{
if (value) { delete value; }
value = new_value;
}
else { throw RuntimeError(get_location(), "Cannot modify immutable variable '" + identifier + "'"); }
}
} // namespace funk
\ No newline at end of file
......@@ -63,6 +63,8 @@ bool Parser::match(TokenType expected)
Node* Parser::parse_statement()
{
LOG_DEBUG("Parse statement");
Node* decl{parse_declaration()};
Node* expr{parse_expression()};
if (!match(TokenType::SEMICOLON))
......@@ -73,9 +75,46 @@ Node* Parser::parse_statement()
throw SyntaxError(error_loc, "Expected ';'");
}
if (decl) { return decl; }
return expr;
}
Node* Parser::parse_declaration()
{
LOG_DEBUG("Parse declaration");
bool mut{false};
if (check(TokenType::MUT))
{
mut = true;
next();
}
if (check(TokenType::NUMB_TYPE) || check(TokenType::REAL_TYPE) || check(TokenType::BOOL_TYPE) ||
check(TokenType::CHAR_TYPE) || check(TokenType::TEXT_TYPE))
{
Token type{next()};
if (check(TokenType::IDENTIFIER))
{
Token identifier{next()};
if (match(TokenType::ASSIGN))
{
// needs to be parse_statement otherwise whines about semicolon dunno if I do it correctly
Node* expr{parse_statement()};
if (!expr) { throw SyntaxError(peek_prev().get_location(), "Expected expression after '='"); }
ExpressionNode* expr_node = dynamic_cast<ExpressionNode*>(expr);
return new DeclarationNode(
type.get_location(), mut, type.get_type(), identifier.get_lexeme(), expr_node);
}
return new DeclarationNode(type.get_location(), mut, type.get_type(), identifier.get_lexeme());
}
}
return nullptr;
}
Node* Parser::parse_expression()
{
LOG_DEBUG("Parse expression");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment