Preserving sequences
This commit is contained in:
parent
ea1dddaf26
commit
d60e2dfb38
@ -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> {
|
||||
{
|
||||
consume();
|
||||
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 {
|
||||
|
@ -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");
|
||||
};
|
||||
|
@ -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,56 +75,66 @@ 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::binary(
|
||||
Token { Token::Type::Operator, "+", {} },
|
||||
Ast::literal({ Token::Type::Numeric, "202", {} }),
|
||||
Ast::literal({ Token::Type::Numeric, "303", {} })
|
||||
)
|
||||
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({
|
||||
Ast::literal({ Token::Type::Symbol, "say", {} }),
|
||||
Ast::binary(
|
||||
{ Token::Type::Operator, "+", {} },
|
||||
Ast::call({
|
||||
Ast::literal({ Token::Type::Symbol, "fib", {} }),
|
||||
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::literal({ Token::Type::Symbol, "n", {} }),
|
||||
Ast::literal({ Token::Type::Numeric, "1", {} })
|
||||
)
|
||||
}),
|
||||
Ast::call({
|
||||
Ast::literal({ Token::Type::Symbol, "fib", {} }),
|
||||
Ast::binary(
|
||||
{ Token::Type::Operator, "-", {} },
|
||||
Ast::literal({ Token::Type::Symbol, "n", {} }),
|
||||
Ast::literal({ Token::Type::Numeric, "2", {} })
|
||||
{ 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 = [] {
|
||||
@ -133,48 +156,52 @@ 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(
|
||||
{ Token::Type::Operator, "+", {} },
|
||||
Ast::literal({ Token::Type::Symbol, "i", {} }),
|
||||
expect_single_ast("[ i j k | i + j + k ]", Ast::lambda({}, Ast::sequence({
|
||||
Ast::binary(
|
||||
{ Token::Type::Operator, "+", {} },
|
||||
Ast::literal({ Token::Type::Symbol, "j", {} }),
|
||||
Ast::literal({ Token::Type::Symbol, "k", {} })
|
||||
)
|
||||
), {
|
||||
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::lambda({}, Ast::binary(
|
||||
{ Token::Type::Operator, "+", {} },
|
||||
Ast::literal({ Token::Type::Symbol, "i", {} }),
|
||||
expect_single_ast("[ i; j; k | i + j + k ]", Ast::lambda({}, Ast::sequence({
|
||||
Ast::binary(
|
||||
{ Token::Type::Operator, "+", {} },
|
||||
Ast::literal({ Token::Type::Symbol, "j", {} }),
|
||||
Ast::literal({ Token::Type::Symbol, "k", {} })
|
||||
)
|
||||
), {
|
||||
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("[|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", {} })));
|
||||
|
Loading…
Reference in New Issue
Block a user