From: Michael D. Lowis Date: Fri, 22 Mar 2019 21:26:11 +0000 (-0400) Subject: added new nodes to AST and updated parser to build the AST X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=dc3d701d6b4af9e53bd3bae7b35576cd138fd3d3;p=proto%2Fsclpl.git added new nodes to AST and updated parser to build the AST --- diff --git a/Makefile b/Makefile index 8301555..738b959 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ OBJS = source/main.o \ source/codegen.o .PHONY: all specs tests -all: sclpl specs tests +all: sclpl tests lib${BIN}.a: ${OBJS} ${AR} ${ARFLAGS} $@ $^ @@ -43,7 +43,7 @@ specs: $(BIN) tests: $(BIN) @echo "Parsing example file..." - ./sclpl -Aast < example.src + ./sclpl -Aast example.src .c.o: ${CC} ${CFLAGS} -c -o $@ $< diff --git a/example.src b/example.src index 0012407..10adc8f 100644 --- a/example.src +++ b/example.src @@ -2,9 +2,9 @@ require ("fmt") provide (main) let const_true bool = true -let const_false bool = false -let const_uint int = 123 -let const_string string = "" +#let const_false bool = false +#let const_uint int = 123 +#let const_string string = "" var var_true bool = true var var_false bool = false diff --git a/source/ast.c b/source/ast.c index 8da9dba..bc3aa53 100644 --- a/source/ast.c +++ b/source/ast.c @@ -96,3 +96,89 @@ bool var_const(AST* var) { assert(var->nodetype == AST_VAR); return (var->value.var.flags == SF_CONSTANT); } + +AST* Func(AST* args, AST* body) +{ + AST* node = ast(AST_FUNC); + node->value.func.args = args; + node->value.func.body = body; + return node; +} + +AST* func_args(AST* func) { + assert(func->nodetype == AST_FUNC); + return func->value.func.args; +} + +AST* func_body(AST* func) { + assert(func->nodetype == AST_FUNC); + return func->value.func.body; +} + +AST* ExpList(void) { + AST* node = ast(AST_EXPLIST); + node->value.explist.nexprs = 0; + node->value.explist.exprs = 0; + return node; +} + +AST** explist_get(AST* explist, size_t* nexprs) { + assert(explist->nodetype == AST_EXPLIST); + *nexprs = explist->value.explist.nexprs; + return explist->value.explist.exprs; +} + +void explist_append(AST* explist, AST* expr) { + assert(explist->nodetype == AST_EXPLIST); + explist->value.explist.nexprs += 1; + explist->value.explist.exprs = realloc(explist->value.explist.exprs, explist->value.explist.nexprs * sizeof(AST*)); + explist->value.explist.exprs[explist->value.explist.nexprs-1] = expr; +} + +void explist_prepend(AST* explist, AST* expr) { + assert(explist->nodetype == AST_EXPLIST); + explist->value.explist.nexprs++; + explist->value.explist.exprs = realloc(explist->value.explist.exprs, explist->value.explist.nexprs * sizeof(AST*)); + memmove(explist->value.explist.exprs+1, explist->value.explist.exprs, explist->value.explist.nexprs-1); + explist->value.explist.exprs[0] = expr; +} + +AST* If(AST* cond, AST* b1, AST* b2) { + AST* node = ast(AST_IF); + node->value.ifexp.cond = cond; + node->value.ifexp.b1 = b1; + node->value.ifexp.b2 = b2; + return node; +} + +AST* if_cond(AST* ifexp) { + assert(ifexp->nodetype == AST_IF); + return ifexp->value.ifexp.cond; +} + +AST* if_then(AST* ifexp) { + assert(ifexp->nodetype == AST_IF); + return ifexp->value.ifexp.b1; +} + +AST* if_else(AST* ifexp) { + assert(ifexp->nodetype == AST_IF); + return ifexp->value.ifexp.b2; +} + +AST* Apply(AST* func, AST* args) { + AST* node = ast(AST_APPLY); + node->value.apply.func = func; + node->value.apply.args = args; + return node; +} + +AST* apply_func(AST* apply) { + assert(apply->nodetype == AST_APPLY); + return apply->value.apply.func; +} + +AST* apply_args(AST* apply) { + assert(apply->nodetype == AST_APPLY); + return apply->value.apply.args; +} diff --git a/source/lex.c b/source/lex.c index b3ccd11..7a4c297 100644 --- a/source/lex.c +++ b/source/lex.c @@ -213,3 +213,13 @@ void lex(Parser* ctx) { } } } + +void lexprintpos(Parser* p, FILE* file, Tok* tok) { + size_t line = 1; + char* data = p->file->fbeg; + char* end = data + tok->offset; + for (; *data && data < end; data++) { + if (*data == '\n') line++; + } + fprintf(file, "%s:%zu: ", tok->file, line); +} diff --git a/source/parser.c b/source/parser.c index 9ab5c25..f5e0df2 100644 --- a/source/parser.c +++ b/source/parser.c @@ -28,7 +28,8 @@ static void error(Parser* parser, const char* fmt, ...) { Tok* tok = peek(parser); va_list args; va_start(args, fmt); - fprintf(stderr, ":%zu: error: ", tok->offset); + lexprintpos(parser, stderr, tok); + fprintf(stderr, " error: "); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); @@ -146,8 +147,8 @@ static AST* func_definition(Parser* p) { // TODO: Function AST nodes } expect(p, ')'); AST* type = type_expression(p); - expression_block(p); - return Var(str, NULL, type, SF_CONSTANT); + AST* body = expression_block(p); + return Var(str, body, type, SF_CONSTANT); } static AST* expression(Parser* p) { @@ -167,11 +168,13 @@ static AST* expression(Parser* p) { } /* determine if this is a function call */ - if (matches(p, '(')) { // TODO - func_expr_list(p); + if (matches(p, '(')) { + exp = Apply(exp, func_expr_list(p)); } else if (accept(p, '.')) { - identifier(p); - func_expr_list(p); + AST* func = identifier(p); + AST* args = func_expr_list(p); + explist_prepend(args, exp); + exp = Apply(func, args); } return exp; @@ -181,12 +184,12 @@ static AST* constant(Parser* p) { AST* tree = NULL; Tok* tok = peek(p); switch (tok->type) { - case T_BOOL: tree = Bool(tok); - case T_CHAR: tree = Char(tok); - case T_STRING: tree = String(tok); - case T_INT: tree = Integer(tok); - case T_FLOAT: tree = Float(tok); - case T_ID: tree = Ident(tok); + case T_BOOL: tree = Bool(tok); break; + case T_CHAR: tree = Char(tok); break; + case T_STRING: tree = String(tok); break; + case T_INT: tree = Integer(tok); break; + case T_FLOAT: tree = Float(tok); break; + case T_ID: tree = Ident(tok); break; default: error(p, "expected an expression"); } accept(p, tok->type); @@ -231,27 +234,31 @@ static AST* struct_fields(Parser* p) { ****************************************************************************/ static AST* expression_block(Parser* p) { expect(p, '{'); + AST* list = ExpList(); while (!matches(p, '}')) { + AST* expr = 0; if (matches(p, T_LET) || matches(p, T_VAR)) { - definition(p); + expr = definition(p); } else if (matches(p, T_FUN)) { - func_definition(p); + expr = func_definition(p); } else { - expression(p); + expr = expression(p); } + explist_append(list, expr); } expect(p, '}'); - return NULL; + return list; } static AST* if_expression(Parser* p) { + AST *cond = 0, *b1 = 0, *b2 = 0; expect(p, T_IF); - expression(p); // condition - expression(p); // true branch + cond = expression(p); // condition + b1 = expression(p); // true branch if (accept(p, T_ELSE)) { - expression(p); // false branch + b2 = expression(p); // false branch } - return NULL; + return If(cond, b1, b2); } static AST* identifier(Parser* p) { @@ -268,16 +275,13 @@ static AST* identifier(Parser* p) { static AST* func_expr_list(Parser* p) { expect(p, '('); - if (!matches(p, ')')) { - while (true) { - expression(p); - if (!matches(p, ')')) - expect(p, ','); - else - break; - } + AST* list = ExpList(); + while (!matches(p, ')')) { + explist_append(list, expression(p)); + if (!matches(p, ')')) + expect(p, ','); } expect(p, ')'); - return NULL; + return list; } diff --git a/source/sclpl.h b/source/sclpl.h index 377af02..6be6362 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -94,7 +94,8 @@ Sym* sym_get(SymTable* syms, char* name); /* AST Types *****************************************************************************/ typedef enum { - AST_VAR, AST_FUNC, AST_EXPLIST, AST_STRING, AST_SYMBOL, AST_CHAR, AST_INT, + AST_VAR, AST_FUNC, AST_EXPLIST, AST_IF, AST_APPLY, + AST_STRING, AST_SYMBOL, AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT } ASTType; @@ -119,6 +120,17 @@ typedef struct AST { size_t nexprs; struct AST** exprs; } explist; + /* If Expression Node */ + struct { + struct AST* cond; + struct AST* b1; + struct AST* b2; + } ifexp; + /* Application Node */ + struct { + struct AST* func; + struct AST* args; + } apply; /* String, Symbol, Identifier */ char* text; /* Character */ @@ -166,8 +178,19 @@ AST* Func(AST* args, AST* body); AST* func_args(AST* func); AST* func_body(AST* func); -AST* ExpList(size_t nexprs, AST** exprs); -AST** explist_get(size_t* nexprs); +AST* ExpList(void); +AST** explist_get(AST* explist, size_t* nexprs); +void explist_append(AST* explist, AST* expr); +void explist_prepend(AST* explist, AST* expr); + +AST* If(AST* cond, AST* b1, AST* b2); +AST* if_cond(AST* ifexp); +AST* if_then(AST* ifexp); +AST* if_else(AST* ifexp); + +AST* Apply(AST* func, AST* args); +AST* apply_func(AST* apply); +AST* apply_args(AST* apply); /* Package Definition *****************************************************************************/ @@ -223,6 +246,7 @@ typedef struct { void lexfile(Parser* ctx, char* path); void lex(Parser* ctx); +void lexprintpos(Parser* p, FILE* file, Tok* tok); void gettoken(Parser* ctx); void toplevel(Parser* p); void codegen_init(Parser* p);