Support failure tests

This commit is contained in:
2024-03-23 14:53:26 +01:00
parent 7e5f7f492d
commit f2a20c2825
14 changed files with 241 additions and 53 deletions

View File

@ -1,4 +1,5 @@
#include "elna/source/lexer.hpp"
#include <cassert>
#include <variant>
#include <sstream>
@ -212,6 +213,60 @@ namespace elna::source
|| of() == type::boolean;
}
std::string token::to_string() const
{
switch (this->m_type)
{
case type::number:
return "«number»";
case type::boolean:
return "«boolean»";
case type::term_operator:
return "«term_operator»";
case type::let:
return "«const»";
case type::identifier:
return "«identifier»";
case type::equals:
return "«=»";
case type::var:
return "«var»";
case type::semicolon:
return "«;»";
case type::left_paren:
return "«(»";
case type::right_paren:
return "«)»";
case type::dot:
return "«)»";
case type::comma:
return "«,»";
case type::factor_operator:
return "«*»";
case type::eof:
return "«EOF»";
case type::begin:
return "«begin»";
case type::end:
return "«end»";
case type::assignment:
return "«:=»";
case type::colon:
return "«:»";
case type::when:
return "«if»";
case type::then:
return "«then»";
case type::_while:
return "«while»";
case type::_do:
return "«do»";
case type::procedure:
return "«proc»";
};
assert(false);
}
unexpected_character::unexpected_character(const std::string& character, const source::position position)
: error(position), character(character)
{
@ -233,7 +288,7 @@ namespace elna::source
std::string unexpected_token::what() const
{
return "Unexpected token";
return "Unexpected token " + m_token.to_string();
}
lexer::lexer(std::vector<token>&& tokens, const position last_position)

View File

@ -49,9 +49,9 @@ namespace elna::source
void empty_visitor::visit(block *block)
{
for (const auto& block_definition : block->definitions())
for (const auto& constant : block->definitions())
{
block_definition->accept(this);
constant->accept(this);
}
for (const auto& block_declaration : block->declarations())
{
@ -83,9 +83,6 @@ namespace elna::source
{
}
/**
* AST node.
*/
void node::accept(parser_visitor *)
{
}
@ -381,14 +378,26 @@ namespace elna::source
std::unique_ptr<program> parser::parse()
{
auto definitions = parse_definitions();
auto constants = parse_constant_definitions();
auto declarations = parse_declarations();
auto procedures = parse_procedure_definitions();
auto parsed_statement = parse_statement();
if (parsed_statement == nullptr)
{
return nullptr;
}
std::vector<std::unique_ptr<definition>> definitions(constants.size() + procedures.size());
std::vector<std::unique_ptr<definition>>::iterator definition = definitions.begin();
for (auto& constant : constants)
{
*definition++ = std::move(constant);
}
for (auto& procedure : procedures)
{
*definition++ = std::move(procedure);
}
return std::make_unique<program>(std::move(definitions),
std::move(declarations), std::move(parsed_statement));
}
@ -492,6 +501,28 @@ namespace elna::source
return nullptr;
}
std::unique_ptr<procedure_definition> parser::parse_procedure_definition()
{
if (!iterator.skip(token::type::procedure))
{
return nullptr;
}
auto definition_identifier = iterator.advance(token::type::identifier);
if (!definition_identifier.has_value() || !iterator.skip(token::type::semicolon))
{
return nullptr;
}
auto definition_body = parse_block();
if (definition_body == nullptr || !iterator.skip(token::type::semicolon))
{
return nullptr;
}
return std::make_unique<procedure_definition>(definition_identifier->get().identifier(),
std::move(definition_body));
}
std::unique_ptr<declaration> parser::parse_declaration()
{
auto declaration_identifier = iterator.advance(token::type::identifier);
@ -641,9 +672,9 @@ namespace elna::source
return std::make_unique<while_statement>(std::move(condition), std::move(body));
}
std::vector<std::unique_ptr<definition>> parser::parse_definitions()
std::vector<std::unique_ptr<constant_definition>> parser::parse_constant_definitions()
{
std::vector<std::unique_ptr<definition>> definitions;
std::vector<std::unique_ptr<constant_definition>> definitions;
if (iterator->of() != token::type::let)
{
@ -651,7 +682,7 @@ namespace elna::source
}
++iterator; // Skip const.
std::unique_ptr<definition> parsed_definition;
std::unique_ptr<constant_definition> parsed_definition;
while ((parsed_definition = parse_constant_definition()) != nullptr)
{
definitions.push_back(std::move(parsed_definition));
@ -674,6 +705,23 @@ namespace elna::source
return definitions;
}
std::vector<std::unique_ptr<procedure_definition>> parser::parse_procedure_definitions()
{
std::vector<std::unique_ptr<procedure_definition>> definitions;
while (iterator.current(token::type::procedure))
{
auto parsed_definition = parse_procedure_definition();
if (parsed_definition == nullptr)
{
break;
}
definitions.push_back(std::move(parsed_definition));
}
return definitions;
}
std::vector<std::unique_ptr<declaration>> parser::parse_declarations()
{
std::vector<std::unique_ptr<declaration>> declarations;
@ -709,7 +757,7 @@ namespace elna::source
std::unique_ptr<block> parser::parse_block()
{
auto definitions = parse_definitions();
auto constants = parse_constant_definitions();
auto declarations = parse_declarations();
auto parsed_statement = parse_statement();
@ -717,6 +765,13 @@ namespace elna::source
{
return nullptr;
}
std::vector<std::unique_ptr<definition>> definitions(constants.size());
std::vector<std::unique_ptr<definition>>::iterator definition = definitions.begin();
for (auto& constant : constants)
{
*definition++ = std::move(constant);
}
return std::make_unique<block>(std::move(definitions),
std::move(declarations), std::move(parsed_statement));
}