Get rid of the raw pointers in the parser

This commit is contained in:
2024-03-06 07:51:56 +01:00
parent d2516cb76c
commit 4dbf3ddb47
12 changed files with 601 additions and 562 deletions

View File

@ -1,254 +1,294 @@
#include "elna/parser.hpp"
#include "elna/source/parser.hpp"
#include <stdexcept>
namespace elna
{
namespace source
{
/**
* AST node.
*/
void Node::accept(ParserVisitor *)
void node::accept(ParserVisitor *)
{
}
void Definition::accept(ParserVisitor *visitor)
definition::definition(std::string&& identifier, std::unique_ptr<integer_literal>&& body)
: m_identifier(std::move(identifier)), m_body(std::move(body))
{
}
void definition::accept(ParserVisitor *visitor)
{
visitor->visit(this);
}
void Block::accept(ParserVisitor *visitor)
std::string& definition::identifier() noexcept
{
return m_identifier;
}
integer_literal& definition::body()
{
return *m_body;
}
block::block(std::vector<std::unique_ptr<definition>>&& definitions, std::unique_ptr<statement>&& body)
: m_definitions(std::move(definitions)), m_body(std::move(body))
{
}
void block::accept(ParserVisitor *visitor)
{
visitor->visit(this);
}
void Expression::accept(ParserVisitor *visitor)
statement& block::body()
{
return *m_body;
}
std::vector<std::unique_ptr<definition>>& block::definitions() noexcept
{
return m_definitions;
}
integer_literal::integer_literal(const std::int32_t value)
: m_number(value)
{
}
void integer_literal::accept(ParserVisitor *visitor)
{
visitor->visit(this);
}
void Number::accept(ParserVisitor *visitor)
std::int32_t integer_literal::number() const noexcept
{
return m_number;
}
variable::variable(const std::string& name)
: m_name(name)
{
}
void variable::accept(ParserVisitor *visitor)
{
visitor->visit(this);
}
void Variable::accept(ParserVisitor *visitor)
const std::string& variable::name() const noexcept
{
visitor->visit(this);
return m_name;
}
BinaryExpression::BinaryExpression(Expression *lhs, Expression *rhs, unsigned char _operator)
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))
{
this->lhs = lhs;
this->rhs = rhs;
switch (_operator)
switch (operation)
{
case '+':
this->_operator = BinaryOperator::sum;
this->m_operator = binary_operator::sum;
break;
case '-':
this->_operator = BinaryOperator::subtraction;
this->m_operator = binary_operator::subtraction;
break;
case '*':
this->_operator = BinaryOperator::multiplication;
this->m_operator = binary_operator::multiplication;
break;
case '/':
this->_operator = BinaryOperator::division;
this->m_operator = binary_operator::division;
break;
default:
throw std::logic_error("Invalid binary operator");
}
}
void BinaryExpression::accept(ParserVisitor *visitor)
void binary_expression::accept(ParserVisitor *visitor)
{
visitor->visit(this);
}
void BangStatement::accept(ParserVisitor *visitor)
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))
{
}
void bang_statement::accept(ParserVisitor *visitor)
{
visitor->visit(this);
}
Block *parse(lex::Token *tokenStream, std::size_t length)
expression& bang_statement::body()
{
return parseBlock(&tokenStream, &length);
return *m_body;
}
Expression *parseFactor(lex::Token **tokens, size_t *length)
parser::parser(const std::vector<token>& tokens)
: tokens(tokens.cbegin()), end(tokens.cend())
{
if ((*tokens)[0].of() == lex::Token::type::identifier)
{
auto variable = new Variable();
variable->identifier = (*tokens)[0].identifier();
++(*tokens);
--(*length);
return variable;
}
else if ((*tokens)[0].of() == lex::Token::Token::type::number)
{
auto number = new Number();
number->value = (*tokens)[0].number();
++(*tokens);
--(*length);
return number;
}
else if ((*tokens)[0].of() == lex::Token::type::left_paren)
{
++(*tokens);
--(*length);
}
auto expression = parseExpression(tokens, length);
std::unique_ptr<block> parser::parse()
{
return parse_block();
}
++(*tokens);
--(*length);
std::unique_ptr<expression> parser::parse_factor()
{
if (tokens->of() == source::token::type::identifier)
{
auto result = std::make_unique<variable>(tokens->identifier());
++tokens;
return result;
}
else if (tokens->of() == source::token::token::type::number)
{
auto result = std::make_unique<integer_literal>(tokens->number());
++tokens;
return result;
}
else if (tokens->of() == source::token::type::left_paren)
{
++tokens;
auto expression = parse_expression();
++tokens;
return expression;
}
return nullptr;
}
Expression *parseTerm(lex::Token **tokens, size_t *length)
std::unique_ptr<expression> parser::parse_term()
{
auto lhs = parseFactor(tokens, length);
if (lhs == nullptr || *length == 0 || (*tokens)[0].of() != lex::Token::type::factor_operator)
auto lhs = parse_factor();
if (lhs == nullptr || tokens == end || tokens->of() != source::token::type::factor_operator)
{
return lhs;
}
auto _operator = (*tokens)[0].identifier()[0];
++(*tokens);
--(*length);
auto _operator = tokens->identifier()[0];
++tokens;
auto rhs = parseFactor(tokens, length);
auto rhs = parse_factor();
if (rhs != nullptr)
{
return new BinaryExpression(lhs, rhs, _operator);
return std::make_unique<binary_expression>(std::move(lhs),
std::move(rhs), _operator);
}
return nullptr;
}
Expression *parseExpression(lex::Token **tokens, size_t *length)
std::unique_ptr<expression> parser::parse_expression()
{
auto term = parseTerm(tokens, length);
if (term == nullptr || *length == 0 || (*tokens)[0].of() != lex::Token::type::term_operator)
auto term = parse_term();
if (term == nullptr || tokens == end || tokens->of() != source::token::type::term_operator)
{
return term;
}
auto _operator = (*tokens)[0].identifier()[0];
++(*tokens);
--(*length);
auto _operator = tokens->identifier()[0];
++tokens;
auto expression = parseExpression(tokens, length);
auto rhs = parse_expression();
if (expression != nullptr)
if (rhs != nullptr)
{
return new BinaryExpression(term, expression, _operator);
return std::make_unique<binary_expression>(std::move(term),
std::move(rhs), _operator);
}
return nullptr;
}
Definition *parseDefinition(lex::Token **tokens, size_t *length)
std::unique_ptr<definition> parser::parse_definition()
{
auto definition = new Definition();
definition->identifier = (*tokens)[0].identifier(); // Copy.
std::string definition_identifier = tokens->identifier(); // Copy.
++(*tokens);
++(*tokens); // Skip the equals sign.
*length -= 2;
++tokens;
++tokens; // Skip the equals sign.
if ((*tokens)[0].of() == lex::Token::type::number)
if (tokens->of() == source::token::type::number)
{
auto number = new Number();
number->value = (*tokens)[0].number();
definition->number = number;
++(*tokens);
--(*length);
return definition;
auto result = std::make_unique<definition>(std::move(definition_identifier),
std::make_unique<integer_literal>(tokens->number()));
++tokens;
return result;
}
return nullptr;
}
Statement *parseStatement(lex::Token **tokens, std::size_t *length)
std::unique_ptr<statement> parser::parse_bang_statement()
{
if ((*tokens)[0].of() == lex::Token::type::bang)
if (tokens->of() == source::token::type::bang)
{
++(*tokens);
--(*length);
auto statement = new BangStatement();
auto expression = parseExpression(tokens, length);
if (expression != nullptr)
++tokens;
auto bang_body = parse_expression();
if (bang_body != nullptr)
{
statement->expression = expression;
return std::make_unique<bang_statement>(std::move(bang_body));
}
else
{
return nullptr;
}
return statement;
}
return nullptr;
}
Definition **parseDefinitions(lex::Token **tokens, size_t *length, size_t *resultLength)
std::vector<std::unique_ptr<definition>> parser::parse_definitions()
{
++(*tokens); // Skip const.
--(*length);
++tokens; // Skip const.
Definition **definitions;
*resultLength = 0;
std::vector<std::unique_ptr<definition>> definitions;
while (*length != 0)
while (tokens != end)
{
auto definition = parseDefinition(tokens, length);
if (definition == nullptr)
auto parsed_definition = parse_definition();
if (parsed_definition == nullptr)
{
return nullptr;
return definitions;
}
definitions = reinterpret_cast<Definition **>(
realloc(definitions, (*resultLength + 1) * sizeof(Definition*)));
definitions[(*resultLength)++] = definition;
definitions.push_back(std::move(parsed_definition));
if ((*tokens)[0].of() == lex::Token::type::semicolon)
if (tokens->of() == source::token::type::semicolon)
{
break;
}
if ((*tokens)[0].of() == lex::Token::type::comma)
if (tokens->of() == source::token::type::comma)
{
++(*tokens);
--(*length);
++tokens;
}
}
return definitions;
}
Block *parseBlock(lex::Token **tokens, std::size_t *length)
std::unique_ptr<block> parser::parse_block()
{
auto block = new Block();
if ((*tokens)[0].of() == lex::Token::type::let)
std::vector<std::unique_ptr<definition>> definitions;
if (tokens->of() == source::token::type::let)
{
size_t length_ = 0;
auto constDefinitions = parseDefinitions(tokens, length, &length_);
if (constDefinitions != nullptr)
{
block->definitionsLength = length_;
block->definitions = constDefinitions;
}
else
{
return nullptr;
}
++(*tokens);
--(*length);
definitions = parse_definitions();
++tokens;
}
auto statement = parseStatement(tokens, length);
if (statement != nullptr)
{
block->statement = statement;
}
else
auto parsed_statement = parse_bang_statement();
if (parsed_statement == nullptr)
{
return nullptr;
}
return block;
return std::make_unique<block>(std::move(definitions), std::move(parsed_statement));
}
}
}