]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
added new nodes to AST and updated parser to build the AST
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 22 Mar 2019 21:26:11 +0000 (17:26 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 22 Mar 2019 21:26:11 +0000 (17:26 -0400)
Makefile
example.src
source/ast.c
source/lex.c
source/parser.c
source/sclpl.h

index 8301555994764677c3d6e81b35a2c859754a0b1f..738b95914926d6700b43c66548cffcd39e455aaf 100644 (file)
--- 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 $@ $<
index 0012407276cdc27b3f5055e2df1b6724744daba1..10adc8f4107754f3885f563cf0da74786f42dde8 100644 (file)
@@ -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
index 8da9dba21eb879abd9e09f6c1e1bd0a8ff10c179..bc3aa53f61b2ae7c974b713085c8b0ed9addc965 100644 (file)
@@ -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;
+}
index b3ccd11d70b1c8d7748be7cc4136a1fa947b3247..7a4c297f93fa56e0e20d3f4384135811995a2dc2 100644 (file)
@@ -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);
+}
index 9ab5c25c26ffd1e6a40a6f5cae757c2c024ce368..f5e0df23d2e685fb6ff9592c2e4738176a0501ca 100644 (file)
@@ -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, "<file>:%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;
 }
 
index 377af0272d62a7e2e00fc33cc333c518dda04fb7..6be6362e9973600eced473d0db371ec02926592b 100644 (file)
@@ -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);