From e5cba43a0e5a19360d87594ae22cdb94872e536c Mon Sep 17 00:00:00 2001 From: Aryadev Chavali Date: Sat, 2 Sep 2023 16:14:49 +0100 Subject: New module for parser functions Same principle as main->lib (previous commit). --- parser.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 parser.c (limited to 'parser.c') diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..d1bc9c9 --- /dev/null +++ b/parser.c @@ -0,0 +1,144 @@ +/* parser.c + * Created: 2023-09-02 + * Author: Aryadev Chavali + * Description: Functions for (de)serialising + */ + +#include + +#include "./parser.h" + +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; +} + +struct PResult parse_buffer(buffer_t *buffer) +{ + node_t *nodes = NULL; + size_t usable = 0, loops = 0; + for (size_t i = 0; i < buffer->size; ++i) + if (usable_character(buffer->data[i])) + { + ++usable; + if (buffer->data[i] == '[') + ++loops; + } + nodes = calloc(usable, sizeof(*nodes)); + + // First pass: Get my info + for (size_t i = 0, col = 0, row = 1, nptr = 0; i < buffer->size; ++i) + { + ++col; + if (buffer->data[i] == '\n') + { + ++row; + col = 0; + } + else if (usable_character(buffer->data[i])) + { + nodes[nptr].col = col; + nodes[nptr].row = row; + switch (buffer->data[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) + { + print_error(buffer->name, node->row, node->col, + "ERROR: Unbalanced square brackets!"); + goto error; + } + // Access last IN loop + --stackptr; + node->loop_ref = stack[stackptr] - nodes; + stack[stackptr]->loop_ref = i; + } + } + + if (stackptr > 0) + { + node_t *node = nodes + usable - 1; + print_error(buffer->name, node->row, node->col, + "ERROR: Unbalanced square brackets!"); + goto error; + } + + return (struct PResult){nodes, usable}; +error: + if (nodes) + free(nodes); + return (struct PResult){0}; +} -- cgit v1.2.3-13-gbd6f