OBFI

Brainfuck Interpreter
git clone http://git.omkov.net/OBFI
Log | Tree | Refs | README | LICENCE | Download

AuthorJakob Wakeling <[email protected]>
Date2020-07-14 01:19:48
Commit1dbad8b9aeadce33deef132408056ee00d1cbdb9
Parent44e07d6c967d25f6473f026083580cff382a8b08

Restructure and refactor interpreter

Diffstat

M CMakeLists.txt | 2 +-
D ext/optget.h | 169 --------------------------------------------------------------------------------
D src/main.c | 136 --------------------------------------------------------------------------------
A src/obfi.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D src/parse.c | 76 ----------------------------------------------------------------------------
D src/parse.h | 58 ----------------------------------------------------------

6 files changed, 149 insertions, 440 deletions

diff --git a/CMakeLists.txt b/CMakeLists.txt
index cac770c..e18fc46 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
 SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
 SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
 
-ADD_COMPILE_DEFINITIONS(VERSION="1.0.1")
+ADD_COMPILE_DEFINITIONS(VERSION="1.0.2")
 
 FILE(GLOB SOURCES ${CMAKE_SOURCE_DIR}/src/*)
 
diff --git a/ext/optget.h b/ext/optget.h
deleted file mode 100644
index cc9ed90..0000000
--- a/ext/optget.h
+++ /dev/null
@@ -1,169 +0,0 @@
-// optget.h, version 1.5.1
-// OMKOV optget library
-// Copyright (C) 2020, Jakob Wakeling
-// All rights reserved.
-
-/*
-OMKOV Permissive Licence, version 1.0
-
-Copyright (C) 2020, Jakob Wakeling
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal with
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimers.
-* Redistributions in binary form must reproduce the above copyright notice, this
-  list of conditions and the following disclaimers in the documentation and/or
-  other materials provided with the distribution.
-* Neither the names of the copyright holders, nor the names of its contributors
-  may be used to endorse or promote products derived from this Software without
-  specific prior written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT
-HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
-*/
-
-#ifndef OMKOV_OPTGET_H_W3LIZK1S
-#define OMKOV_OPTGET_H_W3LIZK1S
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-#include <stdio.h>
-#include <string.h>
-
-#define ARG_NUL 0
-#define ARG_REQ 1
-#define ARG_OPT 2
-
-typedef struct {
-	char *str;
-	int arg, val;
-} lop_t;
-
-typedef struct {
-	int ind, opt, pos, nop;
-	char *arg, *lop, *str;
-	lop_t *lops;
-} opt_t;
-
-static const opt_t OPTGET_INIT = { 1, 0, 1, 0, NULL, NULL, NULL, NULL };
-
-static inline void _permute(char *argv[], int ind, int n);
-
-#define cur argv[opt->ind]
-
-/*
-	Parse the next command line argument
-*/
-static inline int optget(opt_t *opt, char *argv[], int flags) {
-	if (flags & 1) {
-		for (; cur && (cur[0] != '-' || cur[1] == 0); ++opt->ind, ++opt->nop);
-		if (!cur) { opt->ind -= opt->nop; opt->nop = 0; return -1; }
-	}
-	else if (!cur || (cur[0] != '-' || cur[1] == 0)) { return -1; }
-	
-	int optind = opt->ind, optret;
-	
-	if (cur[1] == '-') {
-		if (cur[2] == 0) { if (opt->nop) {
-				_permute(argv, opt->ind++, opt->nop);
-				opt->ind -= opt->nop; opt->nop = 0;
-			} else { ++opt->ind; } return -1;
-		}
-		
-		int optend, lop; optret = '?'; opt->opt = 0; opt->lop = cur;
-		if (!opt->lops) { goto nol; }
-		for (optend = 2; cur[optend] != '=' && cur[optend] != 0; ++optend) {}
-		
-		for (lop = 0; opt->lops[lop].str; ++lop) {
-			if (strncmp(&cur[2], opt->lops[lop].str, (size_t)optend - 2) == 0) {
-				if (!opt->lops[lop].str[optend - 2]) {
-					optret = opt->opt = opt->lops[lop].val;
-					break;
-				}
-			}
-		}
-		
-		if (opt->lops[lop].arg > ARG_NUL) {
-			if (cur[optend]) { opt->arg = &cur[optend + 1]; }
-			else if (argv[opt->ind + 1]) { opt->arg = argv[++opt->ind]; }
-			else {
-				if (opt->lops[lop].arg == ARG_REQ) { optret = ':'; }
-				opt->arg = NULL;
-			}
-		}
-		else { opt->arg = NULL; }
-		
-nol:	opt->pos = 0;
-	}
-	else {
-		optret = opt->opt = cur[opt->pos++]; opt->lop = NULL;
-		const char *optchr = strchr(opt->str, opt->opt);
-		
-		if (!optchr) { optret = '?'; }
-		else if (optchr[1] == ':') {
-			if (cur[opt->pos]) { opt->arg = &cur[opt->pos]; }
-			else if (argv[opt->ind + 1]) { opt->arg = argv[++opt->ind]; }
-			else { opt->arg = NULL; optret = ':'; }
-			opt->pos = 0;
-		}
-		else { opt->arg = NULL; }
-	}
-	
-	if (!opt->pos || !cur[opt->pos]) {
-		++opt->ind; opt->pos = 1;
-		if (opt->nop) for (; optind < opt->ind; ++optind) {
-			_permute(argv, optind, opt->nop);
-		}
-	}
-	
-	if (optret == '?' && opt->str[0] != ':') {
-		if (opt->opt) {
-			fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], opt->opt);
-		}
-		else if (opt->lop) {
-			fprintf(stderr, "%s: invalid option '%s'\n", argv[0], opt->lop);
-		}
-	}
-	if (optret == ':' && opt->str[0] != ':') {
-		if (opt->opt) {
-			fprintf(stderr, "%s: option requires argument -- '%c'\n", argv[0],
-					opt->opt);
-		}
-		else if (opt->lop) {
-			fprintf(stderr, "%s: option requires argument '%s'\n", argv[0],
-					opt->lop);
-		}
-	}
-	
-	return optret;
-}
-
-/*
-	Permute arguments
-*/
-static inline void _permute(char *argv[], int ind, int n) {
-	char *arg = argv[ind];
-	for (int i = ind; i > ind - n; --i) { argv[i] = argv[i - 1]; }
-	argv[ind - n] = arg;
-	return;
-}
-
-#undef cur // argv[opt->ind]
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-#endif // OMKOV_OPTGET_H_W3LIZK1S
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 119d803..0000000
--- a/src/main.c
+++ /dev/null
@@ -1,136 +0,0 @@
-// main.c
-// Main source file for OBFI
-// Copyright (C) 2020, Jakob Wakeling
-// All rights reserved.
-
-/*
-OMKOV Permissive Licence, version 1.0
-
-Copyright (C) 2020, Jakob Wakeling
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal with
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimers.
-* Redistributions in binary form must reproduce the above copyright notice, this
-  list of conditions and the following disclaimers in the documentation and/or
-  other materials provided with the distribution.
-* Neither the names of the copyright holders, nor the names of its contributors
-  may be used to endorse or promote products derived from this Software without
-  specific prior written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT
-HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
-*/
-
-#include "parse.h"
-
-#include "error.h"
-#include "optget.h"
-
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static int execute(tok_t *toks);
-
-static void help(void);
-static void version(void);
-
-int main(int argc, char *argv[]) {
-	lop_t lops[] = {
-		{ "help",    ARG_NUL, 256 },
-		{ "version", ARG_NUL, 257 },
-		{ NULL, 0, 0 }
-	};
-	
-	opt_t opt = OPTGET_INIT; opt.str = ""; opt.lops = lops; int o;
-	while ((o = optget(&opt, argv, 1)) != -1) switch (o) {
-	case 256: { help(); return 0; }
-	case 257: { version(); return 0; }
-	default: { return 1; }
-	}
-	
-	if (opt.ind == argc) { error(1, "%s: missing operand", argv[0]); }
-	
-	char *file = argv[opt.ind]; struct stat fs;
-	if (stat(file, &fs)) { error(1, "%s: %s: %s", argv[0], file, serrno); }
-	
-	char *fb = malloc(sizeof (*fb) * fs.st_size + 1); fb[fs.st_size] = 0;
-	if (!fb) { error(1, "%s: %s", argv[0], serrno); }
-	
-	FILE *fi = fopen(file, "r");
-	if (!fi) { free(fb); error(1, "%s: %s: %s", argv[0], file, serrno); }
-	
-	fread(fb, 1, fs.st_size, fi); fclose(fi);
-	if (errno) { free(fb); error(1, "%s: %s: %s", argv[0], file, serrno); }
-	
-	tok_t *toks = parse(fb, fs.st_size); free(fb);
-	if (!toks) { error(1, "%s: %s", argv[0], serrno); }
-	
-	if (execute(toks)) { free(toks); error(1, "%s: %s", argv[0], serrno); }
-	
-	free(toks); return 0;
-}
-
-static int execute(tok_t *toks) {
-	uint8_t arr[30000] = { 0 }, *ptr = arr;
-	
-	size_t cap = 64, top = 0; tok_t **dat;
-	if (!(dat = malloc(sizeof (*dat) * cap))) { return 1; }
-	
-	for (tok_t *t = toks; t->typ != EOF; ++t) switch (t->typ) {
-	case RGT: { ptr += t->num; break; }
-	case LFT: { ptr -= t->num; break; }
-	case ADD: { *ptr += t->num; break; }
-	case SUB: { *ptr -= t->num; break; }
-	case PUT: { fputc(*ptr, stdout); break; }
-	case GET: { *ptr = fgetc(stdin); break; }
-	case OPN: {
-		if (!*ptr) { for (size_t i = 1; i != 0; ++t) {
-			if ((t + 1)->typ == OPN) { ++i; }
-			else if ((t + 1)->typ == CLS) { --i; }
-		} break; }
-		
-		if (top == cap) {
-			tok_t **old = dat; cap *= 2; dat = realloc(dat, cap);
-			if (!dat) { free(old); return 1; }
-		} dat[top++] = t; break;
-	}
-	case CLS: { if (*ptr) { t = dat[top - 1]; } else { --top; } break; }
-	}
-	
-	free(dat); return 0;
-}
-
-static void help(void) {
-	puts("obfi - interpret brainfuck source file\n");
-	puts("usage: obfi file\n");
-	puts("options:");
-	puts("  --help     Display help information");
-	puts("  --version  Display version information");
-	return;
-}
-
-static void version(void) {
-	puts("OMKOV Brainfuck Interpreter, version " VERSION);
-	puts("Copyright (C) 2020, Jakob Wakeling");
-	puts("All rights reserved.");
-	puts("OMKOV Permissive Licence (https://www.omkov.net/OLPE)");
-	return;
-}
diff --git a/src/obfi.c b/src/obfi.c
new file mode 100644
index 0000000..7574d77
--- /dev/null
+++ b/src/obfi.c
@@ -0,0 +1,148 @@
+// obfi.c
+// Main source file for OBFI
+// Copyright (C) 2020, Jakob Wakeling
+// All rights reserved.
+
+/*
+OMKOV Permissive Licence, version 1.0
+
+Copyright (C) 2020, Jakob Wakeling
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimers.
+* Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimers in the documentation and/or
+  other materials provided with the distribution.
+* Neither the names of the copyright holders, nor the names of its contributors
+  may be used to endorse or promote products derived from this Software without
+  specific prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT
+HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
+*/
+
+#include "error.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TAPELEN 30000
+
+static inline int cmp(const char *s1, const char *s2);
+static inline int run(const char *b, const long *c);
+
+int main(int ac, char *av[]) {
+	if (ac == 1) { error(1, "%s: missing operand", av[0]); }
+	
+	FILE *fi = fopen(av[1], "r");
+	if (!fi) { error(1, "%s: %s: %s", av[0], av[1], serrno); }
+	
+	fseek(fi, 0, SEEK_END); size_t fl = ftell(fi); rewind(fi);
+	
+	char *fb = malloc(fl + 1 * sizeof (*fb)); fb[fl] = 0;
+	if (!fb) { error(1, "%s: %s", av[0], serrno); }
+	
+	long *fc = malloc(fl * sizeof (*fc));
+	if (!fc) { error(1, "%s: %s", av[0], serrno); }
+	
+	fread(fb, 1, fl, fi); fclose(fi);
+	
+	char *p = fb, *q = fb;
+	for (; *p; ++p) if (strchr("><+-.,[]", *p)) { *q++ = *p; } *q = 0;
+	
+	register size_t i, j;
+	for (i = 0; fb[i]; ++i) {
+	switch (fb[i]) {
+	case '<': case '-': { fc[i] = -1; break; }
+	default:            { fc[i] =  1; break; }
+	}
+	switch (fb[i]) {
+	case '>': case '<': { fb[i] = '>'; break; }
+	case '+': case '-': { fb[i] = '+'; break; }
+	}
+	}
+	
+	for (i = 0, j = 0; fb[i]; ++j) {
+		fb[j] = fb[i]; fc[j] = fc[i];
+		if (strchr(">+", fb[++i])) for (; fb[j] == fb[i]; fc[j] += fc[i++]);
+	} fb[j] = 0;
+	
+	for (i = 0; fb[i]; ++i) {
+		if (cmp(fb + i, "[+]")) { fb[i] = 'Z'; fb[i + 1] = fb[i + 2] = ' '; }
+		else if (cmp(fb + i, "[>]")) {
+			fb[i] = 'T'; fb[i + 1] = fb[i + 2] = ' '; fc[i] = fc[i + 1];
+		}
+		else if (cmp(fb + i, "[+>+>]") && fc[i + 1] == -1 && fc[i + 3] == 1 &&
+				fc[i + 2] == -fc[i + 4]) {
+			fb[i] = 'M';
+			fb[i + 1] = fb[i + 2] = fb[i + 3] = fb[i + 4] = fb[i + 5] = ' ';
+			fc[i] = fc[i + 2];
+		}
+		else if (cmp(fb + i, "[>+>+]") && fc[i + 4] == -1 && fc[i + 2] == 1 &&
+				fc[i + 1] == -fc[i + 3]) {
+			fb[i] = 'M';
+			fb[i + 1] = fb[i + 2] = fb[i + 3] = fb[i + 4] = fb[i + 5] = ' ';
+			fc[i] = fc[i + 1];
+		}
+	}
+	
+	for (i = 0, j = 0; fb[i]; ++i) if (fb[i] != ' ') {
+		fb[j] = fb[i]; fc[j] = fc[i]; ++j;
+	} fb[j] = 0;
+	
+	for (i = 0; fb[i]; ++i) {
+		for (j = 0; fb[i] != ">+.,[]ZTM"[j]; ++j) {} fb[i] = j + 1;
+	}
+	
+	size_t l = 1024, t = 0, *S = malloc(l * sizeof (*S));
+	if (!S) { error(1, "%s: %s", av[0], serrno); }
+	
+	for (size_t i = 0; fb[i]; ++i) switch (fb[i]) {
+	case 5: { S[t++] = i; break; }
+	case 6: { --t; fc[S[t]] = i - S[t]; fc[i] = S[t] - i; break; }
+	}
+	
+	if (run(fb, fc)) { error(1, "%s: %s", av[0], serrno); }
+	
+	free(S); free(fb); free(fc); return 0;
+}
+
+static inline int cmp(const char *s1, const char *s2) {
+	size_t i = 0; for (; s2[i] && s1[i] == s2[i]; ++i) {} return !s2[i];
+}
+
+static inline int run(const char *fb, const long *fc) {
+	uint_fast8_t *M = calloc(TAPELEN, sizeof (*M)), *p = M;
+	if (!M) { return 1; }
+	
+	for (size_t i = 0; fb[i]; ++i) switch (fb[i]) {
+	case 1: { p  += fc[i]; break; }
+	case 2: { *p += fc[i]; break; }
+	case 3: { fputc(*p, stdout); break; }
+	case 4: { *p = fgetc(stdin); break; }
+	case 5: { i += !*p ? fc[i] : 0; break; }
+	case 6: { i +=  *p ? fc[i] : 0; break; }
+	case 7: { *p = 0; break; }
+	case 8: { for (; *p; p += fc[i]) {} break; }
+	case 9: { *(p + fc[i]) += *p; *p = 0; break; }
+	}
+	
+	free(M); return 0;
+}
diff --git a/src/parse.c b/src/parse.c
deleted file mode 100644
index 4a0b3d0..0000000
--- a/src/parse.c
+++ /dev/null
@@ -1,76 +0,0 @@
-// parse.c
-// Parser source file for OBFI
-// Copyright (C) 2020, Jakob Wakeling
-// All rights reserved.
-
-/*
-OMKOV Permissive Licence, version 1.0
-
-Copyright (C) 2020, Jakob Wakeling
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal with
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimers.
-* Redistributions in binary form must reproduce the above copyright notice, this
-  list of conditions and the following disclaimers in the documentation and/or
-  other materials provided with the distribution.
-* Neither the names of the copyright holders, nor the names of its contributors
-  may be used to endorse or promote products derived from this Software without
-  specific prior written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT
-HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
-*/
-
-#include "parse.h"
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define TOKSET(type) tok.typ = type; tok.ln = line; tok.cl = col
-
-static inline tok_t lex(char *str) {
-	static char *p; static size_t line, col; tok_t tok;
-	if (str) { p = str; line = 0; col = 0; } tok.num = 1;
-	
-	for (; *p; ++p) switch (*p) {
-	case '>': { TOKSET(RGT); goto count; }
-	case '<': { TOKSET(LFT); goto count; }
-	case '+': { TOKSET(ADD); goto count; }
-	case '-': { TOKSET(SUB); goto count; }
-	case '.': { TOKSET(PUT); ++p; ++col; return tok; }
-	case ',': { TOKSET(GET); ++p; ++col; return tok; }
-	case '[': { TOKSET(OPN); ++p; ++col; return tok; }
-	case ']': { TOKSET(CLS); ++p; ++col; return tok; }
-	case '\n': { ++line; col = 0; continue; }
-	count: {
-		for (register char c = *p++; *p == c; ++p) { ++tok.num; }
-		col += tok.num; return tok;
-	}
-	}
-	
-	tok.typ = END; return tok;
-}
-
-tok_t *parse(char *str, size_t len) {
-	tok_t *toks = malloc(sizeof (*toks) * len);
-	if (!toks) { return NULL; }
-	
-	register tok_t *p = toks;
-	*p = lex(str); while (p->typ != END) { *++p = lex(NULL); }
-	
-	return toks;
-}
diff --git a/src/parse.h b/src/parse.h
deleted file mode 100644
index 453a6fe..0000000
--- a/src/parse.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// parse.h
-// Parser header file for OBFI
-// Copyright (C) 2020, Jakob Wakeling
-// All rights reserved.
-
-/*
-OMKOV Permissive Licence, version 1.0
-
-Copyright (C) 2020, Jakob Wakeling
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal with
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimers.
-* Redistributions in binary form must reproduce the above copyright notice, this
-  list of conditions and the following disclaimers in the documentation and/or
-  other materials provided with the distribution.
-* Neither the names of the copyright holders, nor the names of its contributors
-  may be used to endorse or promote products derived from this Software without
-  specific prior written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT
-HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
-*/
-
-#ifndef OMKOV_OBFI_PARSE_H_AD07BU3C
-#define OMKOV_OBFI_PARSE_H_AD07BU3C
-
-#include <stddef.h>
-#include <stdio.h>
-
-enum {
-	END = EOF, // EOF
-	RGT = 1,   // '>'
-	LFT = 2,   // '<'
-	ADD = 3,   // '+'
-	SUB = 4,   // '-'
-	PUT = 5,   // '.'
-	GET = 6,   // ','
-	OPN = 7,   // '['
-	CLS = 8,   // ']'
-};
-
-typedef struct { int typ; size_t num, ln, cl; } tok_t;
-
-extern tok_t *parse(char *str, size_t len);
-
-#endif // OMKOV_OBFI_PARSE_H_AD07BU3C