elna/source/parser.cpp

455 lines
12 KiB
C++
Raw Normal View History

#include "elna/source/parser.hpp"
2024-03-01 10:13:55 +01:00
#include <stdexcept>
2024-03-07 09:15:11 +01:00
namespace elna::source
2024-03-01 10:13:55 +01:00
{
/**
* AST node.
*/
2024-03-09 08:36:07 +01:00
void node::accept(parser_visitor *)
2024-03-01 10:13:55 +01:00
{
}
2024-03-10 08:50:55 +01:00
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<integer_literal>&& body)
: m_identifier(std::move(identifier)), m_body(std::move(body))
2024-03-01 10:13:55 +01:00
{
}
2024-03-10 08:50:55 +01:00
void declaration::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
2024-03-09 08:36:07 +01:00
void definition::accept(parser_visitor *visitor)
2024-03-01 10:13:55 +01:00
{
visitor->visit(this);
}
std::string& definition::identifier() noexcept
{
return m_identifier;
}
integer_literal& definition::body()
{
return *m_body;
}
2024-03-10 08:50:55 +01:00
block::block(std::vector<std::unique_ptr<definition>>&& definitions,
std::vector<std::unique_ptr<declaration>>&& declarations,
std::unique_ptr<statement>&& body)
: m_definitions(std::move(definitions)), m_declarations(std::move(declarations)), m_body(std::move(body))
{
}
2024-03-09 08:36:07 +01:00
void block::accept(parser_visitor *visitor)
2024-03-01 10:13:55 +01:00
{
visitor->visit(this);
}
statement& block::body()
{
return *m_body;
}
std::vector<std::unique_ptr<definition>>& block::definitions() noexcept
{
return m_definitions;
}
2024-03-10 08:50:55 +01:00
std::vector<std::unique_ptr<declaration>>& block::declarations() noexcept
{
return m_declarations;
}
integer_literal::integer_literal(const std::int32_t value)
: m_number(value)
{
}
2024-03-09 08:36:07 +01:00
void integer_literal::accept(parser_visitor *visitor)
2024-03-01 10:13:55 +01:00
{
visitor->visit(this);
}
std::int32_t integer_literal::number() const noexcept
{
return m_number;
}
2024-03-07 09:15:11 +01:00
variable_expression::variable_expression(const std::string& name)
: m_name(name)
{
}
2024-03-09 08:36:07 +01:00
void variable_expression::accept(parser_visitor *visitor)
2024-03-01 10:13:55 +01:00
{
visitor->visit(this);
}
2024-03-07 09:15:11 +01:00
const std::string& variable_expression::name() const noexcept
2024-03-01 10:13:55 +01:00
{
return m_name;
}
2024-03-01 10:13:55 +01:00
binary_expression::binary_expression(std::unique_ptr<expression>&& lhs,
std::unique_ptr<expression>&& rhs, const unsigned char operation)
: m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
{
switch (operation)
2024-03-01 10:13:55 +01:00
{
2024-03-03 13:11:39 +01:00
case '+':
this->m_operator = binary_operator::sum;
2024-03-03 13:11:39 +01:00
break;
case '-':
this->m_operator = binary_operator::subtraction;
2024-03-03 13:11:39 +01:00
break;
case '*':
this->m_operator = binary_operator::multiplication;
2024-03-03 13:11:39 +01:00
break;
case '/':
this->m_operator = binary_operator::division;
2024-03-03 13:11:39 +01:00
break;
default:
throw std::logic_error("Invalid binary operator");
2024-03-01 10:13:55 +01:00
}
}
2024-03-09 08:36:07 +01:00
void binary_expression::accept(parser_visitor *visitor)
2024-03-01 10:13:55 +01:00
{
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<expression>&& body)
: m_body(std::move(body))
{
}
2024-03-09 08:36:07 +01:00
void bang_statement::accept(parser_visitor *visitor)
2024-03-01 10:13:55 +01:00
{
visitor->visit(this);
}
expression& bang_statement::body()
{
return *m_body;
}
2024-03-10 08:50:55 +01:00
compound_statement::compound_statement(std::vector<std::unique_ptr<statement>>&& statements)
: m_statements(std::move(statements))
{
}
void compound_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
std::vector<std::unique_ptr<statement>>& compound_statement::statements()
{
return m_statements;
}
2024-03-11 10:43:26 +01:00
void assignment_statement::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
parser::parser(const std::vector<token>& tokens)
: tokens(tokens.cbegin()), end(tokens.cend())
{
}
std::unique_ptr<block> parser::parse()
2024-03-01 10:13:55 +01:00
{
return parse_block();
2024-03-01 10:13:55 +01:00
}
std::unique_ptr<expression> parser::parse_factor()
2024-03-01 10:13:55 +01:00
{
if (tokens->of() == source::token::type::identifier)
2024-03-01 10:13:55 +01:00
{
2024-03-07 09:15:11 +01:00
auto result = std::make_unique<variable_expression>(tokens->identifier());
++tokens;
return result;
2024-03-01 10:13:55 +01:00
}
else if (tokens->of() == source::token::token::type::number)
2024-03-01 10:13:55 +01:00
{
auto result = std::make_unique<integer_literal>(tokens->number());
++tokens;
return result;
2024-03-01 10:13:55 +01:00
}
else if (tokens->of() == source::token::type::left_paren)
2024-03-01 10:13:55 +01:00
{
++tokens;
2024-03-01 10:13:55 +01:00
auto expression = parse_expression();
2024-03-01 10:13:55 +01:00
++tokens;
2024-03-01 10:13:55 +01:00
return expression;
}
return nullptr;
}
std::unique_ptr<expression> parser::parse_term()
2024-03-01 10:13:55 +01:00
{
auto lhs = parse_factor();
if (lhs == nullptr || tokens == end || tokens->of() != source::token::type::factor_operator)
2024-03-03 13:11:39 +01:00
{
return lhs;
}
2024-03-09 08:36:07 +01:00
while (tokens->of() == source::token::type::factor_operator)
2024-03-03 13:11:39 +01:00
{
2024-03-09 08:36:07 +01:00
auto _operator = tokens->identifier()[0];
++tokens;
auto rhs = parse_factor();
lhs = std::make_unique<binary_expression>(std::move(lhs),
std::move(rhs), _operator);
2024-03-03 13:11:39 +01:00
}
2024-03-09 08:36:07 +01:00
return lhs;
2024-03-01 10:13:55 +01:00
}
std::unique_ptr<expression> parser::parse_expression()
2024-03-01 10:13:55 +01:00
{
auto term = parse_term();
if (term == nullptr || tokens == end || tokens->of() != source::token::type::term_operator)
2024-03-01 10:13:55 +01:00
{
return term;
}
2024-03-09 08:36:07 +01:00
while (tokens->of() == source::token::type::term_operator)
2024-03-01 10:13:55 +01:00
{
2024-03-09 08:36:07 +01:00
auto _operator = tokens->identifier()[0];
++tokens;
auto rhs = parse_term();
term = std::make_unique<binary_expression>(std::move(term),
std::move(rhs), _operator);
2024-03-01 10:13:55 +01:00
}
2024-03-09 08:36:07 +01:00
return term;
2024-03-01 10:13:55 +01:00
}
std::unique_ptr<definition> parser::parse_definition()
2024-03-01 10:13:55 +01:00
{
2024-03-10 08:50:55 +01:00
auto definition_identifier = advance(token::type::identifier);
2024-03-01 10:13:55 +01:00
2024-03-10 08:50:55 +01:00
if (!definition_identifier.has_value())
{
return nullptr;
}
if (!skip(token::type::equals))
{
return nullptr;
}
2024-03-01 10:13:55 +01:00
if (tokens->of() == source::token::type::number)
2024-03-01 10:13:55 +01:00
{
2024-03-10 08:50:55 +01:00
auto result = std::make_unique<definition>(definition_identifier.value().get().identifier(),
std::make_unique<integer_literal>(tokens->number()));
++tokens;
return result;
2024-03-01 10:13:55 +01:00
}
return nullptr;
}
2024-03-10 08:50:55 +01:00
std::unique_ptr<declaration> parser::parse_declaration()
{
auto declaration_identifier = advance(token::type::identifier);
if (!declaration_identifier.has_value())
{
return nullptr;
}
return std::make_unique<declaration>(declaration_identifier.value().get().identifier());
}
std::unique_ptr<statement> parser::parse_statement()
2024-03-01 10:13:55 +01:00
{
if (tokens->of() == source::token::type::bang)
2024-03-01 10:13:55 +01:00
{
2024-03-10 08:50:55 +01:00
return parse_bang_statement();
2024-03-01 10:13:55 +01:00
}
2024-03-10 08:50:55 +01:00
else if (tokens->of() == source::token::type::begin)
{
return parse_compound_statement();
}
errors.push_back(std::make_unique<unexpected_token>(unexpected_token{ *tokens }));
2024-03-01 10:13:55 +01:00
return nullptr;
}
2024-03-10 08:50:55 +01:00
std::unique_ptr<bang_statement> parser::parse_bang_statement()
2024-03-01 10:13:55 +01:00
{
2024-03-10 08:50:55 +01:00
if (!advance(token::type::bang))
{
return nullptr;
}
auto bang_body = parse_expression();
2024-03-01 10:13:55 +01:00
2024-03-10 08:50:55 +01:00
if (bang_body != nullptr)
{
return std::make_unique<bang_statement>(std::move(bang_body));
}
return nullptr;
}
std::unique_ptr<compound_statement> parser::parse_compound_statement()
{
if (!advance(token::type::begin))
{
return nullptr;
}
auto result = std::make_unique<compound_statement>();
std::unique_ptr<statement> next_statement;
2024-03-01 10:13:55 +01:00
2024-03-11 10:43:26 +01:00
while ((next_statement = parse_statement()) != nullptr)
2024-03-01 10:13:55 +01:00
{
2024-03-11 10:43:26 +01:00
result->statements().push_back(std::move(next_statement));
if (tokens->of() == token::type::semicolon)
2024-03-01 10:13:55 +01:00
{
2024-03-11 10:43:26 +01:00
++tokens;
}
else if (tokens->of() == token::type::end)
{
++tokens;
break;
}
else
{
errors.push_back(std::make_unique<unexpected_token>(*tokens));
break;
2024-03-01 10:13:55 +01:00
}
2024-03-10 08:50:55 +01:00
}
return result;
}
std::vector<std::unique_ptr<definition>> parser::parse_definitions()
{
std::vector<std::unique_ptr<definition>> definitions;
if (tokens->of() != token::type::let)
{
return definitions;
}
++tokens; // Skip const.
std::unique_ptr<definition> parsed_definition;
while ((parsed_definition = parse_definition()) != nullptr)
{
definitions.push_back(std::move(parsed_definition));
2024-03-01 10:13:55 +01:00
2024-03-10 08:50:55 +01:00
if (tokens->of() == source::token::type::comma)
2024-03-01 10:13:55 +01:00
{
2024-03-10 08:50:55 +01:00
++tokens;
2024-03-01 10:13:55 +01:00
}
2024-03-10 08:50:55 +01:00
else if (tokens->of() == source::token::type::semicolon)
2024-03-01 10:13:55 +01:00
{
++tokens;
2024-03-10 08:50:55 +01:00
break;
}
else
{
errors.push_back(std::make_unique<unexpected_token>(*tokens));
break;
2024-03-01 10:13:55 +01:00
}
}
return definitions;
}
2024-03-10 08:50:55 +01:00
std::vector<std::unique_ptr<declaration>> parser::parse_declarations()
2024-03-01 10:13:55 +01:00
{
2024-03-10 08:50:55 +01:00
std::vector<std::unique_ptr<declaration>> declarations;
if (tokens->of() != token::type::var)
2024-03-01 10:13:55 +01:00
{
2024-03-10 08:50:55 +01:00
return declarations;
}
++tokens; // Skip var.
std::unique_ptr<declaration> 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<unexpected_token>(*tokens));
break;
}
2024-03-01 10:13:55 +01:00
}
2024-03-10 08:50:55 +01:00
return declarations;
}
std::unique_ptr<block> parser::parse_block()
{
auto definitions = parse_definitions();
auto declarations = parse_declarations();
auto parsed_statement = parse_statement();
if (parsed_statement == nullptr)
2024-03-01 10:13:55 +01:00
{
return nullptr;
}
2024-03-10 08:50:55 +01:00
return std::make_unique<block>(std::move(definitions),
std::move(declarations), std::move(parsed_statement));
}
std::optional<std::reference_wrapper<const token>> 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<unexpected_token>(*tokens));
return std::optional<std::reference_wrapper<const token>>();
}
bool parser::skip(const token::type token_type)
{
if (tokens->of() == token_type)
{
++tokens;
return true;
}
errors.push_back(std::make_unique<unexpected_token>(*tokens));
return false;
2024-03-01 10:13:55 +01:00
}
}