New module for parser functions
Same principle as main->lib (previous commit).
This commit is contained in:
2
Makefile
2
Makefile
@@ -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
157
main.c
@@ -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
144
parser.c
Normal 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
32
parser.h
Normal 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
|
||||
Reference in New Issue
Block a user