New module for parser functions

Same principle as main->lib (previous commit).
This commit is contained in:
2023-09-02 16:14:49 +01:00
parent c9b6b04d19
commit e5cba43a0e
4 changed files with 178 additions and 157 deletions

View File

@@ -1,7 +1,7 @@
CC=gcc
CFLAGS=-Wall -Wextra -Wpedantic -ggdb -fsanitize=address -std=c11
LIBS=
OBJECTS=lib.o main.o
OBJECTS=lib.o parser.o main.o
OUT=obf.out
ARGS=

157
main.c
View File

@@ -11,6 +11,7 @@
#include <string.h>
#include "./lib.h"
#include "./parser.h"
#define MEMORY_DEFAULT 30000
@@ -20,162 +21,6 @@ typedef struct
uint8_t memory[MEMORY_DEFAULT];
} machine_t;
typedef struct AST
{
size_t col, row;
enum
{
NEXT = 0,
PREV,
INC,
DEC,
OUT,
READ,
LIN,
LOUT
} type;
int loop_ref;
} node_t;
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
{
node_t *nodes;
size_t size;
} 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};
}
int main(int argc, char *argv[])
{
if (argc == 1)

144
parser.c Normal file
View File

@@ -0,0 +1,144 @@
/* parser.c
* Created: 2023-09-02
* Author: Aryadev Chavali
* Description: Functions for (de)serialising
*/
#include <string.h>
#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};
}

32
parser.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef PARSER_H
#define PARSER_H
#include "./lib.h"
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;
};
char *ast_to_str(node_t *ast, size_t size);
struct PResult parse_buffer(buffer_t *buffer);
#endif