From: Michael D. Lowis Date: Tue, 15 Dec 2015 03:54:37 +0000 (-0500) Subject: Started adding function application to the parser X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=072a7e35048f786e58700e574af6e022b42f6999;p=proto%2Fsclpl.git Started adding function application to the parser --- diff --git a/Makefile b/Makefile index a6495c6..281ffba 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ LD = ${CC} # flags INCS = -Isource/ CPPFLAGS = -D_XOPEN_SOURCE=700 -CFLAGS += ${INCS} ${CPPFLAGS} -Wall -Wextra +CFLAGS += ${INCS} ${CPPFLAGS} LDFLAGS += ${LIBS} #------------------------------------------------------------------------------ diff --git a/source/ast.c b/source/ast.c index 6eb8f66..3332931 100644 --- a/source/ast.c +++ b/source/ast.c @@ -30,7 +30,7 @@ static void ast_free(void* ptr) break; case AST_FUNC: - //vec_deinit(&(ast->value.func.args)); + vec_deinit(&(ast->value.func.args)); gc_delref(ast->value.func.body); break; @@ -266,6 +266,19 @@ void func_set_body(AST* func, AST* body) func->value.func.body = (AST*)gc_addref(body); } +AST* FnApp(AST* fn) +{ + AST* node = ast(AST_FNAPP); + node->value.fnapp.fn = (AST*)gc_addref(fn); + vec_init(&(node->value.fnapp.args)); + return node; +} + +void fnapp_add_arg(AST* func, AST* arg) +{ + vec_push_back(&(func->value.fnapp.args), gc_addref(arg)); +} + //AST* Ann(char* name, AST* value) //{ diff --git a/source/grammar.c b/source/grammar.c index 49aa084..aef5ce2 100644 --- a/source/grammar.c +++ b/source/grammar.c @@ -14,6 +14,7 @@ static AST* function(Parser* p); static AST* literal(Parser* p); static AST* expr_block(Parser* p); static AST* token_to_tree(Tok* tok); +static AST* func_app(Parser* p, AST* fn); AST* toplevel(Parser* p) { @@ -56,22 +57,24 @@ static AST* require(Parser* p) static AST* expression(Parser* p) { + AST* expr = NULL; if (accept(p, T_LPAR)) { - AST* expr = expression(p); + expr = expression(p); expect(p, T_RPAR); - return expr; } else if (accept_str(p, T_ID, "if")) { - return if_stmnt(p); + expr = if_stmnt(p); } else if (accept_str(p, T_ID, "fn")) { - return function(p); + expr = function(p); } else if (match(p, T_ID)) { - return Ident(expect(p,T_ID)); - //if (peek(p)->type == T_LPAR) { - // arglist(p); - //} + expr = Ident(expect(p,T_ID)); } else { - return literal(p); + expr = literal(p); } + /* Check if this is a function application */ + if (peek(p)->type == T_LPAR) { + expr = func_app(p, expr); + } + return expr; } static AST* if_stmnt(Parser* p) @@ -141,24 +144,21 @@ static AST* token_to_tree(Tok* tok) } } - +static AST* func_app(Parser* p, AST* fn) +{ + AST* app = FnApp(fn); + expect(p,T_LPAR); + while (peek(p)->type != T_RPAR) { + fnapp_add_arg(p, expression(p)); + if (peek(p)->type != T_RPAR) + expect(p, T_COMMA); + } + expect(p,T_RPAR); + return app; +} #if 0 - -static AST* require(Parser* p); -static AST* type_annotation(Parser* p); -static AST* type_definition(Parser* p); -static AST* type(Parser* p); -static AST* tuple(Parser* p); -static AST* function(Parser* p); -static AST* definition(Parser* p); -static AST* expression(Parser* p); -static AST* arglist(Parser* p); -static AST* if_stmnt(Parser* p); -static AST* fn_stmnt(Parser* p); - - static AST* type_annotation(Parser* p) { //shifttok(p, T_ID); @@ -168,8 +168,6 @@ static AST* type_annotation(Parser* p) return NULL; } -/*****************************************************************************/ - static AST* type_definition(Parser* p) { //expect(p, T_ID); @@ -201,34 +199,4 @@ static AST* tuple(Parser* p) { ////reduce(p, mrk); return NULL; } - -static AST* function(Parser* p) { - ////size_t mark1 = mark(p) - 1; - ////size_t mark2 = mark(p); - //while (!accept(p, T_RPAR)) { - // type(p); - // if (T_RPAR != peek(p)->type) - // expect(p, T_COMMA); - //} - ////reduce(p, mark2); - ////reduce(p, mark1); - return NULL; -} - -static AST* arglist(Parser* p) -{ - ////size_t mrk = mark(p); - //expect(p, T_LPAR); - //while(peek(p)->type != T_RPAR) { - // expression(p); - // if(peek(p)->type != T_RPAR) - // expect(p, T_COMMA); - //} - //expect(p, T_RPAR); - ////reduce(p, mrk); - return NULL; -} - - - #endif diff --git a/source/sclpl.h b/source/sclpl.h index ceb023a..b031129 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -73,7 +73,7 @@ typedef struct { *****************************************************************************/ typedef enum ASTType { AST_STRING = 0, AST_SYMBOL, AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT, - AST_REQ, AST_DEF, AST_ANN, AST_IF, AST_FUNC, AST_BLOCK + AST_REQ, AST_DEF, AST_ANN, AST_IF, AST_FUNC, AST_FNAPP, AST_BLOCK } ASTType; typedef struct AST { @@ -104,6 +104,11 @@ typedef struct AST { vec_t args; struct AST* body; } func; + /* Function Application */ + struct { + struct AST* fn; + vec_t args; + } fnapp; /* Code Block */ vec_t exprs; /* String, Symbol, Identifier */ @@ -178,16 +183,17 @@ AST* func_body(AST* func); void func_add_arg(AST* func, AST* arg); void func_set_body(AST* func, AST* body); +/* Function Application */ +AST* FnApp(AST* fn); +void fnapp_add_arg(AST* func, AST* arg); + ///* Annotation */ //AST* Ann(char* name, AST* value); //char* ann_name(AST* def); //AST* ann_value(AST* def); -// -// -// -// + /* Lexer and Parser Types *****************************************************************************/ typedef struct { diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb index 9f25e4f..49ec174 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -205,19 +205,19 @@ describe "sclpl grammar" do end end -# context "function application" do -# it "should parse an application with no params " do -# expect(ast('foo()')).to eq([["T_ID:foo"]]) -# end -# -# it "should parse an application with one param" do -# expect(ast('foo(a)')).to eq([["T_ID:foo", "T_ID:a"]]) -# end -# -# it "should parse an application with two params" do -# expect(ast('foo(a,b)')).to eq([["T_ID:foo", "T_ID:a", "T_ID:b"]]) -# end -# end + context "function application" do + it "should parse an application with no params " do + expect(ast('foo()')).to eq([["T_ID:foo"]]) + end + + it "should parse an application with one param" do + expect(ast('foo(a)')).to eq([["T_ID:foo", "T_ID:a"]]) + end + + it "should parse an application with two params" do + expect(ast('foo(a,b)')).to eq([["T_ID:foo", "T_ID:a", "T_ID:b"]]) + end + end end context "corner cases" do