#include "elna/source/parser.hpp" #include namespace elna::source { /** * AST node. */ void node::accept(parser_visitor *) { } definition::definition(std::string&& identifier, std::unique_ptr&& body) : m_identifier(std::move(identifier)), m_body(std::move(body)) { } void definition::accept(parser_visitor *visitor) { visitor->visit(this); } std::string& definition::identifier() noexcept { return m_identifier; } integer_literal& definition::body() { return *m_body; } block::block(std::vector>&& definitions, std::unique_ptr&& body) : m_definitions(std::move(definitions)), m_body(std::move(body)) { } void block::accept(parser_visitor *visitor) { visitor->visit(this); } statement& block::body() { return *m_body; } std::vector>& block::definitions() noexcept { return m_definitions; } integer_literal::integer_literal(const std::int32_t value) : m_number(value) { } void integer_literal::accept(parser_visitor *visitor) { visitor->visit(this); } std::int32_t integer_literal::number() const noexcept { return m_number; } variable_expression::variable_expression(const std::string& name) : m_name(name) { } void variable_expression::accept(parser_visitor *visitor) { visitor->visit(this); } const std::string& variable_expression::name() const noexcept { return m_name; } binary_expression::binary_expression(std::unique_ptr&& lhs, std::unique_ptr&& rhs, const unsigned char operation) : m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) { switch (operation) { case '+': this->m_operator = binary_operator::sum; break; case '-': this->m_operator = binary_operator::subtraction; break; case '*': this->m_operator = binary_operator::multiplication; break; case '/': this->m_operator = binary_operator::division; break; default: throw std::logic_error("Invalid binary operator"); } } void binary_expression::accept(parser_visitor *visitor) { visitor->visit(this); } expression& binary_expression::lhs() { return *m_lhs; } expression& binary_expression::rhs() { return *m_rhs; } binary_operator binary_expression::operation() const noexcept { return m_operator; } bang_statement::bang_statement(std::unique_ptr&& body) : m_body(std::move(body)) { } void bang_statement::accept(parser_visitor *visitor) { visitor->visit(this); } expression& bang_statement::body() { return *m_body; } parser::parser(const std::vector& tokens) : tokens(tokens.cbegin()), end(tokens.cend()) { } std::unique_ptr parser::parse() { return parse_block(); } std::unique_ptr parser::parse_factor() { if (tokens->of() == source::token::type::identifier) { auto result = std::make_unique(tokens->identifier()); ++tokens; return result; } else if (tokens->of() == source::token::token::type::number) { auto result = std::make_unique(tokens->number()); ++tokens; return result; } else if (tokens->of() == source::token::type::left_paren) { ++tokens; auto expression = parse_expression(); ++tokens; return expression; } return nullptr; } std::unique_ptr parser::parse_term() { auto lhs = parse_factor(); if (lhs == nullptr || tokens == end || tokens->of() != source::token::type::factor_operator) { return lhs; } while (tokens->of() == source::token::type::factor_operator) { auto _operator = tokens->identifier()[0]; ++tokens; auto rhs = parse_factor(); lhs = std::make_unique(std::move(lhs), std::move(rhs), _operator); } return lhs; } std::unique_ptr parser::parse_expression() { auto term = parse_term(); if (term == nullptr || tokens == end || tokens->of() != source::token::type::term_operator) { return term; } while (tokens->of() == source::token::type::term_operator) { auto _operator = tokens->identifier()[0]; ++tokens; auto rhs = parse_term(); term = std::make_unique(std::move(term), std::move(rhs), _operator); } return term; } std::unique_ptr parser::parse_definition() { std::string definition_identifier = tokens->identifier(); // Copy. ++tokens; ++tokens; // Skip the equals sign. if (tokens->of() == source::token::type::number) { auto result = std::make_unique(std::move(definition_identifier), std::make_unique(tokens->number())); ++tokens; return result; } return nullptr; } std::unique_ptr parser::parse_bang_statement() { if (tokens->of() == source::token::type::bang) { ++tokens; auto bang_body = parse_expression(); if (bang_body != nullptr) { return std::make_unique(std::move(bang_body)); } } return nullptr; } std::vector> parser::parse_definitions() { ++tokens; // Skip const. std::vector> definitions; while (tokens != end) { auto parsed_definition = parse_definition(); if (parsed_definition == nullptr) { return definitions; } definitions.push_back(std::move(parsed_definition)); if (tokens->of() == source::token::type::semicolon) { break; } if (tokens->of() == source::token::type::comma) { ++tokens; } } return definitions; } std::unique_ptr parser::parse_block() { std::vector> definitions; if (tokens->of() == source::token::type::let) { definitions = parse_definitions(); ++tokens; } auto parsed_statement = parse_bang_statement(); if (parsed_statement == nullptr) { return nullptr; } return std::make_unique(std::move(definitions), std::move(parsed_statement)); } }