#include "elna/source/parser.hpp" #include namespace elna::source { /** * AST node. */ void node::accept(parser_visitor *) { } declaration::declaration(const std::string& identifier) : m_identifier(identifier) { } std::string& declaration::identifier() noexcept { return m_identifier; } definition::definition(const std::string& identifier, std::unique_ptr&& body) : m_identifier(std::move(identifier)), m_body(std::move(body)) { } void declaration::accept(parser_visitor *visitor) { visitor->visit(this); } 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::vector>&& declarations, std::unique_ptr&& body) : m_definitions(std::move(definitions)), m_declarations(std::move(declarations)), 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; } std::vector>& block::declarations() noexcept { return m_declarations; } 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; } compound_statement::compound_statement(std::vector>&& statements) : m_statements(std::move(statements)) { } void compound_statement::accept(parser_visitor *visitor) { visitor->visit(this); } std::vector>& compound_statement::statements() { return m_statements; } 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() { auto definition_identifier = advance(token::type::identifier); if (!definition_identifier.has_value()) { return nullptr; } if (!skip(token::type::equals)) { return nullptr; } if (tokens->of() == source::token::type::number) { auto result = std::make_unique(definition_identifier.value().get().identifier(), std::make_unique(tokens->number())); ++tokens; return result; } return nullptr; } std::unique_ptr parser::parse_declaration() { auto declaration_identifier = advance(token::type::identifier); if (!declaration_identifier.has_value()) { return nullptr; } return std::make_unique(declaration_identifier.value().get().identifier()); } std::unique_ptr parser::parse_statement() { if (tokens->of() == source::token::type::bang) { return parse_bang_statement(); } else if (tokens->of() == source::token::type::begin) { return parse_compound_statement(); } errors.push_back(std::make_unique(unexpected_token{ *tokens })); return nullptr; } std::unique_ptr parser::parse_bang_statement() { if (!advance(token::type::bang)) { return nullptr; } auto bang_body = parse_expression(); if (bang_body != nullptr) { return std::make_unique(std::move(bang_body)); } return nullptr; } std::unique_ptr parser::parse_compound_statement() { if (!advance(token::type::begin)) { return nullptr; } auto result = std::make_unique(); std::unique_ptr next_statement; do { if ((next_statement = parse_statement()) == nullptr) { return nullptr; } result->statements().push_back(std::move(next_statement)); } while (tokens->of() != token::type::end); ++tokens; return result; } std::vector> parser::parse_definitions() { std::vector> definitions; if (tokens->of() != token::type::let) { return definitions; } ++tokens; // Skip const. std::unique_ptr parsed_definition; while ((parsed_definition = parse_definition()) != nullptr) { definitions.push_back(std::move(parsed_definition)); if (tokens->of() == source::token::type::comma) { ++tokens; } else if (tokens->of() == source::token::type::semicolon) { ++tokens; break; } else { errors.push_back(std::make_unique(*tokens)); break; } } return definitions; } std::vector> parser::parse_declarations() { std::vector> declarations; if (tokens->of() != token::type::var) { return declarations; } ++tokens; // Skip var. std::unique_ptr parsed_declaration; while ((parsed_declaration = parse_declaration()) != nullptr) { declarations.push_back(std::move(parsed_declaration)); if (tokens->of() == token::type::comma) { ++tokens; } else if (tokens->of() == token::type::semicolon) { ++tokens; break; } else { errors.push_back(std::make_unique(*tokens)); break; } } return declarations; } std::unique_ptr parser::parse_block() { auto definitions = parse_definitions(); auto declarations = parse_declarations(); auto parsed_statement = parse_statement(); if (parsed_statement == nullptr) { return nullptr; } return std::make_unique(std::move(definitions), std::move(declarations), std::move(parsed_statement)); } std::optional> parser::advance(const token::type token_type) { if (tokens->of() == token_type) { return std::make_optional<>(std::cref(*tokens++)); } errors.push_back(std::make_unique(*tokens)); return std::optional>(); } bool parser::skip(const token::type token_type) { if (tokens->of() == token_type) { ++tokens; return true; } errors.push_back(std::make_unique(*tokens)); return false; } }