diff --git a/doc/grammar.bnf b/doc/grammar.bnf index 90a533d..bf89054 100644 --- a/doc/grammar.bnf +++ b/doc/grammar.bnf @@ -4,9 +4,11 @@ EXPR ::= | int | ident | VARDECL +| FUNDECL | FUNCALL | LAMBDA 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* diff --git a/examples/fun.gri b/examples/fun.gri index 13ee527..088a5a2 100644 --- a/examples/fun.gri +++ b/examples/fun.gri @@ -7,4 +7,8 @@ (assert-eq? 12 (b a 3)) ;; calling function literal -(assert-eq? 7 ( (-> (x y) (+ x y 1)) 2 4 )) \ No newline at end of file +(assert-eq? 7 ( (-> (x y) (+ x y 1)) 2 4 )) + +;; syntaxic sugar for function declaration +($ (c n) (* 2 n)) +(assert-eq? 18 (c 9)) \ No newline at end of file diff --git a/src/Parser.cpp b/src/Parser.cpp index 00f9d0e..c424a0d 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_DECL, NODE_OPAR})) + { + return parse_fundecl(); + } + if (type_is({NODE_OPAR, NODE_DECL})) { return parse_vardecl(); @@ -164,6 +169,31 @@ namespace grino return node; } + std::shared_ptr Parser::parse_fundecl() + { + consume(NODE_OPAR); + consume(NODE_DECL); + + consume(NODE_OPAR); + auto ident = consume(NODE_IDENT); + + auto params = parse_params(); + consume(NODE_CPAR); + + auto body = parse_body(); + consume(NODE_CPAR); + + auto lambda = make_node(NODE_LAMBDA); + lambda->add_child(params); + lambda->add_child(body); + + auto node = make_node(NODE_VARDECL); + node->add_child(ident); + node->add_child(lambda); + + return node; + } + std::shared_ptr Parser::parse_funcall() { consume(NODE_OPAR); diff --git a/src/Parser.hpp b/src/Parser.hpp index 29041c6..f7d65ae 100644 --- a/src/Parser.hpp +++ b/src/Parser.hpp @@ -35,6 +35,7 @@ namespace grino std::shared_ptr parse_module(); std::shared_ptr parse_expr(); std::shared_ptr parse_vardecl(); + std::shared_ptr parse_fundecl(); std::shared_ptr parse_funcall(); std::shared_ptr parse_lambda(); std::shared_ptr parse_params(); diff --git a/tests/Parser.cpp b/tests/Parser.cpp index e69fcd4..5233d61 100644 --- a/tests/Parser.cpp +++ b/tests/Parser.cpp @@ -74,3 +74,10 @@ TEST_CASE_METHOD(ParserTest, "Parser_lambda") "( (-> (x) x ) 4 )"); } + +TEST_CASE_METHOD(ParserTest, "Parser_fundecl") +{ + test_parse("MODULE(VARDECL(IDENT[f],LAMBDA(PARAMS(IDENT[x])," + "BODY(FUNCALL(IDENT[+],IDENT[x],INT[1])))))", + "($ (f x) (+ x 1))"); +}