diff --git a/src/musique.hh b/src/musique.hh index 12d4a76..c793dfa 100644 --- a/src/musique.hh +++ b/src/musique.hh @@ -317,6 +317,7 @@ struct Parser Result parse_binary_operator(); Result parse_literal(); + Result peek_type() const; Token consume(); // Tests if current token has given type diff --git a/src/parser.cc b/src/parser.cc index b85f827..8b02fc8 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -44,8 +44,28 @@ Result Parser::parse_binary_operator() Result Parser::parse_literal() { - Try(ensure(Token::Type::Numeric)); - return Ast::literal(consume()); + switch (Try(peek_type())) { + case Token::Type::Numeric: + return Ast::literal(consume()); + + case Token::Type::Open_Paren: + consume(); + return parse_expression().and_then([&](Ast ast) -> tl::expected { + Try(ensure(Token::Type::Close_Paren)); + consume(); + return ast; + }); + + default: + unimplemented(); + } +} + +Result Parser::peek_type() const +{ + return token_id >= tokens.size() + ? errors::unexpected_end_of_source(tokens.back().location) + : Result(tokens[token_id].type); } Token Parser::consume() diff --git a/src/tests/parser.cc b/src/tests/parser.cc index 9f6da36..d2ebdca 100644 --- a/src/tests/parser.cc +++ b/src/tests/parser.cc @@ -56,4 +56,26 @@ suite parser_test = [] { Ast::literal({ Token::Type::Numeric, "303", {} }) )); }; + + "Grouping expressions in parentheses"_test = [] { + expect_ast("(101 + 202) * 303", Ast::binary( + Token { Token::Type::Operator, "*", {} }, + 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( + 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", {} }) + ) + )); + }; };