aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2023-09-02 15:21:56 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2023-09-02 15:21:56 +0100
commit2d33640c037c9f3bcbddc200eec39bb713ca0c9f (patch)
treee23a1f2ac92959a6429d1cd8b5ff130da6074da9 /main.c
downloadobf-2d33640c037c9f3bcbddc200eec39bb713ca0c9f.tar.gz
obf-2d33640c037c9f3bcbddc200eec39bb713ca0c9f.tar.bz2
obf-2d33640c037c9f3bcbddc200eec39bb713ca0c9f.zip
INIT
Simple parser, took like an hour. Not very smart but at least it's like O(n).
Diffstat (limited to 'main.c')
-rw-r--r--main.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..5174e3d
--- /dev/null
+++ b/main.c
@@ -0,0 +1,193 @@
+/* main.c
+ * Created: 2023-09-02
+ * Author: Aryadev Chavali
+ * Description: Entrypoint of compiler
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MEMORY_DEFAULT 30000
+
+typedef struct
+{
+ size_t dp;
+ uint8_t memory[MEMORY_DEFAULT];
+} machine_t;
+
+bool usable_character(char c)
+{
+ return c == '>' || c == '<' || c == '+' || c == '-' || c == '-' || c == '.' ||
+ c == ',' || c == '[' || c == ']';
+}
+
+typedef struct AST
+{
+ size_t col, row;
+ enum
+ {
+ NEXT = 0,
+ PREV,
+ INC,
+ DEC,
+ OUT,
+ READ,
+ LIN,
+ LOUT
+ } type;
+ int loop_ref;
+} node_t;
+
+struct PResult
+{
+ node_t *nodes;
+ size_t size;
+} parse_input(const char *input, size_t input_size)
+{
+ node_t *nodes = NULL;
+ size_t usable = 0, loops = 0;
+ for (size_t i = 0; i < input_size; ++i)
+ if (usable_character(input[i]))
+ {
+ ++usable;
+ if (input[i] == '[')
+ ++loops;
+ }
+ nodes = calloc(usable, sizeof(*nodes));
+
+ // First pass: Get my info
+ for (size_t i = 0, col = 0, row = 1, nptr = 0; i < input_size; ++i)
+ {
+ ++col;
+ if (input[i] == '\n')
+ {
+ ++row;
+ col = 0;
+ }
+ else if (usable_character(input[i]))
+ {
+ nodes[nptr].col = col;
+ nodes[nptr].row = row;
+ switch (input[i])
+ {
+ case '>':
+ nodes[nptr].type = NEXT;
+ break;
+ case '<':
+ nodes[nptr].type = PREV;
+ break;
+ case '+':
+ nodes[nptr].type = INC;
+ break;
+ case '-':
+ nodes[nptr].type = DEC;
+ break;
+ case '.':
+ nodes[nptr].type = OUT;
+ break;
+ case ',':
+ nodes[nptr].type = READ;
+ break;
+ case '[':
+ nodes[nptr].type = LIN;
+ nodes[nptr].loop_ref = -1;
+ break;
+ case ']':
+ nodes[nptr].type = LOUT;
+ nodes[nptr].loop_ref = -1;
+ break;
+ }
+ ++nptr;
+ }
+ }
+
+ // Second pass: setup any loop references
+ node_t *stack[loops];
+ memset(stack, 0, loops);
+ size_t stackptr = 0;
+ for (size_t i = 0; i < usable; ++i)
+ {
+ node_t *node = nodes + i;
+ if (node->type == LIN)
+ stack[stackptr++] = node;
+ else if (node->type == LOUT)
+ {
+ if (stackptr == 0)
+ {
+ fputs("ERROR: Unbalanced square brackets!\n", stderr);
+ goto error;
+ }
+ // Access last IN loop
+ --stackptr;
+ node->loop_ref = stack[stackptr] - nodes;
+ stack[stackptr]->loop_ref = i;
+ }
+ }
+
+ if (stackptr > 0)
+ {
+ fputs("ERROR: Unbalanced square brackets!\n", stderr);
+ goto error;
+ }
+
+ return (struct PResult){nodes, usable};
+error:
+ if (nodes)
+ free(nodes);
+ return (struct PResult){0};
+}
+
+char *ast_to_str(node_t *ast, size_t size)
+{
+ char *out = calloc(size + 1, 1);
+ for (size_t i = 0; i < size; ++i)
+ {
+ switch (ast[i].type)
+ {
+ case NEXT:
+ out[i] = '>';
+ break;
+ case PREV:
+ out[i] = '<';
+ break;
+ case INC:
+ out[i] = '+';
+ break;
+ case DEC:
+ out[i] = '-';
+ break;
+ case OUT:
+ out[i] = '.';
+ break;
+ case READ:
+ out[i] = ',';
+ break;
+ case LIN:
+ out[i] = '[';
+ break;
+ case LOUT:
+ out[i] = ']';
+ break;
+ }
+ }
+ out[size] = '\0';
+ return out;
+}
+
+int main(void)
+{
+ const char input[] = "[[->+<]";
+ struct PResult res = parse_input(input, sizeof(input) / sizeof(input[0]));
+ if (res.nodes == NULL)
+ {
+ fputs("Exiting early...\n", stderr);
+ return 1;
+ }
+ char *str = ast_to_str(res.nodes, res.size);
+ free(str);
+ free(res.nodes);
+ return 0;
+}