Block parameters accepts separators; block testing

This commit is contained in:
Robert Bendun 2022-05-15 22:22:26 +02:00
parent 5bfec0e77a
commit 926a68cb84
3 changed files with 62 additions and 27 deletions

View File

@ -291,7 +291,7 @@ struct Ast
static Ast binary(Token, Ast lhs, Ast rhs);
static Ast call(std::vector<Ast> call);
static Ast sequence(std::vector<Ast> call);
static Ast block(Ast seq, std::vector<Ast> parameters = {});
static Ast block(Location location, Ast seq = sequence({}), std::vector<Ast> parameters = {});
enum class Type
{
@ -303,9 +303,9 @@ struct Ast
};
Type type;
Location location;
Token token;
std::vector<Ast> arguments{};
std::vector<Ast> parameters{};
};
bool operator==(Ast const& lhs, Ast const& rhs);

View File

@ -62,7 +62,12 @@ Result<Ast> Parser::parse_atomic_expression()
case Token::Type::Open_Block:
{
auto opening = consume();
if (expect(Token::Type::Close_Block)) {
consume();
return Ast::block(std::move(opening).location);
}
auto start = token_id;
std::vector<Ast> parameters;
@ -76,7 +81,7 @@ Result<Ast> Parser::parse_atomic_expression()
return parse_sequence().and_then([&](Ast ast) -> tl::expected<Ast, Error> {
Try(ensure(Token::Type::Close_Block));
consume();
return Ast::block(ast, std::move(parameters));
return Ast::block(opening.location, ast, std::move(parameters));
});
}
@ -98,7 +103,9 @@ Result<Ast> Parser::parse_atomic_expression()
Result<Ast> Parser::parse_identifier()
{
Try(ensure(Token::Type::Symbol));
return Ast::literal(consume());
auto lit = Ast::literal(consume());
while (expect(Token::Type::Expression_Separator)) { consume(); }
return lit;
}
Result<std::vector<Ast>> parse_one_or_more(Parser &p, Result<Ast> (Parser::*parser)(), std::optional<Token::Type> separator)
@ -157,6 +164,7 @@ Ast Ast::literal(Token token)
{
Ast ast;
ast.type = Type::Literal;
ast.location = token.location;
ast.token = std::move(token);
return ast;
}
@ -165,6 +173,7 @@ Ast Ast::binary(Token token, Ast lhs, Ast rhs)
{
Ast ast;
ast.type = Type::Binary;
ast.location = token.location;
ast.token = std::move(token);
ast.arguments.push_back(std::move(lhs));
ast.arguments.push_back(std::move(rhs));
@ -173,8 +182,11 @@ Ast Ast::binary(Token token, Ast lhs, Ast rhs)
Ast Ast::call(std::vector<Ast> call)
{
assert(!call.empty(), "Call must have at least pice of code that is beeing called");
Ast ast;
ast.type = Type::Call;
ast.location = call.front().location;
ast.arguments = std::move(call);
return ast;
}
@ -183,18 +195,19 @@ Ast Ast::sequence(std::vector<Ast> expressions)
{
Ast ast;
ast.type = Type::Sequence;
if (!expressions.empty()) {
ast.location = expressions.front().location;
}
ast.arguments = std::move(expressions);
return ast;
}
Ast Ast::block(Ast seq, std::vector<Ast> parameters)
Ast Ast::block(Location location, Ast seq, std::vector<Ast> parameters)
{
Ast ast;
ast.type = Type::Block;
ast.parameters = std::move(parameters);
if (seq.type == Type::Sequence)
ast.arguments = std::move(seq).arguments;
else
ast.location = location;
ast.arguments = std::move(parameters);
ast.arguments.push_back(std::move(seq));
return ast;
}
@ -255,13 +268,6 @@ std::ostream& operator<<(std::ostream& os, Ast const& tree)
os << '}';
}
if (!tree.parameters.empty()) {
os << " with parameters { ";
for (auto const& arg : tree.parameters) {
os << arg << ' ';
}
os << '}';
}
return os;
}
@ -290,14 +296,5 @@ void dump(Ast const& tree, unsigned indent)
}
std::cout << i << '}';
}
if (!tree.parameters.empty()) {
std::cout << " with parameters {\n";
for (auto const& arg : tree.parameters) {
dump(arg, +i);
}
std::cout << i << '}';
}
std::cout << '\n';
}

View File

@ -127,4 +127,42 @@ suite parser_test = [] {
})
}));
};
"Block"_test = [] {
expect_ast("[]", Ast::block(Location{}));
expect_ast("[ i; j; k ]", Ast::block({}, Ast::sequence({
Ast::literal({ Token::Type::Symbol, "i", {} }),
Ast::literal({ Token::Type::Symbol, "j", {} }),
Ast::literal({ Token::Type::Symbol, "k", {} })
}), {}));
expect_ast("[ i j k | i + j + k ]", Ast::block({}, Ast::binary(
{ Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Symbol, "i", {} }),
Ast::binary(
{ Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Symbol, "j", {} }),
Ast::literal({ Token::Type::Symbol, "k", {} })
)
), {
Ast::literal({ Token::Type::Symbol, "i", {} }),
Ast::literal({ Token::Type::Symbol, "j", {} }),
Ast::literal({ Token::Type::Symbol, "k", {} })
}));
expect_ast("[ i; j; k | i + j + k ]", Ast::block({}, Ast::binary(
{ Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Symbol, "i", {} }),
Ast::binary(
{ Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Symbol, "j", {} }),
Ast::literal({ Token::Type::Symbol, "k", {} })
)
), {
Ast::literal({ Token::Type::Symbol, "i", {} }),
Ast::literal({ Token::Type::Symbol, "j", {} }),
Ast::literal({ Token::Type::Symbol, "k", {} })
}));
};
};