From 17c5293fcf0f917da3383f76dfa162f7b5acd7f0 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Sat, 12 Dec 2015 22:41:40 -0500 Subject: [PATCH] Completed function literal parsing --- source/ast.c | 23 ++++++++++++++------ source/grammar.c | 24 ++++++++++----------- source/pprint.c | 9 ++++++-- source/sclpl.h | 10 ++++++--- spec/parser_spec.rb | 52 ++++++++++++++++++++++----------------------- 5 files changed, 68 insertions(+), 50 deletions(-) diff --git a/source/ast.c b/source/ast.c index 2497c91..c7f6964 100644 --- a/source/ast.c +++ b/source/ast.c @@ -30,7 +30,7 @@ static void ast_free(void* ptr) break; case AST_FUNC: - gc_delref(ast->value.func.args); + //vec_deinit(&(ast->value.func.args)); gc_delref(ast->value.func.body); break; @@ -238,17 +238,17 @@ AST* block_get(AST* block, size_t index) return (AST*)vec_at(&(block->value.exprs), index); } -AST* Func(AST* args, AST* body) +AST* Func(void) { AST* node = ast(AST_FUNC); - node->value.func.args = args; - node->value.func.body = body; + vec_init(&(node->value.func.args)); + node->value.func.body = NULL; return node; } -AST* func_args(AST* func) +vec_t* func_args(AST* func) { - return func->value.func.args; + return &(func->value.func.args); } AST* func_body(AST* func) @@ -256,6 +256,17 @@ AST* func_body(AST* func) return func->value.func.body; } +void func_add_arg(AST* func, AST* arg) +{ + vec_push_back(func_args(func), arg); +} + +void func_set_body(AST* func, AST* body) +{ + func->value.func.body = body; +} + + //AST* Ann(char* name, AST* value) //{ // (void)name; diff --git a/source/grammar.c b/source/grammar.c index f70a25c..49aa084 100644 --- a/source/grammar.c +++ b/source/grammar.c @@ -21,9 +21,9 @@ AST* toplevel(Parser* p) if (!match(p, T_END_FILE)) { if (accept_str(p, T_ID, "require")) ret = require(p); - else if (accept_str(p, T_ID, "def")) { + else if (accept_str(p, T_ID, "def")) ret = definition(p); - } else + else ret = expression(p); } //printf("%p\n", ret); @@ -49,15 +49,13 @@ static AST* definition(Parser* p) static AST* require(Parser* p) { - Tok* tok = expect(p, T_STRING); - AST* ast = Require(tok); + AST* ast = Require(expect(p, T_STRING)); expect(p, T_END); return ast; } static AST* expression(Parser* p) { - if (accept(p, T_LPAR)) { AST* expr = expression(p); expect(p, T_RPAR); @@ -74,7 +72,6 @@ static AST* expression(Parser* p) } else { return literal(p); } - } static AST* if_stmnt(Parser* p) @@ -91,16 +88,17 @@ static AST* if_stmnt(Parser* p) static AST* function(Parser* p) { + AST* func = Func(); expect(p, T_LPAR); - //while(peek(p)->type != T_RPAR) { - // expect(p, T_ID); - // if(peek(p)->type != T_RPAR) - // expect(p, T_COMMA); - //} + while(peek(p)->type != T_RPAR) { + func_add_arg(func, Ident(expect(p,T_ID))); + if(peek(p)->type != T_RPAR) + expect(p, T_COMMA); + } expect(p, T_RPAR); - AST* body = expr_block(p); + func_set_body(func, expr_block(p)); expect(p, T_END); - return Func(NULL,body); + return func; } static AST* literal(Parser* p) diff --git a/source/pprint.c b/source/pprint.c index 52721e3..9b49226 100644 --- a/source/pprint.c +++ b/source/pprint.c @@ -88,7 +88,7 @@ static const char* tree_type_to_string(ASTType type) { switch(type) { case AST_STRING: return "T_STRING"; case AST_SYMBOL: return "T_SYMBOL"; - case AST_IDENT: return "T_IDENT"; + case AST_IDENT: return "T_ID"; case AST_CHAR: return "T_CHAR"; case AST_INT: return "T_INT"; case AST_FLOAT: return "T_FLOAT"; @@ -153,7 +153,12 @@ void pprint_tree(FILE* file, AST* tree, int depth) break; case AST_FUNC: - printf("(fn ()"); + printf("(fn ("); + for (size_t i = 0; i < vec_size(func_args(tree)); i++) { + printf(" "); + pprint_literal(file, vec_at(func_args(tree), i), depth); + } + printf(")"); for (size_t i = 0; i < block_size(func_body(tree)); i++) { printf(" "); pprint_tree(file, block_get(func_body(tree), i), depth); diff --git a/source/sclpl.h b/source/sclpl.h index 14a5700..ceb023a 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -101,7 +101,7 @@ typedef struct AST { } ifexpr; /* Function */ struct { - struct AST* args; + vec_t args; struct AST* body; } func; /* Code Block */ @@ -172,9 +172,13 @@ size_t block_size(AST* block); AST* block_get(AST* block, size_t index); /* Function */ -AST* Func(AST* args, AST* body); -AST* func_args(AST* func); +AST* Func(void); +vec_t* func_args(AST* func); AST* func_body(AST* func); +void func_add_arg(AST* func, AST* arg); +void func_set_body(AST* func, AST* body); + + ///* Annotation */ //AST* Ann(char* name, AST* value); diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb index 545e4c6..9f25e4f 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -23,7 +23,7 @@ describe "sclpl grammar" do end it "should parse an identifier" do - expect(ast('foo')).to eq(['T_IDENT:foo']) + expect(ast('foo')).to eq(['T_ID:foo']) end end @@ -143,23 +143,23 @@ describe "sclpl grammar" do expect(ast('def foo() 123 321;')).to eq([ ['def', 'foo', ['fn', [], 'T_INT:123', 'T_INT:321']] ]) end -# -# it "should parse a function definition with one argument" do -# expect(ast('def foo(a) 123;')).to eq([ -# ['T_ID:def', 'T_ID:foo', ['T_ID:fn', ['T_ID:a'], 'T_INT:123']] ]) -# end -# -# it "should parse a function definition with two arguments" do -# expect(ast('def foo(a,b) 123;')).to eq([ -# ['T_ID:def', 'T_ID:foo', ['T_ID:fn', ['T_ID:a', 'T_ID:b'], 'T_INT:123']] ]) -# end -# -# it "should parse a function definition with three arguments" do -# expect(ast('def foo(a,b,c) 123;')).to eq([ -# ['T_ID:def', 'T_ID:foo', ['T_ID:fn', ['T_ID:a', 'T_ID:b', 'T_ID:c'], 'T_INT:123']] ]) -# end + + it "should parse a function definition with one argument" do + expect(ast('def foo(a) 123;')).to eq([ + ['def', 'foo', ['fn', ['T_ID:a'], 'T_INT:123']] ]) + end + + it "should parse a function definition with two arguments" do + expect(ast('def foo(a,b) 123;')).to eq([ + ['def', 'foo', ['fn', ['T_ID:a', 'T_ID:b'], 'T_INT:123']] ]) + end + + it "should parse a function definition with three arguments" do + expect(ast('def foo(a,b,c) 123;')).to eq([ + ['def', 'foo', ['fn', ['T_ID:a', 'T_ID:b', 'T_ID:c'], 'T_INT:123']] ]) + end end -# + # context "annotations" do # it "should parse a type annotation for a simple type" do # expect(ast('ann foo int;')).to eq([ ['T_ID:ann', 'T_ID:foo', 'T_ID:int'] ]) @@ -195,16 +195,16 @@ describe "sclpl grammar" do it "should parse a function with no params" do expect(ast('fn() 123;')).to eq([["fn", [], "T_INT:123"]]) end -# -# it "should parse a function with one param" do -# expect(ast('fn(a) 123;')).to eq([["T_ID:fn", ["T_ID:a"], "T_INT:123"]]) -# end -# -# it "should parse a function with two params" do -# expect(ast('fn(a,b) 123;')).to eq([["T_ID:fn", ["T_ID:a", "T_ID:b"], "T_INT:123"]]) -# end + + it "should parse a function with one param" do + expect(ast('fn(a) 123;')).to eq([["fn", ["T_ID:a"], "T_INT:123"]]) + end + + it "should parse a function with two params" do + expect(ast('fn(a,b) 123;')).to eq([["fn", ["T_ID:a", "T_ID:b"], "T_INT:123"]]) + end end -# + # context "function application" do # it "should parse an application with no params " do # expect(ast('foo()')).to eq([["T_ID:foo"]]) -- 2.52.0