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 binary(Token, Ast lhs, Ast rhs);
static Ast call(std::vector<Ast> call); static Ast call(std::vector<Ast> call);
static Ast sequence(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 enum class Type
{ {
@ -303,9 +303,9 @@ struct Ast
}; };
Type type; Type type;
Location location;
Token token; Token token;
std::vector<Ast> arguments{}; std::vector<Ast> arguments{};
std::vector<Ast> parameters{};
}; };
bool operator==(Ast const& lhs, Ast const& rhs); 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: case Token::Type::Open_Block:
{ {
consume(); auto opening = consume();
if (expect(Token::Type::Close_Block)) {
consume();
return Ast::block(std::move(opening).location);
}
auto start = token_id; auto start = token_id;
std::vector<Ast> parameters; 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> { return parse_sequence().and_then([&](Ast ast) -> tl::expected<Ast, Error> {
Try(ensure(Token::Type::Close_Block)); Try(ensure(Token::Type::Close_Block));
consume(); 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() Result<Ast> Parser::parse_identifier()
{ {
Try(ensure(Token::Type::Symbol)); 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) 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 ast;
ast.type = Type::Literal; ast.type = Type::Literal;
ast.location = token.location;
ast.token = std::move(token); ast.token = std::move(token);
return ast; return ast;
} }
@ -165,6 +173,7 @@ Ast Ast::binary(Token token, Ast lhs, Ast rhs)
{ {
Ast ast; Ast ast;
ast.type = Type::Binary; ast.type = Type::Binary;
ast.location = token.location;
ast.token = std::move(token); ast.token = std::move(token);
ast.arguments.push_back(std::move(lhs)); ast.arguments.push_back(std::move(lhs));
ast.arguments.push_back(std::move(rhs)); 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) 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 ast;
ast.type = Type::Call; ast.type = Type::Call;
ast.location = call.front().location;
ast.arguments = std::move(call); ast.arguments = std::move(call);
return ast; return ast;
} }
@ -183,19 +195,20 @@ Ast Ast::sequence(std::vector<Ast> expressions)
{ {
Ast ast; Ast ast;
ast.type = Type::Sequence; ast.type = Type::Sequence;
if (!expressions.empty()) {
ast.location = expressions.front().location;
}
ast.arguments = std::move(expressions); ast.arguments = std::move(expressions);
return ast; 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 ast;
ast.type = Type::Block; ast.type = Type::Block;
ast.parameters = std::move(parameters); ast.location = location;
if (seq.type == Type::Sequence) ast.arguments = std::move(parameters);
ast.arguments = std::move(seq).arguments; ast.arguments.push_back(std::move(seq));
else
ast.arguments.push_back(std::move(seq));
return ast; return ast;
} }
@ -255,13 +268,6 @@ std::ostream& operator<<(std::ostream& os, Ast const& tree)
os << '}'; os << '}';
} }
if (!tree.parameters.empty()) {
os << " with parameters { ";
for (auto const& arg : tree.parameters) {
os << arg << ' ';
}
os << '}';
}
return os; return os;
} }
@ -290,14 +296,5 @@ void dump(Ast const& tree, unsigned indent)
} }
std::cout << i << '}'; 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'; 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", {} })
}));
};
}; };