Skip to content

Commit

Permalink
Merge pull request #47 from stryku/42-implement-for-loop
Browse files Browse the repository at this point in the history
Implemented for loop
  • Loading branch information
stryku committed Jul 6, 2019
2 parents 9b32382 + 0ef6642 commit c2af9b6
Show file tree
Hide file tree
Showing 25 changed files with 1,171 additions and 220 deletions.
2 changes: 2 additions & 0 deletions source/ast/CMakeLists.txt
Expand Up @@ -7,6 +7,8 @@ set(AST_SOURCES
class_node.hpp
conditional_node.cpp
conditional_node.hpp
for_node.cpp
for_node.hpp
if_else_node.cpp
if_else_node.hpp
infix_nodes.hpp
Expand Down
4 changes: 4 additions & 0 deletions source/ast/ast_node_visitor.hpp
Expand Up @@ -18,8 +18,10 @@ class return_node;
class translation_unit_node;
class user_function_node;
class variable_declaration_node;
class standalone_variable_declaration_node;
class while_node;
class initializer_list_node;
class for_node;

class ast_node_visitor
{
Expand All @@ -43,7 +45,9 @@ class ast_node_visitor
virtual void visit(const translation_unit_node& node) = 0;
virtual void visit(const user_function_node& node) = 0;
virtual void visit(const variable_declaration_node& node) = 0;
virtual void visit(const standalone_variable_declaration_node& node) = 0;
virtual void visit(const while_node& node) = 0;
virtual void visit(const initializer_list_node& node) = 0;
virtual void visit(const for_node& node) = 0;
};
}
87 changes: 87 additions & 0 deletions source/ast/for_node.cpp
@@ -0,0 +1,87 @@
#include "ast/for_node.hpp"
#include "ast/ast_node_visitor.hpp"
#include "ast/block_node.hpp"

namespace cmsl::ast {
for_node::for_node(ast_node::token_t for_kw, ast_node::token_t open_paren,
std::unique_ptr<ast_node> init,
ast_node::token_t init_semicolon,
std::unique_ptr<ast_node> condition,
ast_node::token_t condition_semicolon,
std::unique_ptr<ast_node> iteration,
ast_node::token_t close_paren,
std::unique_ptr<block_node> body)
: m_for_kw{ for_kw }
, m_open_paren{ open_paren }
, m_init{ std::move(init) }
, m_init_semicolon{ init_semicolon }
, m_condition{ std::move(condition) }
, m_condition_semicolon{ condition_semicolon }
, m_iteration{ std::move(iteration) }
, m_close_paren{ close_paren }
, m_body{ std::move(body) }
{
}

for_node::~for_node() = default;

ast_node::token_t for_node::for_kw() const
{
return m_for_kw;
}

ast_node::token_t for_node::open_paren() const
{
return m_open_paren;
}

const ast_node* for_node::init() const
{
return m_init.get();
}

ast_node::token_t for_node::init_semicolon() const
{
return m_init_semicolon;
}

const ast_node* for_node::condition() const
{
return m_condition.get();
}

ast_node::token_t for_node::condition_semicolon() const
{
return m_condition_semicolon;
}

const ast_node* for_node::iteration() const
{
return m_iteration.get();
}

ast_node::token_t for_node::close_paren() const
{
return m_close_paren;
}

const block_node& for_node::body() const
{
return *m_body;
}

void for_node::visit(ast_node_visitor& visitor) const
{
visitor.visit(*this);
}

source_location for_node::begin_location() const
{
return m_for_kw.src_range().begin;
}

source_location for_node::end_location() const
{
return m_body->end_location();
}
}
49 changes: 49 additions & 0 deletions source/ast/for_node.hpp
@@ -0,0 +1,49 @@
#pragma once

#include "ast/ast_node.hpp"

#include <memory>

namespace cmsl::ast {

class block_node;

class for_node : public ast_node
{
public:
explicit for_node(token_t for_kw, token_t open_paren,
std::unique_ptr<ast_node> init, token_t init_semicolon,
std::unique_ptr<ast_node> condition,
token_t condition_semicolon,
std::unique_ptr<ast_node> iteration,
ast_node::token_t close_paren,
std::unique_ptr<block_node> body);
~for_node();

token_t for_kw() const;
token_t open_paren() const;
const ast_node* init() const;
token_t init_semicolon() const;
const ast_node* condition() const;
token_t condition_semicolon() const;
const ast_node* iteration() const;
token_t close_paren() const;
const block_node& body() const;

void visit(ast_node_visitor& visitor) const override;
source_location begin_location() const override;
source_location end_location() const override;

private:
token_t m_for_kw;
token_t m_open_paren;
std::unique_ptr<ast_node> m_init;
token_t m_init_semicolon;
std::unique_ptr<ast_node> m_condition;
token_t m_condition_semicolon;
std::unique_ptr<ast_node> m_iteration;
token_t m_close_paren;
std::unique_ptr<block_node> m_body;
};

}
143 changes: 128 additions & 15 deletions source/ast/parser.cpp
Expand Up @@ -3,22 +3,20 @@
#include "ast/block_node.hpp"
#include "ast/class_node.hpp"
#include "ast/conditional_node.hpp"
#include "ast/for_node.hpp"
#include "ast/if_else_node.hpp"
#include "ast/infix_nodes.hpp"
#include "ast/return_node.hpp"
#include "ast/translation_unit_node.hpp"
#include "ast/type_parser.hpp"
#include "ast/type_parsing_result.hpp"
#include "ast/user_function_node.hpp"
#include "ast/variable_declaration_node.hpp"
#include "ast/while_node.hpp"

#include "common/algorithm.hpp"
#include "common/assert.hpp"

#include "ast/type_parser.hpp"
#include "ast/type_parsing_result.hpp"
#include "errors/error.hpp"
#include "errors/errors_observer.hpp"
#include "parser.hpp"

#include <map>

Expand All @@ -42,7 +40,7 @@ std::unique_ptr<ast_node> parser::parse_translation_unit()
} else if (current_is(token_type_t::kw_class)) {
node = parse_class();
} else {
node = parse_variable_declaration();
node = parse_standalone_variable_declaration();
}

if (!node) {
Expand Down Expand Up @@ -115,7 +113,7 @@ std::unique_ptr<ast_node> parser::parse_class()

class_nodes.emplace_back(std::move(fun));
} else {
auto member = parse_variable_declaration();
auto member = parse_standalone_variable_declaration();
if (!member) {
return nullptr;
}
Expand Down Expand Up @@ -299,11 +297,13 @@ std::unique_ptr<block_node> parser::parse_block()
if (current_is(token_type_t::kw_return)) {
node = parse_return_node();
} else if (declaration_starts()) {
node = parse_variable_declaration();
node = parse_standalone_variable_declaration();
} else if (current_is(token_type_t::kw_if)) {
node = parse_if_else_node();
} else if (current_is(token_type_t::kw_while)) {
node = parse_while_node();
} else if (current_is(token_type_t::kw_for)) {
node = parse_for_node();
} else if (current_is(token_type_t::open_brace)) {
node = parse_block();
} else {
Expand Down Expand Up @@ -414,7 +414,7 @@ std::optional<parser::param_list_values> parser::param_declarations()
return param_list_values{ *open_paren, std::move(params), *close_paren };
}

std::unique_ptr<ast_node> parser::parse_variable_declaration()
std::unique_ptr<variable_declaration_node> parser::parse_variable_declaration()
{
const auto ty = parse_type();
if (!ty) {
Expand All @@ -426,26 +426,38 @@ std::unique_ptr<ast_node> parser::parse_variable_declaration()
return nullptr;
}

std::optional<variable_declaration_node::initialization_values>
std::optional<standalone_variable_declaration_node::initialization_values_t>
initialization_vals;
if (const auto equal = try_eat(token_type_t::equal)) {
auto initialization = parse_expr();
if (!initialization) {
return nullptr;
}

initialization_vals = variable_declaration_node::initialization_values{
*equal, std::move(initialization)
};
initialization_vals =
standalone_variable_declaration_node::initialization_values_t{
*equal, std::move(initialization)
};
}

return std::make_unique<variable_declaration_node>(
*ty, *name, std::move(initialization_vals));
}

std::unique_ptr<ast_node> parser::parse_standalone_variable_declaration()
{
auto variable_decl = parse_variable_declaration();
if (!variable_decl) {
return nullptr;
}

const auto semicolon = eat(token_type_t::semicolon);
if (!semicolon) {
return nullptr;
}

return std::make_unique<variable_declaration_node>(
*ty, *name, std::move(initialization_vals), *semicolon);
return std::make_unique<standalone_variable_declaration_node>(
std::move(variable_decl), *semicolon);
}

std::optional<type_representation> parser::parse_type()
Expand Down Expand Up @@ -776,4 +788,105 @@ std::unique_ptr<ast_node> parser::parse_initializer_list()
return std::make_unique<initializer_list_node>(
*open_brace, std::move(*values), *close_brace);
}

std::unique_ptr<ast_node> parser::parse_for_node()
{

const auto for_kw = eat(token_type_t::kw_for);
if (!for_kw) {
return nullptr;
}

const auto open_paren = eat(token_type_t::open_paren);
if (!open_paren) {
return nullptr;
}

auto init = parse_for_init();
if (!init.has_value()) {
return nullptr;
}

const auto init_semicolon = eat(token_type_t::semicolon);
if (!init_semicolon) {
return nullptr;
}

auto condition = parse_for_condition();
if (!condition.has_value()) {
return nullptr;
}

const auto condition_semicolon = eat(token_type_t::semicolon);
if (!condition_semicolon) {
return nullptr;
}

auto iteration = parse_for_iteration();
if (!iteration.has_value()) {
return nullptr;
}

const auto close_paren = eat(token_type_t::close_paren);
if (!close_paren) {
return nullptr;
}

auto body = parse_block();
if (!body) {
return nullptr;
}

return std::make_unique<for_node>(
*for_kw, *open_paren, std::move(*init), *init_semicolon,
std::move(*condition), *condition_semicolon, std::move(*iteration),
*close_paren, std::move(body));
}

std::optional<std::unique_ptr<ast_node>> parser::parse_for_init()
{
std::unique_ptr<ast_node> node;

if (declaration_starts()) {
node = parse_variable_declaration();
} else if (!current_is(token_type_t::semicolon)) {
node = parse_expr();
} else {
return nullptr;
}

if (!node) {
return std::nullopt;
}

return std::move(node);
}

std::optional<std::unique_ptr<ast_node>> parser::parse_for_condition()
{
if (current_is(token_type_t::semicolon)) {
return nullptr;
}

auto node = parse_expr();
if (!node) {
return std::nullopt;
}

return std::move(node);
}

std::optional<std::unique_ptr<ast_node>> parser::parse_for_iteration()
{
if (current_is(token_type_t::close_paren)) {
return nullptr;
}

auto node = parse_expr();
if (!node) {
return std::nullopt;
}

return std::move(node);
}
}

0 comments on commit c2af9b6

Please sign in to comment.