diff --git a/doc/grammar.bnf b/doc/grammar.bnf index bf89054..ff5eff2 100644 --- a/doc/grammar.bnf +++ b/doc/grammar.bnf @@ -7,9 +7,11 @@ EXPR ::= | FUNDECL | FUNCALL | LAMBDA +| BLOCK VARDECL ::= opar decl ident EXPR cpar FUNDECL ::= opar decl opar ident* cpar BODY cpar FUNCALL ::= opar EXPR EXPR* cpar LAMBDA ::= opar lambda opar PARAMS cpar BODY cpar PARAMS ::= ident* BODY ::= EXPR* +BLOCK ::= opar colon EXPR* cpar diff --git a/examples/block.gri b/examples/block.gri new file mode 100644 index 0000000..4ae230d --- /dev/null +++ b/examples/block.gri @@ -0,0 +1,2 @@ +(assert-eq? 6 (: 2 4 6)) +(assert-eq? 9 (: 2 4 (: 3 0 9))) \ No newline at end of file diff --git a/src/Compiler.cpp b/src/Compiler.cpp index a2cd7c4..22145b6 100644 --- a/src/Compiler.cpp +++ b/src/Compiler.cpp @@ -30,6 +30,7 @@ namespace grino } } break; + case NODE_BLOCK: case NODE_BODY: { for (size_t i=0; isize(); i++) { diff --git a/src/Lexer.cpp b/src/Lexer.cpp index 5ad60c0..544f17a 100644 --- a/src/Lexer.cpp +++ b/src/Lexer.cpp @@ -7,6 +7,7 @@ namespace grino : m_logger { logger } , m_loc {source_path, 1} { + add_text(NODE_COLON, ":", false); add_text(NODE_OPAR, "(", false); add_text(NODE_CPAR, ")", false); add_text(NODE_DECL, "$", false); diff --git a/src/Node.hpp b/src/Node.hpp index 85186dd..6f03099 100644 --- a/src/Node.hpp +++ b/src/Node.hpp @@ -16,7 +16,9 @@ G(NODE_DECL), \ G(NODE_LAMBDA), \ G(NODE_PARAMS), \ - G(NODE_BODY), + G(NODE_BODY), \ + G(NODE_COLON), \ + G(NODE_BLOCK) namespace grino { diff --git a/src/Parser.cpp b/src/Parser.cpp index c424a0d..1749e7c 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -118,6 +118,11 @@ namespace grino std::shared_ptr Parser::parse_expr() { + if (type_is({NODE_OPAR, NODE_COLON})) + { + return parse_block(); + } + if (type_is({NODE_OPAR, NODE_DECL, NODE_OPAR})) { return parse_fundecl(); @@ -250,4 +255,21 @@ namespace grino return node; } + std::shared_ptr Parser::parse_block() + { + auto node = make_node(NODE_BLOCK); + + consume(NODE_OPAR); + consume(NODE_COLON); + + while (!type_is(NODE_CPAR)) + { + node->add_child(parse_expr()); + } + + consume(NODE_CPAR); + + return node; + } + } diff --git a/src/Parser.hpp b/src/Parser.hpp index f7d65ae..e21f8bf 100644 --- a/src/Parser.hpp +++ b/src/Parser.hpp @@ -40,6 +40,7 @@ namespace grino std::shared_ptr parse_lambda(); std::shared_ptr parse_params(); std::shared_ptr parse_body(); + std::shared_ptr parse_block(); }; } diff --git a/tests/Lexer.cpp b/tests/Lexer.cpp index 3bc306d..f0d34b5 100644 --- a/tests/Lexer.cpp +++ b/tests/Lexer.cpp @@ -99,3 +99,12 @@ TEST_CASE_METHOD(LexerTest, "Lexer_lambda") test_next(lexer, "LAMBDA"); test_end(lexer); } + +TEST_CASE_METHOD(LexerTest, "Lexer_block") +{ + grino::Lexer lexer {m_logger, "tests/lexer"}; + + lexer.scan(" : "); + test_next(lexer, "COLON"); + test_end(lexer); +} diff --git a/tests/Parser.cpp b/tests/Parser.cpp index 5233d61..3f9f85d 100644 --- a/tests/Parser.cpp +++ b/tests/Parser.cpp @@ -81,3 +81,9 @@ TEST_CASE_METHOD(ParserTest, "Parser_fundecl") "BODY(FUNCALL(IDENT[+],IDENT[x],INT[1])))))", "($ (f x) (+ x 1))"); } + +TEST_CASE_METHOD(ParserTest, "Parser_block") +{ + test_parse("MODULE(BLOCK(INT[1],BOOL[true],IDENT[salut]))", + "(: 1 true salut )"); +}