Block parameters accepts separators; block testing
This commit is contained in:
parent
5bfec0e77a
commit
926a68cb84
@ -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);
|
||||||
|
@ -62,7 +62,12 @@ Result<Ast> Parser::parse_atomic_expression()
|
|||||||
|
|
||||||
case Token::Type::Open_Block:
|
case Token::Type::Open_Block:
|
||||||
{
|
{
|
||||||
|
auto opening = consume();
|
||||||
|
if (expect(Token::Type::Close_Block)) {
|
||||||
consume();
|
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,18 +195,19 @@ 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;
|
|
||||||
else
|
|
||||||
ast.arguments.push_back(std::move(seq));
|
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';
|
||||||
}
|
}
|
||||||
|
@ -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", {} })
|
||||||
|
}));
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user