Preserving sequences

This commit is contained in:
Robert Bendun 2022-06-20 06:20:24 +02:00
parent ea1dddaf26
commit d60e2dfb38
3 changed files with 92 additions and 58 deletions

View File

@ -78,7 +78,7 @@ Result<Ast> Parser::parse(std::string_view source, std::string_view filename)
Result<Ast> Parser::parse_sequence()
{
auto seq = Try(parse_many(*this, &Parser::parse_expression, Token::Type::Expression_Separator, At_Least::Zero));
return wrap_if_several(std::move(seq), Ast::sequence);
return Ast::sequence(std::move(seq));
}
Result<Ast> Parser::parse_expression()
@ -283,14 +283,15 @@ Result<Ast> Parser::parse_atomic_expression()
}
case Token::Type::Open_Paren:
{
consume();
return parse_expression().and_then([&](Ast ast) -> Result<Ast> {
auto ast = Try(parse_sequence());
if (not expect(Token::Type::Close_Paren)) {
unimplemented("Error handling of this code is not implemented yet");
}
consume();
return ast;
});
}
default:
return Error {

View File

@ -129,6 +129,12 @@ suite intepreter_test = [] {
evaluates_to(Value::from(Number(42)), "var x = [i|i] 42; x");
};
// Added to explicitly test against bug
// Previously this test would return 10
should("respect parens in block") = [] {
evaluates_to(Value::from(Number(42)), "[(10;42)].0");
};
should("allow modifying declared variable") = [] {
evaluates_to(Value::from(Number(43)), "var x = 42; x = 43; 10; x");
};

View File

@ -10,7 +10,20 @@ void expect_ast(
{
auto result = Parser::parse(source, "test");
expect(result.has_value(), sl) << "code was expect to parse, but had not";
expect(eq(*result, expected)) << "parser yielded unexpected tree";
expect(eq(*result, expected), sl) << "parser yielded unexpected tree";
}
void expect_single_ast(
std::string_view source,
Ast const& expected,
reflection::source_location sl = reflection::source_location::current())
{
auto result = Parser::parse(source, "test");
expect(result.has_value(), sl) << "code was expect to parse, but had not";
expect(eq(result->type, Ast::Type::Sequence), sl) << "parsed does not yielded sequence";
expect(not result->arguments.empty(), sl) << "parsed yielded empty sequence";
expect(eq(result->arguments[0], expected), sl) << "parser yielded unexpected tree";
}
suite parser_test = [] {
@ -19,23 +32,23 @@ suite parser_test = [] {
};
"Literal parsing"_test = [] {
expect_ast("1", Ast::literal(Token { Token::Type::Numeric, "1", {} }));
expect_single_ast("1", Ast::literal(Token { Token::Type::Numeric, "1", {} }));
};
"Binary opreator parsing"_test = [] {
expect_ast("1 + 2", Ast::binary(
expect_single_ast("1 + 2", Ast::binary(
Token { Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Numeric, "1", {} }),
Ast::literal({ Token::Type::Numeric, "2", {} })
));
expect_ast("100 * 200", Ast::binary(
expect_single_ast("100 * 200", Ast::binary(
Token { Token::Type::Operator, "*", {} },
Ast::literal({ Token::Type::Numeric, "100", {} }),
Ast::literal({ Token::Type::Numeric, "200", {} })
));
expect_ast("101 + 202 * 303", Ast::binary(
expect_single_ast("101 + 202 * 303", Ast::binary(
Token { Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Numeric, "101", {} }),
Ast::binary(
@ -49,8 +62,8 @@ suite parser_test = [] {
// This test shouldn't be skipped since language will support precedense.
// It stays here as reminder that this feature should be implemented.
skip / "Binary operator precedense"_test = [] {
expect_ast("101 * 202 + 303", Ast::binary(
"Binary operator precedense"_test = [] {
expect_single_ast("101 * 202 + 303", Ast::binary(
Token { Token::Type::Operator, "+", {} },
Ast::binary(
Token { Token::Type::Operator, "*", {} },
@ -62,57 +75,67 @@ suite parser_test = [] {
};
"Grouping expressions in parentheses"_test = [] {
expect_ast("(101 + 202) * 303", Ast::binary(
expect_single_ast("(101 + 202) * 303", Ast::binary(
Token { Token::Type::Operator, "*", {} },
Ast::binary(
Ast::sequence({ Ast::binary(
Token { Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Numeric, "101", {} }),
Ast::literal({ Token::Type::Numeric, "202", {} })
),
)}),
Ast::literal({ Token::Type::Numeric, "303", {} })
));
expect_ast("101 * (202 + 303)", Ast::binary(
expect_single_ast("101 * (202 + 303)", Ast::binary(
Token { Token::Type::Operator, "*", {} },
Ast::literal({ Token::Type::Numeric, "101", {} }),
Ast::sequence({
Ast::binary(
Token { Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Numeric, "202", {} }),
Ast::literal({ Token::Type::Numeric, "303", {} })
)
})
));
};
"Explicit function call"_test = [] {
expect_ast("foo 1 2", Ast::call({
expect_single_ast("foo 1 2", Ast::call({
Ast::literal({ Token::Type::Symbol, "foo", {} }),
Ast::literal({ Token::Type::Numeric, "1", {} }),
Ast::literal({ Token::Type::Numeric, "2", {} })
}));
expect_ast("say (fib (n-1) + fib (n-2))", Ast::call({
should("Support function call with complicated expression") = [] {
expect_single_ast("say (fib (n-1) + fib (n-2))", Ast::call({
Ast::literal({ Token::Type::Symbol, "say", {} }),
Ast::sequence({
Ast::binary(
{ Token::Type::Operator, "+", {} },
Ast::call({
Ast::literal({ Token::Type::Symbol, "fib", {} }),
Ast::sequence({
Ast::binary(
{ Token::Type::Operator, "-", {} },
Ast::literal({ Token::Type::Symbol, "n", {} }),
Ast::literal({ Token::Type::Numeric, "1", {} })
)
})
}),
Ast::call({
Ast::literal({ Token::Type::Symbol, "fib", {} }),
Ast::sequence({
Ast::binary(
{ Token::Type::Operator, "-", {} },
Ast::literal({ Token::Type::Symbol, "n", {} }),
Ast::literal({ Token::Type::Numeric, "2", {} })
)
})
})
)
})
}));
};
};
"Sequence"_test = [] {
expect_ast("42; 101", Ast::sequence({
@ -133,15 +156,16 @@ suite parser_test = [] {
};
"Block"_test = [] {
expect_ast("[]", Ast::block(Location{}));
expect_single_ast("[]", Ast::block(Location{}));
expect_ast("[ i; j; k ]", Ast::block({}, Ast::sequence({
expect_single_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::lambda({}, Ast::binary(
expect_single_ast("[ i j k | i + j + k ]", Ast::lambda({}, Ast::sequence({
Ast::binary(
{ Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Symbol, "i", {} }),
Ast::binary(
@ -149,13 +173,16 @@ suite parser_test = [] {
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::lambda({}, Ast::binary(
expect_single_ast("[ i; j; k | i + j + k ]", Ast::lambda({}, Ast::sequence({
Ast::binary(
{ Token::Type::Operator, "+", {} },
Ast::literal({ Token::Type::Symbol, "i", {} }),
Ast::binary(
@ -163,18 +190,18 @@ suite parser_test = [] {
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("[|1]", Ast::lambda({}, Ast::literal({ Token::Type::Numeric, "1", {} }), {}));
expect_single_ast("[|1]", Ast::lambda({}, Ast::sequence({ Ast::literal({ Token::Type::Numeric, "1", {} })}), {}));
};
"Variable declarations"_test = [] {
should("Support variable declaration with assigment") = [] {
expect_ast("var x = 10", Ast::variable_declaration(
expect_single_ast("var x = 10", Ast::variable_declaration(
{},
{ Ast::literal({ Token::Type::Symbol, "x", {} }) },
Ast::literal({ Token::Type::Numeric, "10", {} })));