11 Commits 69bb58c9ce ... 292b08e80f

Auteur SHA1 Bericht Datum
  soud 292b08e80f small output text change 9 jaren geleden
  soud 6b98c224cb another seg fault bites the dust 9 jaren geleden
  Steven f34473c352 comment style change 9 jaren geleden
  soud 93c07cfe15 parser error state 9 jaren geleden
  soud 9c59723c99 removed tab test file 9 jaren geleden
  soud 452e3ad5e0 tabs and line breaks support 9 jaren geleden
  soud 94770adc30 fixed seg fault 9 jaren geleden
  soud 8981a6b099 revised bin expr and vars 9 jaren geleden
  Steven ba2d4e94ad revised destroyers and fixed some memory leaks 9 jaren geleden
  Steven 4e87536580 parse block level, ast_op_t struct and unless keyword 9 jaren geleden
  Steven dcd99752d9 list structures in nodes 9 jaren geleden
10 gewijzigde bestanden met toevoegingen van 207 en 251 verwijderingen
  1. 4 1
      Makefile
  2. 1 1
      examples/fibonacci.er
  3. 19 22
      examples/parse.er
  4. 104 130
      src/ast.c
  5. 30 59
      src/ast.h
  6. 1 1
      src/erupt.h
  7. 33 33
      src/lexer.c
  8. 2 1
      src/lexer.h
  9. 13 3
      src/main.c
  10. 0 0
      src/parser.c

+ 4 - 1
Makefile

@@ -7,7 +7,10 @@ all:
 	@mkdir -p bin/
 	$(CC) $(CFLAGS) $(CFILES)
 	$(CXX) $(OBJFILES) $(LDFLAGS) -o bin/erupt
-	@-rm -r $(OBJFILES)
+	@-rm $(OBJFILES)
+
+install:
+	cp bin/erupt /usr/bin
 
 clean:
 	@rm *.o

+ 1 - 1
examples/fibonacci.er

@@ -1,6 +1,6 @@
 fun fibo(i64 n) -> i64
 {
-    if n < 3 {
+    if n < 2 {
         return 1;
     }
 

+ 19 - 22
examples/parse.er

@@ -1,21 +1,18 @@
-/*
- *                          main(*)
- *                   --------------------
- *                  /         |          \
- *               i = 0      while(*)   print(i)
- *                         ---------
- *                        /         \
- *                     if(*)   print("in while")
- *                    ------
- *                   /      \
- *                i += 1    else
- *                         ------
- *                        /      \
- *                     i += 2    print("else stmt")
- *
- */
-
-use whatever_really;
+(*
+                         main(.)
+                  --------------------
+                 /         |          \
+              i = 0      while(.)   print(i)
+                        ---------
+                       /         \
+                    if(.)   print("in while")
+                   ------
+                  /      \
+               i += 1    else
+                        ------
+                       /      \
+                    i += 2    print("else stmt")
+*)
 
 mut i32 glob_var = 5;
 
@@ -24,15 +21,15 @@ fun main
     mut i32 i = 0;
 
     while i < 20 {
-        if odd : i {
+        if odd(i) {
             i += 1;
         } else {
             i += 2;
-            write : "else stmt";
+            write("else stmt");
         }
 
-        write : "in while";
+        write("in while");
     }
 
-    write : i;
+    write(i);
 }

+ 104 - 130
src/ast.c

@@ -23,7 +23,7 @@
 #include "erupt.h"
 #include "ast.h"
 
-ast_node_t *create_var(char *name, ast_type_t data_type, char *value, bool mutable)
+ast_node_t *create_var(char *name, ast_type_t data_type, bool mutable)
 {
         ast_node_t *node = smalloc(sizeof(ast_node_t));
 
@@ -32,56 +32,10 @@ ast_node_t *create_var(char *name, ast_type_t data_type, char *value, bool mutab
         node->var.data_type = data_type;
         node->var.mutable = mutable;
 
-        switch (data_type) {
-        case I8:
-                node->var.int8_value = strtol(value, NULL, 10);
-                break;
-        case I16:
-                node->var.int16_value = strtol(value, NULL, 10);
-                break;
-        case I32:
-                node->var.int32_value = strtol(value, NULL, 10);
-                break;
-        case I64:
-                node->var.int64_value = strtoll(value, NULL, 10);
-                break;
-        case U8:
-                node->var.uint8_value = strtoul(value, NULL, 10);
-                break;
-        case U16:
-                node->var.uint16_value = strtoul(value, NULL, 10);
-                break;
-        case U32:
-                node->var.uint32_value = strtoul(value, NULL, 10);
-                break;
-        case U64:
-                node->var.uint64_value = strtoull(value, NULL, 10);
-                break;
-        case STR:
-                node->var.str_value = strdup(value);
-                break;
-        case BOOL: {
-                bool state = NULL;
-
-                if (strcmp(value, TRUE_KEYWORD) == 0)
-                        state = true;
-                else if (strcmp(value, FALSE_KEYWORD) == 0)
-                        state = false;
-
-                node->var.bool_value = state;
-                break;
-        }
-        case FLOAT:
-                node->var.float_value = strtof(value, NULL);
-                break;
-        default:
-                erupt_fatal_error("somehow got invalid data type\n");
-        }
-
         return node;
 }
 
-ast_node_t *create_fn_proto(char *name, ast_var_t **args, size_t arg_count, ast_type_t data_type)
+ast_node_t *create_fn_proto(char *name, ast_node_list_t *args, ast_type_t data_type)
 {
         ast_node_t *node = smalloc(sizeof(ast_node_t));
 
@@ -89,17 +43,12 @@ ast_node_t *create_fn_proto(char *name, ast_var_t **args, size_t arg_count, ast_
         node->prototype.name = strdup(name);
         node->prototype.data_type = data_type;
 
-        node->prototype.args = smalloc(sizeof(ast_var_t) * arg_count);
-
-        for (size_t i = 0; i < arg_count; ++i)
-                node->prototype.args[i] = args[i];
-
-        node->prototype.arg_count = arg_count;
+        node->prototype.args = args;
 
         return node;
 }
 
-ast_node_t *create_fn(ast_node_t *prototype, ast_node_t *body)
+ast_node_t *create_fn(ast_node_t *prototype, ast_node_list_t *body)
 {
         ast_node_t *node = smalloc(sizeof(ast_node_t));
 
@@ -110,110 +59,129 @@ ast_node_t *create_fn(ast_node_t *prototype, ast_node_t *body)
         return node;
 }
 
-ast_node_t *create_call(char *name, ast_node_t **args, size_t arg_count)
+ast_node_t *create_call(char *name, ast_node_list_t *args)
 {
         ast_node_t *node = smalloc(sizeof(ast_node_t));
 
         node->type = TYPE_CALL;
         node->call.name = strdup(name);
 
-        node->call.args = smalloc(sizeof(char) * arg_count);
-
-        for (size_t i = 0; i < arg_count; ++i)
-                node->call.args[i] = args[i];
-
-        node->call.arg_count = arg_count;
+        node->call.args = args;
 
         return node;
 }
 
-ast_node_t *create_if(ast_node_t *condition, ast_node_t *true_body,
-                      ast_node_t *false_body)
+ast_node_t *create_if(ast_node_t *condition, ast_node_list_t *true_body,
+                      ast_node_list_t *false_body)
 {
         ast_node_t *node = smalloc(sizeof(ast_node_t));
 
         node->type = TYPE_IF;
-        node->if_exp.condition = condition;
-        node->if_exp.true_body = true_body;
-        node->if_exp.false_body = false_body;
+        node->if_expr.condition = condition;
+        node->if_expr.true_body = true_body;
+        node->if_expr.false_body = false_body;
 
         return node;
 }
 
-ast_node_t *create_bin_exp(ast_op_t operator, ast_node_t *lhs, ast_node_t *rhs)
+ast_node_t *create_bin_expr(ast_op_t operator, ast_node_t *lhs, ast_node_t *rhs)
 {
         ast_node_t *node = smalloc(sizeof(ast_node_t));
 
-        node->type = TYPE_BIN_EXP;
-        node->bin_exp.operator = operator;
-        node->bin_exp.lhs = lhs;
-        node->bin_exp.rhs = rhs;
+        node->type = TYPE_BIN_EXPR;
+        node->bin_expr.operator = operator;
+        node->bin_expr.lhs = lhs;
+        node->bin_expr.rhs = rhs;
 
         return node;
 }
 
+ast_node_list_t *create_node_list(void)
+{
+        ast_node_list_t *nl = smalloc(sizeof(ast_node_list_t));
+
+        nl->node = NULL;
+        nl->next = NULL;
+
+        return nl;
+}
+
+void swap_lists(ast_node_list_t *a, ast_node_list_t *b)
+{
+        ast_node_list_t *tmp = a;
+        a = b;
+        b = tmp;
+}
+
+static void destroy_node(ast_node_t *node)
+{
+        if (!node)
+                return;
+
+        switch(node->type) {
+        case TYPE_VAR:
+                if (node->var.name)
+                        free(node->var.name);
+                break;
+        case TYPE_PROTO:
+                if (node->prototype.name)
+                        free(node->prototype.name);
+
+                if (node->prototype.args)
+                        destroy_ast(node->prototype.args);
+                break;
+        case TYPE_FN:
+                if (node->fn.prototype)
+                        destroy_node(node->fn.prototype);
+
+                if (node->fn.body)
+                        destroy_ast(node->fn.body);
+                break;
+        case TYPE_CALL:
+                if (node->call.name)
+                        free(node->call.name);
+
+                if (node->call.args)
+                        destroy_ast(node->call.args);
+                break;
+        case TYPE_IF:
+                if (node->if_expr.condition)
+                        destroy_node(node->if_expr.condition);
+
+                if (node->if_expr.true_body)
+                        destroy_ast(node->if_expr.true_body);
+
+                if (node->if_expr.false_body)
+                        destroy_ast(node->if_expr.false_body);
+                break;
+        case TYPE_BIN_EXPR:
+                if (node->bin_expr.lhs)
+                        destroy_node(node->bin_expr.lhs);
+                if (node->bin_expr.rhs)
+                        destroy_node(node->bin_expr.rhs);
+                break;
+        }
+
+        free(node);
+}
+
 void destroy_ast(ast_node_list_t *nl)
 {
-        do {
-                switch(nl->node->type) {
-                case TYPE_VAR:
-                        if (nl->node->var.name)
-                                free(nl->node->var.name);
-                        break;
-                case TYPE_PROTO:
-                        if (nl->node->prototype.name)
-                                free(nl->node->prototype.name);
-
-                        for (size_t i = 0; i < nl->node->prototype.arg_count; ++i)
-                                free(nl->node->prototype.args[i]);
-
-                        free(nl->node->prototype.args);
-                        break;
-                case TYPE_FN:
-                        if (nl->node->fn.prototype)
-                                free(nl->node->fn.prototype);
-
-                        if (nl->node->fn.body)
-                                free(nl->node->fn.body);
-                        break;
-                case TYPE_CALL:
-                        if (nl->node->call.name)
-                                free(nl->node->call.name);
-
-                        for (size_t i = 0; i < nl->node->call.arg_count; ++i)
-                                free(nl->node->call.args[i]);
-
-                        free(nl->node->call.args);
-                        break;
-                case TYPE_IF:
-                        if (nl->node->if_exp.condition)
-                                free(nl->node->if_exp.condition);
-
-                        if (nl->node->if_exp.true_body)
-                                free(nl->node->if_exp.true_body);
-
-                        if (nl->node->if_exp.false_body)
-                                free(nl->node->if_exp.false_body);
-                        break;
-                case TYPE_BIN_EXP:
-                        if (nl->node->bin_exp.lhs)
-                                free(nl->node->bin_exp.lhs);
-                        if (nl->node->bin_exp.rhs)
-                                free(nl->node->bin_exp.rhs);
-                        break;
-                }
+        if (!nl)
+                return;
 
-                free(nl->node);
-                nl = nl->next;
-        } while (nl->next != NULL);
+        do {
+                destroy_node(nl->node);
+        } while ((nl = nl->next));
 
         free(nl);
-        verbose_printf("destroyed ast\n");
 }
 
-
 static void dump_node(ast_node_t *node)
 {
+        if (!node)
+                return;
+
         switch (node->type) {
         case TYPE_VAR:
                 printf("variable:\n\tname: %s\n\ttype: %u\n\tmutable:%d\n",
@@ -225,7 +193,14 @@ static void dump_node(ast_node_t *node)
                 break;
         case TYPE_FN:
                 printf("function:\n");
-                dump_node(node->fn.prototype);
+
+                if (node->fn.prototype)
+                        dump_node(node->fn.prototype);
+
+                if (node->fn.body) {
+                        printf("body:\n");
+                        dump_node_list(node->fn.body);
+                }
                 break;
         case TYPE_CALL:
                 /* TODO */
@@ -233,16 +208,15 @@ static void dump_node(ast_node_t *node)
         case TYPE_IF:
                 /* TODO */
                 break;
-        case TYPE_BIN_EXP:
+        case TYPE_BIN_EXPR:
                 /* TODO */
                 break;
         }
 }
 
-void dump_nodes(ast_node_list_t *nl)
+void dump_node_list(ast_node_list_t *nl)
 {
         do {
                 dump_node(nl->node);
-                nl = nl->next;
-        } while (nl->next != NULL);
+        } while ((nl = nl->next));
 }

+ 30 - 59
src/ast.h

@@ -45,79 +45,47 @@ typedef enum {
 } ast_type_t;
 
 typedef enum {
-        /* math operators */
-        OP_PLUS,
-        OP_MIN,
-        OP_DIV,
-        OP_MUL,
-        OP_MOD,
-
-        /* logical operators */
-        OP_AND,
-        OP_OR,
-        OP_NOT,
-
-        /* relational operators */
-        OP_NOT_EQ,
-        OP_EQ,
-        OP_GT,
-        OP_GT_EQ,
-        OP_LT,
-        OP_LT_EQ,
-
-        /* bitwise operators */
-        OP_BIN_OR,
-        OP_BIN_XOR,
-        OP_BIN_AND,
-        OP_BIN_NOT
+        ASSOC_LEFT,
+        ASSOC_RIGHT,
+        ASSOC_NONE
+} ast_assoc_t;
+
+typedef struct {
+        tokentype symbol;
+        int precedence;
+        ast_assoc_t assoc;
+        bool unary;
 } ast_op_t;
 
 struct ast_node;
+struct ast_node_list;
 
 typedef struct {
         char *name;
         ast_type_t data_type;
         bool mutable;
-
-        union {
-                int8_t int8_value;
-                int16_t int16_value;
-                int32_t int32_value;
-                int64_t int64_value;
-
-                uint8_t uint8_value;
-                uint16_t uint16_value;
-                uint32_t uint32_value;
-                uint64_t uint64_value;
-
-                char *str_value;
-                bool bool_value;
-                float float_value;
-        };
 } ast_var_t;
 
 typedef struct {
         char *name;
-        ast_var_t **args;
-        size_t arg_count;
+        struct ast_node_list *args;
         ast_type_t data_type;
 } ast_proto_t;
 
 typedef struct {
         struct ast_node *prototype;
-        struct ast_node *body;
+        struct ast_node_list *body;
 } ast_fn_t;
 
 typedef struct {
         char *name;
-        struct ast_node **args;
-        size_t arg_count;
+        struct ast_node_list *args;
 } ast_call_t;
 
 typedef struct {
         struct ast_node *condition;
-        struct ast_node *true_body;
-        struct ast_node *false_body;
+        struct ast_node_list *true_body;
+        struct ast_node_list *false_body;
 } ast_if_t;
 
 typedef struct {
@@ -125,7 +93,7 @@ typedef struct {
 
         struct ast_node *lhs;
         struct ast_node *rhs;
-} ast_bin_exp_t;
+} ast_bin_expr_t;
 
 typedef struct ast_node {
         enum {
@@ -134,7 +102,7 @@ typedef struct ast_node {
                 TYPE_FN,
                 TYPE_CALL,
                 TYPE_IF,
-                TYPE_BIN_EXP
+                TYPE_BIN_EXPR
         } type;
 
         union {
@@ -142,8 +110,8 @@ typedef struct ast_node {
                 ast_proto_t prototype;
                 ast_fn_t fn;
                 ast_call_t call;
-                ast_if_t if_exp;
-                ast_bin_exp_t bin_exp;
+                ast_if_t if_expr;
+                ast_bin_expr_t bin_expr;
         };
 } ast_node_t;
 
@@ -152,13 +120,16 @@ typedef struct ast_node_list {
         struct ast_node_list *next;
 } ast_node_list_t;
 
-ast_node_t *create_var(char *name, ast_type_t data_type, char *value, bool mutable);
-ast_node_t *create_fn_proto(char *name, ast_var_t **args, size_t arg_count, ast_type_t data_type);
-ast_node_t *create_fn(ast_node_t *prototype, ast_node_t *body);
-ast_node_t *create_call(char *name, ast_node_t **args, size_t arg_count);
-ast_node_t *create_if(ast_node_t *condition, ast_node_t *true_body, ast_node_t *false_body);
-ast_node_t *create_bin_exp(ast_op_t operator, ast_node_t *lhs, ast_node_t *rhs);
+ast_node_t *create_var(char *name, ast_type_t data_type, bool mutable);
+ast_node_t *create_fn_proto(char *name, ast_node_list_t *args, ast_type_t data_type);
+ast_node_t *create_fn(ast_node_t *prototype, ast_node_list_t *body);
+ast_node_t *create_call(char *name, ast_node_list_t *args);
+ast_node_t *create_if(ast_node_t *condition, ast_node_list_t *true_body,
+                      ast_node_list_t *false_body);
+ast_node_t *create_bin_expr(ast_op_t operator, ast_node_t *lhs, ast_node_t *rhs);
+ast_node_list_t *create_node_list(void);
+void swap_lists(ast_node_list_t *a, ast_node_list_t *b);
 void destroy_ast(ast_node_list_t *nl);
-void dump_nodes(ast_node_list_t *nl);
+void dump_node_list(ast_node_list_t *nl);
 
 #endif /* !AST_H */

+ 1 - 1
src/erupt.h

@@ -24,7 +24,7 @@
 #define ERUPT_H
 
 #ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* strndup */
+# define _GNU_SOURCE /* strndup */
 #endif
 
 #include <string.h>

+ 33 - 33
src/lexer.c

@@ -30,11 +30,11 @@ static void emit_token(lexer_t *lexer, tokentype type);
 static tokentype get_keyword(lexer_t *lexer);
 static bool is_int(char c);
 static bool is_ident(char c);
+static bool is_whitespace(char c);
 static void read_string(lexer_t *lexer, char id);
 static void read_int(lexer_t *lexer);
 static void read_ident(lexer_t *lexer);
 static void read_comment(lexer_t *lexer);
-static void read_long_comment(lexer_t *lexer);
 
 /* string => ketword_t "map" for detecting keywords */
 static keyword_t keywords[] = {
@@ -49,11 +49,12 @@ static keyword_t keywords[] = {
         {BREAK_KEYWORD    , TOKEN_BREAK},
         {CONTINUE_KEYWORD , TOKEN_CONTINUE},
         {IF_KEYWORD       , TOKEN_IF},
+        {UNLESS_KEYWORD   , TOKEN_UNLESS},
         {ELSE_KEYWORD     , TOKEN_ELSE},
 };
 
 
-lexer_t *tokenize(char *target_file, char *source)
+lexer_t *lex(char *target_file, char *source)
 {
         char c;
         lexer_t *lexer = create_lexer(target_file, source);
@@ -65,7 +66,12 @@ lexer_t *tokenize(char *target_file, char *source)
 
                 c = eat(lexer);
                 switch (c) {
-                case '(': emit_token(lexer, TOKEN_L_PAREN); break;
+                case '(':
+                           if (peek(lexer) == '*')
+                                   read_comment(lexer);
+                           else
+                                   emit_token(lexer, TOKEN_L_PAREN);
+                           break;
                 case ')': emit_token(lexer, TOKEN_R_PAREN); break;
                 case '[': emit_token(lexer, TOKEN_L_BRACKET); break;
                 case ']': emit_token(lexer, TOKEN_R_BRACKET); break;
@@ -151,12 +157,12 @@ lexer_t *tokenize(char *target_file, char *source)
                         }
                         break;
                 case '/':
-                        if (peek(lexer) == '*')
-                                read_long_comment(lexer);
-                        else if (peek(lexer) == '/')
-                                read_comment(lexer);
-                        else
+                        if (peek(lexer) == '=') {
+                                eat(lexer);
+                                emit_token(lexer, TOKEN_SLASH_EQ);
+                        } else {
                                 emit_token(lexer, TOKEN_SLASH);
+                        }
                         break;
                 case '!':
                         if (peek(lexer) == '=') {
@@ -202,7 +208,9 @@ lexer_t *tokenize(char *target_file, char *source)
                         }
                         break;
                 case ' ':
-                        while (peek(lexer) == ' ')
+                case '\t':
+                case '\r':
+                        while (is_whitespace(peek(lexer)))
                                 eat(lexer);
                         break;
                 default:
@@ -294,6 +302,11 @@ static bool is_ident(char c)
         return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
 }
 
+static bool is_whitespace(char c)
+{
+        return c == ' ' || c == '\t' || c == '\r';
+}
+
 static void read_string(lexer_t *lexer, char id)
 {
         while (eat(lexer) != id) {
@@ -326,42 +339,29 @@ static void read_ident(lexer_t *lexer)
 
 static void read_comment(lexer_t *lexer)
 {
-        while (peek(lexer) != '\n' && peek(lexer) != EOF)
-                eat(lexer);
-
-        ++lexer->line_n;
-        verbose_printf("\tskipped comment\n");
-
-        // don't tokenize comments
-}
-
-static void read_long_comment(lexer_t *lexer)
-{
-        while (peek(lexer)) {
+        while (1) {
                 if (peek(lexer) == '\n')
                         ++lexer->line_n;
 
-                if (eat(lexer) == '*' && peek(lexer) == '/') {
+                if (eat(lexer) == '*' && peek(lexer) == ')') {
                         eat(lexer);
-                        verbose_printf("skipped long comment\n");
+                        verbose_printf("skipped comment\n");
                         break;
                 }
         }
+
+        /* don't tokenize comments */
 }
 
 void destroy_lexer(lexer_t *lexer)
 {
-        if (lexer->ts != NULL) {
-                do {
-                        if (lexer->ts->value != NULL)
-                                free(lexer->ts->value);
-
-                        if (lexer->ts->prev != NULL)
-                                free(lexer->ts->prev);
-                } while((lexer->ts = lexer->ts->next));
-        }
+        if (!lexer)
+                return;
+
+        if (lexer->ts)
+                destroy_tokens(lexer->ts);
 
-        if (lexer->tail != NULL)
+        if (lexer->tail)
                 free(lexer->tail);
 
         free(lexer);

+ 2 - 1
src/lexer.h

@@ -36,6 +36,7 @@
 #define BREAK_KEYWORD    "break"
 #define CONTINUE_KEYWORD "continue"
 #define IF_KEYWORD       "if"
+#define UNLESS_KEYWORD   "unless"
 #define ELSE_KEYWORD     "else"
 
 #define I8_KEYWORD     "i8"
@@ -68,7 +69,7 @@ typedef struct {
         tokentype type;
 } keyword_t;
 
-lexer_t *tokenize(char *target_file, char *source);
+lexer_t *lex(char *target_file, char *source);
 void destroy_lexer(lexer_t *lexer);
 
 #endif /* !LEXER_H */

+ 13 - 3
src/main.c

@@ -24,7 +24,6 @@
 #include <sys/stat.h>
 
 #include "erupt.h"
-#include "lexer.h"
 #include "parser.h"
 
 static char *read_file(const char *path);
@@ -41,7 +40,7 @@ static const char *USAGE =
 "       -t, --tokens\n"
 "               show generated token stream\n"
 "       -n, --nodes\n"
-"               show nodes of the generated AST. fails if any error occurs\n"
+"               show nodes of the generated AST\n"
 "       -h, --help\n"
 "               show this\n";
 
@@ -61,7 +60,7 @@ int main(int argc, char *argv[])
 
         input_file = read_file(argv[optind]);
 
-        lexer_t *lexer = tokenize(argv[optind], input_file);
+        lexer_t *lexer = lex(argv[optind], input_file);
 
         if (SHOW_TOKENS)
                 dump_tokens(lexer->ts);
@@ -70,7 +69,18 @@ int main(int argc, char *argv[])
 
         ast_node_list_t *ast = parse_token_stream(lexer->ts);
 
+        if (SHOW_NODES)
+                dump_node_list(ast);
+
+        if (PARSE_FAILED) {
+                destroy_lexer(lexer);
+                destroy_ast(ast);
+
+                erupt_fatal_error("error(s) occured, stopping compilation.\n");
+        }
+
         destroy_lexer(lexer);
+        destroy_ast(ast);
 
         return ERUPT_OK;
 }

+ 0 - 0
src/parser.c


Some files were not shown because too many files changed in this diff