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
|
CC=gcc
|
||||||
CFLAGS=-Wall -Wextra -Wpedantic -ggdb -fsanitize=address -std=c11
|
CFLAGS=-Wall -Wextra -Wpedantic -ggdb -fsanitize=address -std=c11
|
||||||
LIBS=
|
LIBS=
|
||||||
OBJECTS=lib.o main.o
|
OBJECTS=lib.o parser.o main.o
|
||||||
OUT=obf.out
|
OUT=obf.out
|
||||||
ARGS=
|
ARGS=
|
||||||
|
|
||||||
|
|||||||
157
main.c
157
main.c
@@ -11,6 +11,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "./lib.h"
|
#include "./lib.h"
|
||||||
|
#include "./parser.h"
|
||||||
|
|
||||||
#define MEMORY_DEFAULT 30000
|
#define MEMORY_DEFAULT 30000
|
||||||
|
|
||||||
@@ -20,162 +21,6 @@ typedef struct
|
|||||||
uint8_t memory[MEMORY_DEFAULT];
|
uint8_t memory[MEMORY_DEFAULT];
|
||||||
} machine_t;
|
} 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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc == 1)
|
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