From 926a68cb84b41265b76f0caf689e4966eeb7d6df Mon Sep 17 00:00:00 2001 From: Robert Bendun Date: Sun, 15 May 2022 22:22:26 +0200 Subject: [PATCH] Block parameters accepts separators; block testing --- src/musique.hh | 4 ++-- src/parser.cc | 47 +++++++++++++++++++++------------------------ src/tests/parser.cc | 38 ++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/musique.hh b/src/musique.hh index 82e3c39..9a5f51f 100644 --- a/src/musique.hh +++ b/src/musique.hh @@ -291,7 +291,7 @@ struct Ast static Ast binary(Token, Ast lhs, Ast rhs); static Ast call(std::vector call); static Ast sequence(std::vector call); - static Ast block(Ast seq, std::vector parameters = {}); + static Ast block(Location location, Ast seq = sequence({}), std::vector parameters = {}); enum class Type { @@ -303,9 +303,9 @@ struct Ast }; Type type; + Location location; Token token; std::vector arguments{}; - std::vector parameters{}; }; bool operator==(Ast const& lhs, Ast const& rhs); diff --git a/src/parser.cc b/src/parser.cc index 2803fe9..26b0c43 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -62,7 +62,12 @@ Result Parser::parse_atomic_expression() 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; std::vector parameters; @@ -76,7 +81,7 @@ Result Parser::parse_atomic_expression() return parse_sequence().and_then([&](Ast ast) -> tl::expected { 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 Parser::parse_atomic_expression() Result 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> parse_one_or_more(Parser &p, Result (Parser::*parser)(), std::optional 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 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,19 +195,20 @@ Ast Ast::sequence(std::vector 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 parameters) +Ast Ast::block(Location location, Ast seq, std::vector 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.arguments.push_back(std::move(seq)); + 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'; } diff --git a/src/tests/parser.cc b/src/tests/parser.cc index 7bebfc9..0117597 100644 --- a/src/tests/parser.cc +++ b/src/tests/parser.cc @@ -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", {} }) + })); + }; };