INIT
Simple parser, took like an hour. Not very smart but at least it's like O(n).
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.out
|
||||
*.o
|
||||
20
Makefile
Normal file
20
Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -Wextra -Wpedantic -ggdb -fsanitize=address -std=c11
|
||||
LIBS=
|
||||
OBJECTS=main.o
|
||||
OUT=obf.out
|
||||
ARGS=
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $^ -o $@ $(LIBS)
|
||||
|
||||
$(OUT): $(OBJECTS)
|
||||
$(CC) $(CFLAGS) $^ -o $@ $(LIBS)
|
||||
|
||||
.PHONY:
|
||||
clean:
|
||||
rm -rfv $(OUT) $(OBJECTS)
|
||||
|
||||
.PHONY: run
|
||||
run: $(OUT)
|
||||
./$^ $(ARGS)
|
||||
193
main.c
Normal file
193
main.c
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user