G

G Programming Language
git clone http://git.omkov.net/G
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2021-09-06 09:09:31
Commit064b88e75bc83041db3cd0da086d730d9fbbc236
Parent9bce4407310ef3b4f7615a66498d7ff70e1ac8bb

parse: Consolidate lexer and parser

Diffstat

M src/compile.c | 10 ++++------
A src/g.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R src/lexer.c -> src/lex.c | 37 ++++++++++++++++++++++++++++++-------
D src/lexer.h | 90 --------------------------------------------------------------------------------
A src/parse.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D src/parser.c | 198 --------------------------------------------------------------------------------
D src/parser.h | 47 -----------------------------------------------
M src/util/ast.h | 6 +++---
M src/util/stack.h | 2 +-

9 files changed, 310 insertions, 352 deletions

diff --git a/src/compile.c b/src/compile.c
index 43e9c13..09933d7 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -6,9 +6,8 @@
 

 #include "compile.h"
-#include "lexer.h"
+#include "g.h"
 #include "cll/cll.h"
-#include "parser.h"
 #include "util/ast.h"
 
 #include "cll/error.h"
@@ -20,7 +19,7 @@ bool lflag = false, pflag = false;
 
 void compile(char *src, UINT len) {
 	if (lflag) {
-		lexer l = lex_init(src, len);
+		lex l = lex_init(src, len);
 
 		for (tok t = lex_next(&l); t.k != LK_EOF; free(t.s), t = lex_next(&l)) {
 			printf("%zu:%zu: %s \"%s\"\n", t.p.ln, t.p.cl+1, tok_ks[t.k], t.s);
@@ -33,9 +32,8 @@ void compile(char *src, UINT len) {
 	return;
 
 compile:;
-	lexer l = lex_init(src, len);
-	parser p = parser_init(&l);
-	ast *a = parser_parse(&p);
+	lex l = lex_init(src, len);
+	ast *a = parse(&l);
 
 	ast_print(a, 0);
 
diff --git a/src/g.h b/src/g.h
new file mode 100644
index 0000000..f6db769
--- /dev/null
+++ b/src/g.h
@@ -0,0 +1,77 @@
+// g.h
+// Common header file for G
+// Copyright (C) 2021, Jakob Wakeling
+// All rights reserved.
+
+
+
+#ifndef G_G_H_PHZNJHJ7
+#define G_G_H_PHZNJHJ7
+
+#include "type.h"
+#include "util/stack.h"
+#include "value.h"
+
+#include "cll/cll.h"
+
+typedef enum {
+	LK_VOID, LK_EOF,
+	
+	LK_IDN, LK_INT, LK_FLT,
+	LK_CHR, LK_STR,
+	
+	LK_LBRACK, LK_RBRACK,
+	LK_LPAREN, LK_RPAREN,
+	LK_LBRACE, LK_RBRACE,
+	LK_COLON,  LK_SCOLON,
+	LK_PERIOD, LK_COMMA,
+	
+	LK_RARROW,
+	
+	LK_ADD, LK_SUB, LK_MUL, LK_DIV, LK_MOD,
+	LK_LNOT, LK_BNOT, LK_BAND, LK_BOR, LK_BXOR,
+	LK_SHL, LK_SHR, LK_EQ, LK_NEQ, LK_LT, LK_LTE,
+	LK_GT, LK_GTE, LK_LAND, LK_LOR, LK_TERN, LK_ASSN,
+	LK_ADDEQ, LK_SDDEQ, LK_MULEQ, LK_DIVEQ, LK_MODEQ,
+	LK_ANDEQ, LK_OREQ, LK_XOREQ, LK_SHLEQ, LK_SHREQ,
+	LK_PROC, LK_RETURN, LK_IF, LK_ELSE, LK_FOR,
+} tok_k;
+
+typedef enum {
+	AK_VOID,
+	
+	AK_DECL, AK_ASSN, AK_COMP,
+	
+	AK_INT, AK_FLT,
+	
+	AK_VARIABLE,
+	AK_CONSTANT,
+	AK_PROCEDURE,
+	
+	AK_RETURN,
+} ast_k;
+
+typedef struct { UINT fi, fp, ln, cl; } pos;
+
+typedef struct { tok_k k; pos p; char *s; } tok;
+typedef struct { char *s; UINT sp, sl, ln, cl; tok t; } lex;
+
+typedef struct ast {
+	ast_k k; pos p; type *t; val v; str s;
+	struct ast *c, *cl, *cr; stack *cs;
+} ast;
+
+extern char *tok_ks[];
+extern char *ast_ks[];
+
+extern lex lex_init(char *src, UINT len);
+extern tok lex_next(lex *l);
+extern tok lex_kind(lex *l, tok_k k);
+extern tok lex_peek(lex *l);
+
+extern ast *ast_init(void);
+extern void ast_free(ast *a);
+
+extern ast *parse(lex *l);
+
+#endif // G_G_H_PHZNJHJ7
diff --git a/src/lexer.c b/src/lex.c
similarity index 80%
rename from src/lexer.c
rename to src/lex.c
index 9a76a19..9cc9018 100644
--- a/src/lexer.c
+++ b/src/lex.c
@@ -5,7 +5,7 @@
 

 
-#include "lexer.h"
+#include "g.h"
 #include "type.h"
 
 #include "cll/error.h"
@@ -24,17 +24,36 @@
 #define ISIDNCA(c) (isalpha(c) || c == '_')
 #define ISIDNCB(c) (isalpha(c) || isdigit(c) || c == '_')
 
-#define TOK_K(a, b) #a,
-str tok_ks[] = { TOK_KS };
-#undef TOK_K
+char *tok_ks[] = {
+	"LK_VOID", "LK_EOF",
+	
+	"LK_IDN", "LK_INT", "LK_FLT",
+	"LK_CHR", "LK_STR",
+	
+	"LK_LBRACK", "LK_RBRACK",
+	"LK_LPAREN", "LK_RPAREN",
+	"LK_LBRACE", "LK_RBRACE",
+	"LK_COLON",  "LK_SCOLON",
+	"LK_PERIOD", "LK_COMMA",
+	
+	"LK_RARROW",
+	
+	"LK_ADD", "LK_SUB", "LK_MUL", "LK_DIV", "LK_MOD",
+	"LK_LNOT", "LK_BNOT", "LK_BAND", "LK_BOR", "LK_BXOR",
+	"LK_SHL", "LK_SHR", "LK_EQ", "LK_NEQ", "LK_LT", "LK_LTE",
+	"LK_GT", "LK_GTE", "LK_LAND", "LK_LOR", "LK_TERN", "LK_ASSN",
+	"LK_ADDEQ", "LK_SDDEQ", "LK_MULEQ", "LK_DIVEQ", "LK_MODEQ",
+	"LK_ANDEQ", "LK_OREQ", "LK_XOREQ", "LK_SHLEQ", "LK_SHREQ",
+	"LK_PROC", "LK_RETURN", "LK_IF", "LK_ELSE", "LK_FOR",
+};
 
 /* Initialise a lexer. */
-lexer lex_init(str src, UINT len) {
-	lexer l = { src, 0, len, 0, 0 }; lex_next(&l); return l;
+lex lex_init(str src, UINT len) {
+	lex l = { src, 0, len, 0, 0 }; lex_next(&l); return l;
 }
 
 /* Lex the next token, and return the current one. */
-tok lex_next(lexer *l) {
+tok lex_next(lex *l) {
 	/* Short circuit if the current token is EOF */
 	if (l->t.k == LK_EOF) { return l->t; }
 
@@ -114,7 +133,7 @@ ret:;
 }
 
 /* Lex the next token if the current is of a specific type. */
-tok lex_kind(lexer *l, tok_k k) {
+tok lex_kind(lex *l, tok_k k) {
 	if (l->t.k != k) { error(
 		1, "%zu:%zu: Unexpected: \"%s\", was expecting: \"%s\"",
 		l->t.p.ln, l->t.p.cl, tok_ks[l->t.k], tok_ks[k]
@@ -124,4 +143,4 @@ tok lex_kind(lexer *l, tok_k k) {
 }
 
 /* Return the current token. */
-tok lex_peek(lexer *l) { return l->t; }
+tok lex_peek(lex *l) { return l->t; }
diff --git a/src/lexer.h b/src/lexer.h
deleted file mode 100644
index 4764282..0000000
--- a/src/lexer.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// lexer.h
-// Lexer header file for G
-// Copyright (C) 2021, Jakob Wakeling
-// All rights reserved.
-
-
-
-#ifndef OMKOV_G_LEXER_H_O0ISYNPF
-#define OMKOV_G_LEXER_H_O0ISYNPF
-
-#include "cll/cll.h"
-
-#define TOK_KS \
-TOK_K(LK_VOID, "NULL") \
-TOK_K(LK_EOF,  "EOF") \
-\
-TOK_K(LK_IDN, "identifier") \
-TOK_K(LK_INT, "integer") \
-TOK_K(LK_FLT, "float") \
-TOK_K(LK_CHR, "character") \
-TOK_K(LK_STR, "string") \
-\
-TOK_K(LK_LBRACK, "[" ) \
-TOK_K(LK_RBRACK, "]" ) \
-TOK_K(LK_LPAREN, "(" ) \
-TOK_K(LK_RPAREN, ")" ) \
-TOK_K(LK_LBRACE, "{" ) \
-TOK_K(LK_RBRACE, "}" ) \
-TOK_K(LK_COLON,  ":" ) \
-TOK_K(LK_SCOLON, ";" ) \
-TOK_K(LK_PERIOD, ".") \
-TOK_K(LK_COMMA,  ",") \
-\
-TOK_K(LK_RARROW,  "->") \
-\
-TOK_K(LK_ADD,   "+") \
-TOK_K(LK_SUB,   "-") \
-TOK_K(LK_MUL,   "*") \
-TOK_K(LK_DIV,   "/") \
-TOK_K(LK_MOD,   "%") \
-TOK_K(LK_LNOT,  "!") \
-TOK_K(LK_BNOT,  "~") \
-TOK_K(LK_BAND,  "&") \
-TOK_K(LK_BOR,   "|") \
-TOK_K(LK_BXOR,  "^") \
-TOK_K(LK_SHL,   "<<") \
-TOK_K(LK_SHR,   ">>") \
-TOK_K(LK_EQ,    "==") \
-TOK_K(LK_NEQ,   "!=") \
-TOK_K(LK_LT,    "<") \
-TOK_K(LK_LTE,   "<=") \
-TOK_K(LK_GT,    ">") \
-TOK_K(LK_GTE,   ">=") \
-TOK_K(LK_LAND,  "&&") \
-TOK_K(LK_LOR,   "||") \
-TOK_K(LK_TERN,  "?") \
-TOK_K(LK_ASSN,  "=") \
-TOK_K(LK_ADDEQ, "+=") \
-TOK_K(LK_SDDEQ, "-=") \
-TOK_K(LK_MULEQ, "*=") \
-TOK_K(LK_DIVEQ, "/=") \
-TOK_K(LK_MODEQ, "%=") \
-TOK_K(LK_ANDEQ, "&=") \
-TOK_K(LK_OREQ,  "|=") \
-TOK_K(LK_XOREQ, "^=") \
-TOK_K(LK_SHLEQ, "<<=") \
-TOK_K(LK_SHREQ, ">>=") \
-\
-TOK_K(LK_PROC, "proc") \
-\
-TOK_K(LK_RETURN, "return" ) \
-TOK_K(LK_IF,     "if") \
-TOK_K(LK_ELSE,   "else") \
-TOK_K(LK_FOR,    "for") \
-
-#define TOK_K(a, b) a,
-typedef enum { TOK_KS } tok_k;
-#undef TOK_K
-
-typedef struct { tok_k k; pos p; str s; } tok;
-typedef struct { str s; UINT sp, sl, ln, cl; tok t; } lexer;
-
-extern str tok_ks[];
-
-extern lexer lex_init(str src, UINT len);
-extern tok lex_next(lexer *l);
-extern tok lex_kind(lexer *l, tok_k k);
-extern tok lex_peek(lexer *l);
-
-#endif // OMKOV_G_LEXER_H_O0ISYNPF
diff --git a/src/parse.c b/src/parse.c
new file mode 100644
index 0000000..8bd85c3
--- /dev/null
+++ b/src/parse.c
@@ -0,0 +1,195 @@
+// parser.c
+// Parser source file for G
+// Copyright (C) 2021, Jakob Wakeling
+// All rights reserved.
+
+
+
+#include "cll/cll.h"
+#include "g.h"
+#include "type.h"
+#include "util/stack.h"
+#include "value.h"
+
+#include "cll/error.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// #define L (p)
+
+char *ast_ks[] = {
+	"AK_VOID",
+	
+	"AK_DECL", "AK_ASSN", "AK_COMP",
+	
+	"AK_INT", "AK_FLT",
+	
+	"AK_VARIABLE",
+	"AK_CONSTANT",
+	"AK_PROCEDURE",
+	
+	"AK_RETURN",
+};
+
+static ast *parser_parse_root(lex *l);
+static ast *parser_parse_decl(lex *l);
+
+static ast *parser_parse_stmt(lex *l);
+static ast *parser_parse_stmt_comp(lex *l);
+
+static ast *parser_parse_expr(lex *l);
+static ast *parser_parse_expr_term(lex *l);
+static ast *parser_parse_expr_fact(lex *l);
+
+static ast *parser_parse_proc(lex *l);
+static ast *parser_parse_proc_parm(lex *l);
+static ast *parser_parse_proc_rett(lex *l);
+
+static ast *parser_parse_int(lex *l);
+
+ast *ast_init() { return calloc(1, sizeof (ast)); }
+void ast_free(ast *a) { stack_free(a->cs); free(a); return; }
+
+ast *parse(lex *l) { return parser_parse_root(l); }
+
+static ast *parser_parse_root(lex *l) {
+	return parser_parse_decl(l);
+}
+
+/* Parse a declaration. */
+static ast *parser_parse_decl(lex *l) {
+	ast *a = ast_init();
+	
+	a->s = lex_kind(l, LK_IDN).s;
+	lex_kind(l, LK_COLON);
+	
+	if (lex_peek(l).k == LK_IDN) { /* lookup and store type */ }
+	
+	switch (lex_peek(l).k) {
+	case LK_COLON:  { lex_kind(l, LK_COLON);  a->k = AK_DECL; } goto decl_expr;
+	case LK_ASSN: { lex_kind(l, LK_ASSN); a->k = AK_ASSN; } goto decl_expr;
+	decl_expr: { a->cl = parser_parse_expr(l); } break;
+	default: { error(
+		1, "%zu:%zu: Unexpected: \"%s\" (parser_parse_decl)",
+		lex_peek(l).p.ln, lex_peek(l).p.cl, tok_ks[lex_peek(l).k]
+	); } break;
+	}
+	
+	return a;
+}
+
+/* Parse a statement. */
+static ast *parser_parse_stmt(lex *l) {
+	ast *a = ast_init();
+	
+	switch (lex_peek(l).k) {
+	case LK_RETURN: { a->k = AK_RETURN; lex_kind(l, LK_RETURN); a->c = parser_parse_expr(l); } break;
+	default: { error(
+		1, "%zu:%zu: Unexpected: \"%s\" (parser_parse_stmt)",
+		lex_peek(l).p.ln, lex_peek(l).p.cl, tok_ks[lex_peek(l).k]
+	); } break;
+	}
+	
+	return a;
+}
+
+/* Parse a compound statement. */
+static ast *parser_parse_stmt_comp(lex *l) {
+	lex_kind(l, LK_LBRACE);
+	ast *a = ast_init(); a->k = AK_COMP;
+	a->cs = stack_init();
+	
+	/* Parse statements and expressions until EOF or closing brace */
+	for (; lex_peek(l).k != LK_EOF && lex_peek(l).k != LK_RBRACE;) {
+		switch (lex_peek(l).k) {
+		case LK_RETURN: { stack_push(a->cs, parser_parse_stmt(l)); } break;
+		default: { stack_push(a->cs, parser_parse_expr(l)); } break;
+		}
+		
+		if (lex_peek(l).k == LK_SCOLON) { lex_kind(l, LK_SCOLON); }
+	}
+	
+	lex_kind(l, LK_RBRACE); return a;
+}
+
+/* Parse an expression. */
+static ast *parser_parse_expr(lex *l) {
+	ast *al = parser_parse_expr_term(l);
+	
+	
+	
+	return al;
+}
+
+/* Parse an expression term. */
+static ast *parser_parse_expr_term(lex *l) {
+	ast *al = parser_parse_expr_fact(l);
+	
+	
+	
+	return al;
+}
+
+/* Parse an expression factor. */
+static ast *parser_parse_expr_fact(lex *l) {
+	switch (lex_peek(l).k) {
+	case LK_PROC: { return parser_parse_proc(l); } break;
+	case LK_INT: { return parser_parse_int(l); } break;
+	default: { error(
+		1, "%zu:%zu: Unexpected: \"%s\" (parser_parse_expr_fact)",
+		lex_peek(l).p.ln, lex_peek(l).p.cl, tok_ks[lex_peek(l).k]
+	); } break;
+	}
+}
+
+/* Parse a procedure. */
+static ast *parser_parse_proc(lex *l) {
+	lex_kind(l, LK_PROC);
+	ast *a = ast_init(); a->k = AK_PROCEDURE;
+	
+	lex_kind(l, LK_LPAREN);
+	a->cs = stack_init();
+	
+	/* Parse optional procedure parameter(s) */
+	if (lex_peek(l).k != LK_RPAREN) {
+		stack_push(a->cs, parser_parse_proc_parm(l));
+		
+		while (lex_peek(l).k == LK_COMMA) {
+			lex_kind(l, LK_COMMA);
+			stack_push(a->cs, parser_parse_proc_parm(l));
+		}
+	}
+	
+	lex_kind(l, LK_RPAREN);
+	
+	/* Parse optional procedure return type(s) */
+	/* TODO parse more than one unnamed return type */
+	if (lex_peek(l).k == LK_RARROW) {
+		lex_kind(l, LK_RARROW);
+		
+		/* TODO dont hardcode return type */
+		lex_kind(l, LK_IDN); a->t = t_s64;
+	}
+	
+	a->c = parser_parse_stmt_comp(l);
+	
+	return a;
+}
+
+/* Parse a procedure parameter. */
+static ast *parser_parse_proc_parm(lex *l) {
+	return NULL; /* TODO */
+}
+
+/* Parse a procedure return type. */
+static ast *parser_parse_proc_rett(lex *l) {
+	return NULL; /* TODO */
+}
+
+static ast *parser_parse_int(lex *l) {
+	val v = val_strint(lex_kind(l, LK_INT).s);
+	ast *a = ast_init(); a->k = AK_INT; a->v = v;
+	return a;
+}
diff --git a/src/parser.c b/src/parser.c
deleted file mode 100644
index 111fb32..0000000
--- a/src/parser.c
+++ /dev/null
@@ -1,198 +0,0 @@
-// parser.c
-// Parser source file for G
-// Copyright (C) 2021, Jakob Wakeling
-// All rights reserved.
-
-
-
-#include "lexer.h"
-#include "cll/cll.h"
-#include "parser.h"
-#include "type.h"
-#include "util/stack.h"
-#include "value.h"
-
-#include "cll/error.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define L (p->l)
-
-static ast *parser_parse_root(parser *p);
-static ast *parser_parse_decl(parser *p);
-
-static ast *parser_parse_stmt(parser *p);
-static ast *parser_parse_stmt_comp(parser *p);
-
-static ast *parser_parse_expr(parser *p);
-static ast *parser_parse_expr_term(parser *p);
-static ast *parser_parse_expr_fact(parser *p);
-
-static ast *parser_parse_proc(parser *p);
-static ast *parser_parse_proc_parm(parser *p);
-static ast *parser_parse_proc_rett(parser *p);
-
-static ast *parser_parse_int(parser *p);
-
-ast *ast_init() { return calloc(1, sizeof (ast)); }
-void ast_free(ast *a) { stack_free(a->cs); free(a); return; }
-
-const str ast_str(ast_k k) {
-	switch (k) {
-	case AK_VOID: { return "AK_VOID"; }
-	case AK_DECL: { return "AK_DECL"; }
-	case AK_ASSN: { return "AK_ASSN"; }
-	case AK_COMP: { return "AK_COMP"; }
-	case AK_INT: { return "AK_INT"; }
-	case AK_FLT: { return "AK_FLT"; }
-	case AK_VARIABLE: { return "AK_VARIABLE"; }
-	case AK_CONSTANT: { return "AK_CONSTANT"; }
-	case AK_PROCEDURE: { return "AK_PROCEDURE"; }
-	case AK_RETURN: { return "AK_RETURN"; }
-	}
-}
-
-parser parser_init(lexer *l) { return (parser){ l }; }
-ast *parser_parse(parser *p) { return parser_parse_root(p); }
-
-static ast *parser_parse_root(parser *p) {
-	return parser_parse_decl(p);
-}
-
-/* Parse a declaration. */
-static ast *parser_parse_decl(parser *p) {
-	ast *a = ast_init();
-	
-	a->s = lex_kind(L, LK_IDN).s;
-	lex_kind(L, LK_COLON);
-	
-	if (lex_peek(L).k == LK_IDN) { /* lookup and store type */ }
-	
-	switch (lex_peek(L).k) {
-	case LK_COLON:  { lex_kind(L, LK_COLON);  a->k = AK_DECL; } goto decl_expr;
-	case LK_ASSN: { lex_kind(L, LK_ASSN); a->k = AK_ASSN; } goto decl_expr;
-	decl_expr: { a->cl = parser_parse_expr(p); } break;
-	default: { error(
-		1, "%zu:%zu: Unexpected: \"%s\" (parser_parse_decl)",
-		lex_peek(L).p.ln, lex_peek(L).p.cl, tok_ks[lex_peek(L).k]
-	); } break;
-	}
-	
-	return a;
-}
-
-/* Parse a statement. */
-static ast *parser_parse_stmt(parser *p) {
-	ast *a = ast_init();
-	
-	switch (lex_peek(L).k) {
-	case LK_RETURN: { a->k = AK_RETURN; lex_kind(L, LK_RETURN); a->c = parser_parse_expr(p); } break;
-	default: { error(
-		1, "%zu:%zu: Unexpected: \"%s\" (parser_parse_stmt)",
-		lex_peek(L).p.ln, lex_peek(L).p.cl, tok_ks[lex_peek(L).k]
-	); } break;
-	}
-	
-	return a;
-}
-
-/* Parse a compound statement. */
-static ast *parser_parse_stmt_comp(parser *p) {
-	lex_kind(L, LK_LBRACE);
-	ast *a = ast_init(); a->k = AK_COMP;
-	a->cs = stack_init();
-	
-	/* Parse statements and expressions until EOF or closing brace */
-	for (; lex_peek(L).k != LK_EOF && lex_peek(L).k != LK_RBRACE;) {
-		switch (lex_peek(L).k) {
-		case LK_RETURN: { stack_push(a->cs, parser_parse_stmt(p)); } break;
-		default: { stack_push(a->cs, parser_parse_expr(p)); } break;
-		}
-		
-		if (lex_peek(L).k == LK_SCOLON) { lex_kind(L, LK_SCOLON); }
-	}
-	
-	lex_kind(L, LK_RBRACE); return a;
-}
-
-/* Parse an expression. */
-static ast *parser_parse_expr(parser *p) {
-	ast *al = parser_parse_expr_term(p);
-	
-	
-	
-	return al;
-}
-
-/* Parse an expression term. */
-static ast *parser_parse_expr_term(parser *p) {
-	ast *al = parser_parse_expr_fact(p);
-	
-	
-	
-	return al;
-}
-
-/* Parse an expression factor. */
-static ast *parser_parse_expr_fact(parser *p) {
-	switch (lex_peek(L).k) {
-	case LK_PROC: { return parser_parse_proc(p); } break;
-	case LK_INT: { return parser_parse_int(p); } break;
-	default: { error(
-		1, "%zu:%zu: Unexpected: \"%s\" (parser_parse_expr_fact)",
-		lex_peek(L).p.ln, lex_peek(L).p.cl, tok_ks[lex_peek(L).k]
-	); } break;
-	}
-}
-
-/* Parse a procedure. */
-static ast *parser_parse_proc(parser *p) {
-	lex_kind(L, LK_PROC);
-	ast *a = ast_init(); a->k = AK_PROCEDURE;
-	
-	lex_kind(L, LK_LPAREN);
-	a->cs = stack_init();
-	
-	/* Parse optional procedure parameter(s) */
-	if (lex_peek(L).k != LK_RPAREN) {
-		stack_push(a->cs, parser_parse_proc_parm(p));
-		
-		while (lex_peek(L).k == LK_COMMA) {
-			lex_kind(L, LK_COMMA);
-			stack_push(a->cs, parser_parse_proc_parm(p));
-		}
-	}
-	
-	lex_kind(L, LK_RPAREN);
-	
-	/* Parse optional procedure return type(s) */
-	/* TODO parse more than one unnamed return type */
-	if (lex_peek(L).k == LK_RARROW) {
-		lex_kind(L, LK_RARROW);
-		
-		/* TODO dont hardcode return type */
-		lex_kind(L, LK_IDN); a->t = t_s64;
-	}
-	
-	a->c = parser_parse_stmt_comp(p);
-	
-	return a;
-}
-
-/* Parse a procedure parameter. */
-static ast *parser_parse_proc_parm(parser *p) {
-	return NULL; /* TODO */
-}
-
-/* Parse a procedure return type. */
-static ast *parser_parse_proc_rett(parser *p) {
-	return NULL; /* TODO */
-}
-
-static ast *parser_parse_int(parser *p) {
-	val v = val_strint(lex_kind(L, LK_INT).s);
-	ast *a = ast_init(); a->k = AK_INT; a->v = v;
-	return a;
-}
diff --git a/src/parser.h b/src/parser.h
deleted file mode 100644
index 87209dc..0000000
--- a/src/parser.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// parser.h
-// Parser header file for G
-// Copyright (C) 2021, Jakob Wakeling
-// All rights reserved.
-
-
-
-#ifndef OMKOV_G_PARSER_H_1QQ9RNKG
-#define OMKOV_G_PARSER_H_1QQ9RNKG
-
-#include "lexer.h"
-#include "cll/cll.h"
-#include "type.h"
-#include "util/stack.h"
-#include "value.h"
-
-typedef enum {
-	AK_VOID,
-	
-	AK_DECL, AK_ASSN, AK_COMP,
-	
-	AK_INT, AK_FLT,
-	
-	AK_VARIABLE,
-	AK_CONSTANT,
-	AK_PROCEDURE,
-	
-	AK_RETURN,
-} ast_k; /* AST Kind */
-
-typedef struct ast {
-	ast_k k; pos p; type *t; val v; str s;
-	struct ast *c, *cl, *cr; stack *cs;
-	
-	union {};
-} ast;
-
-typedef struct { lexer *l; } parser;
-
-extern ast *ast_init();
-extern void ast_free(ast *a);
-extern const str ast_str(ast_k k);
-
-extern parser parser_init(lexer *l);
-extern ast *parser_parse(parser *p);
-
-#endif // OMKOV_G_PARSER_H_1QQ9RNKG
diff --git a/src/util/ast.h b/src/util/ast.h
index 7f7cd7a..660b235 100644
--- a/src/util/ast.h
+++ b/src/util/ast.h
@@ -8,14 +8,14 @@
 #ifndef OMKOV_G_AST_H_TUNIMNOY
 #define OMKOV_G_AST_H_TUNIMNOY
 
-#include "../parser.h"
-#include "../misc.h"
+#include "../g.h"
+#include "../cll/cll.h"
 
 #include <stdio.h>
 
 static void ast_print(ast *a, UINT i) {
 	for (UINT j = 0; j != i; ++j) { printf("    "); }
-	printf("%zu:%zu: %s: %s\n", a->p.ln, a->p.cl, ast_str(a->k), a->s);
+	printf("%zu:%zu: %s: %s\n", a->p.ln, a->p.cl, ast_ks[a->k], a->s);
 
 	if (a->c) { ast_print(a->c, i + 1); }
 	if (a->cl) { ast_print(a->cl, i + 1); }
diff --git a/src/util/stack.h b/src/util/stack.h
index 5c986c1..d1a4acc 100644
--- a/src/util/stack.h
+++ b/src/util/stack.h
@@ -8,7 +8,7 @@
 #ifndef OMKOV_G_STACK_H_0R2AT1B5
 #define OMKOV_G_STACK_H_0R2AT1B5
 
-#include "../misc.h"
+#include "../cll/cll.h"
 
 typedef struct { ptr *a; UINT al, ac; } stack;