Compare commits
10 Commits
2a4d7addae
...
f4e0be8977
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4e0be8977 | ||
|
|
9fb9413c45 | ||
|
|
fbf2202cfd | ||
|
|
3c39df6c95 | ||
|
|
70cfeac995 | ||
|
|
493b98c524 | ||
|
|
2c1c89c048 | ||
|
|
b03ef6564a | ||
|
|
7686c1043c | ||
|
|
ffc8068a74 |
219
assembler.c
219
assembler.c
@@ -9,79 +9,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
// Structure representing a loop operative as indices into an ASM label array.
|
// Structure representing a loop operative as indices into an ASM label array.
|
||||||
struct Label
|
typedef struct
|
||||||
{
|
{
|
||||||
u64 cur, next;
|
u64 cur, next;
|
||||||
};
|
} label_t;
|
||||||
|
|
||||||
/* First, the functions to call external utilities (badly written, I know). They
|
|
||||||
* presume a filled asm_buffer. */
|
|
||||||
|
|
||||||
void asm_write(buffer_t **asm_buffer)
|
|
||||||
{
|
|
||||||
FILE *fp = fopen(asm_buffer[0]->name, "w");
|
|
||||||
fwrite(asm_buffer[0]->data, asm_buffer[0]->size, 1, fp);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int asm_assemble(const char *srcname, const char *objname)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
char *format_str = "yasm -f elf64 -g dwarf2 -o %s %s";
|
|
||||||
#else
|
|
||||||
char *format_str = "yasm -f elf64 -o %s %s";
|
|
||||||
#endif
|
|
||||||
char command[snprintf(NULL, 0, format_str, objname, srcname) + 1];
|
|
||||||
sprintf(command, format_str, objname, srcname);
|
|
||||||
return system(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
int asm_link(const char *objname, const char *outname)
|
|
||||||
{
|
|
||||||
char *format_str = "ld -o %s %s";
|
|
||||||
char command[snprintf(NULL, 0, format_str, outname, objname) + 1];
|
|
||||||
sprintf(command, format_str, outname, objname);
|
|
||||||
return system(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
int asm_compile(buffer_t **asm_buffer, const char *objname, const char *outname)
|
|
||||||
{
|
|
||||||
asm_write(asm_buffer);
|
|
||||||
asm_assemble(asm_buffer[0]->name, objname);
|
|
||||||
return asm_link(objname, outname);
|
|
||||||
}
|
|
||||||
|
|
||||||
void asm_setup_buffer(buffer_t **asm_buffer, const char *outname)
|
|
||||||
{
|
|
||||||
*asm_buffer = buffer_init_str(outname, NULL, 1024);
|
|
||||||
asm_buffer[0]->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the initial boilerplate of the assembly file
|
|
||||||
void asm_write_init(buffer_t **asm_buffer)
|
|
||||||
{
|
|
||||||
const char format_string[] = "section .bss\n"
|
|
||||||
" memory resb %d\n"
|
|
||||||
"section .text\n"
|
|
||||||
"global _start\n"
|
|
||||||
"_start:\n"
|
|
||||||
" mov r9, memory\n";
|
|
||||||
char initial_assembly[snprintf(NULL, 0, format_string, MEMORY_DEFAULT) + 1];
|
|
||||||
snprintf(initial_assembly, sizeof(initial_assembly), format_string,
|
|
||||||
MEMORY_DEFAULT);
|
|
||||||
buffer_append_bytes(asm_buffer, (u8 *)initial_assembly,
|
|
||||||
sizeof(initial_assembly) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the exit code for the assembly file
|
|
||||||
void asm_write_exit(buffer_t **asm_buffer)
|
|
||||||
{
|
|
||||||
buffer_append_bytes(asm_buffer,
|
|
||||||
(u8 *)" mov rax, 60\n"
|
|
||||||
" mov rdi, 0\n"
|
|
||||||
" syscall\n",
|
|
||||||
37);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A table which translates brainfuck operations into generic assembly code (I
|
// A table which translates brainfuck operations into generic assembly code (I
|
||||||
// love C's array indexing)
|
// love C's array indexing)
|
||||||
@@ -110,87 +41,94 @@ static const struct
|
|||||||
|
|
||||||
// Linear search in the ASM label array for a label with the current AST
|
// Linear search in the ASM label array for a label with the current AST
|
||||||
// relative index
|
// relative index
|
||||||
i64 get_abs_label(u64, struct Label *, u64);
|
i64 get_abs_label(u64, label_t *, u64);
|
||||||
|
|
||||||
// Translate an AST relative jump to a specific ASM label, storing the current
|
// Translate an AST relative jump to a specific ASM label, storing the current
|
||||||
// and next items in given pointers.
|
// and next items in given pointers.
|
||||||
void ast_ref_to_asm_label(u64, struct Label *, u64, i64 *, i64 *);
|
void ast_ref_to_asm_label(u64, label_t *, u64, i64 *, i64 *);
|
||||||
|
|
||||||
void asm_translate_nodes(buffer_t **asm_buffer, struct PResult nodes,
|
void asm_translate_nodes(vec_t *asm_buffer, struct PResult nodes,
|
||||||
const char *src_name)
|
const char *src_name)
|
||||||
{
|
{
|
||||||
asm_write_init(asm_buffer);
|
vec_append_fmt(asm_buffer,
|
||||||
|
"section .bss\n"
|
||||||
|
" memory resb %d\n"
|
||||||
|
"section .text\n"
|
||||||
|
"global _start\n"
|
||||||
|
"_start:\n"
|
||||||
|
" mov r9, memory\n",
|
||||||
|
MEMORY_DEFAULT);
|
||||||
|
|
||||||
// First pass: Setup the ASM label array
|
// First pass: Setup the ASM label array
|
||||||
struct Label labels[nodes.labels ? nodes.labels * 2 : 1];
|
label_t labels[nodes.labels ? nodes.labels * 2 : 1];
|
||||||
if (nodes.labels)
|
if (nodes.labels)
|
||||||
{
|
{
|
||||||
u64 label_ptr = 0;
|
u64 label_ptr = 0;
|
||||||
for (size_t i = 0; i < nodes.size; ++i)
|
for (size_t i = 0; i < nodes.size; ++i)
|
||||||
if (nodes.nodes[i].type == LIN || nodes.nodes[i].type == LOUT)
|
if (nodes.nodes[i].type == LIN || nodes.nodes[i].type == LOUT)
|
||||||
labels[label_ptr++] =
|
labels[label_ptr++] =
|
||||||
(struct Label){.cur = i, .next = nodes.nodes[i].loop_ref};
|
(label_t){.cur = i, .next = nodes.nodes[i].loop_ref};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second pass: Translating to assembly
|
// Second pass: Translating to assembly
|
||||||
for (size_t i = 0; i < nodes.size; ++i)
|
for (size_t i = 0; i < nodes.size; ++i)
|
||||||
{
|
{
|
||||||
node_t node = nodes.nodes[i];
|
ast_node_t node = nodes.nodes[i];
|
||||||
if (node.type == LIN || node.type == LOUT)
|
// Something we can compile with only the information at hand
|
||||||
|
if (!(node.type == LIN || node.type == LOUT))
|
||||||
{
|
{
|
||||||
// Translate the node-relative addresses to assembly-label-relative
|
// I love tables so goddamn much
|
||||||
// addresses
|
vec_append(asm_buffer, table[node.type].str, table[node.type].len);
|
||||||
i64 cur_asm_label = 0, next_asm_label = 0;
|
continue;
|
||||||
ast_ref_to_asm_label(i, labels, nodes.labels * 2, &cur_asm_label,
|
}
|
||||||
&next_asm_label);
|
|
||||||
if (cur_asm_label == -1 || next_asm_label == -1)
|
|
||||||
{
|
|
||||||
print_error(
|
|
||||||
src_name, node.row, node.col,
|
|
||||||
"[ASSEMBLY ERROR]: Could not find label for current jump!\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format labels
|
// NOTE: Must be a label
|
||||||
char current_label[128], next_label[128];
|
|
||||||
|
|
||||||
sprintf(current_label, ".L%lu", cur_asm_label);
|
// Translate the node-relative addresses to assembly-label-relative
|
||||||
sprintf(next_label, ".L%lu", next_asm_label);
|
// addresses
|
||||||
|
i64 cur_asm_label = 0, next_asm_label = 0;
|
||||||
|
ast_ref_to_asm_label(i, labels, nodes.labels * 2, &cur_asm_label,
|
||||||
|
&next_asm_label);
|
||||||
|
if (cur_asm_label == -1 || next_asm_label == -1)
|
||||||
|
{
|
||||||
|
print_error(src_name, node.row, node.col,
|
||||||
|
"[ASSEMBLY ERROR]: Could not find label for current jump!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// Setup format string for assembly jump code
|
// Format labels
|
||||||
char *format_string = NULL;
|
char current_label[128], next_label[128];
|
||||||
if (node.type == LIN)
|
|
||||||
{
|
sprintf(current_label, ".L%lu", cur_asm_label);
|
||||||
format_string = "%s:\n"
|
sprintf(next_label, ".L%lu", next_asm_label);
|
||||||
" cmp byte [r9], 0\n"
|
|
||||||
" je %s\n";
|
// Setup format string for assembly jump code
|
||||||
}
|
char *format_string = NULL;
|
||||||
else
|
if (node.type == LIN)
|
||||||
{
|
{
|
||||||
format_string = "%s:\n"
|
format_string = "%s:\n"
|
||||||
" cmp byte [r9], 0\n"
|
" cmp byte [r9], 0\n"
|
||||||
" jne %s\n";
|
" je %s\n";
|
||||||
}
|
|
||||||
char formatted_string[snprintf(NULL, 0, format_string, current_label,
|
|
||||||
next_label) +
|
|
||||||
1];
|
|
||||||
snprintf(formatted_string, sizeof(formatted_string), format_string,
|
|
||||||
current_label, next_label);
|
|
||||||
buffer_append_bytes(asm_buffer, (u8 *)formatted_string,
|
|
||||||
sizeof(formatted_string) - 1);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// I love tables so goddamn much
|
format_string = "%s:\n"
|
||||||
buffer_append_bytes(asm_buffer, (u8 *)table[node.type].str,
|
" cmp byte [r9], 0\n"
|
||||||
table[node.type].len);
|
" jne %s\n";
|
||||||
}
|
}
|
||||||
|
vec_append_fmt(asm_buffer, format_string, current_label, next_label);
|
||||||
}
|
}
|
||||||
asm_write_exit(asm_buffer);
|
|
||||||
|
vec_append(asm_buffer,
|
||||||
|
" mov rax, 60\n"
|
||||||
|
" mov rdi, 0\n"
|
||||||
|
" syscall\n",
|
||||||
|
37);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implementations for throwaway functions */
|
/* Implementations for throwaway functions */
|
||||||
|
|
||||||
i64 get_abs_label(u64 ref, struct Label *labels, u64 size)
|
i64 get_abs_label(u64 ref, label_t *labels, u64 size)
|
||||||
{
|
{
|
||||||
for (u64 i = 0; i < size; ++i)
|
for (u64 i = 0; i < size; ++i)
|
||||||
if (labels[i].cur == ref)
|
if (labels[i].cur == ref)
|
||||||
@@ -198,7 +136,7 @@ i64 get_abs_label(u64 ref, struct Label *labels, u64 size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_ref_to_asm_label(u64 ref, struct Label *labels, u64 size, i64 *cur,
|
void ast_ref_to_asm_label(u64 ref, label_t *labels, u64 size, i64 *cur,
|
||||||
i64 *next)
|
i64 *next)
|
||||||
{
|
{
|
||||||
*cur = get_abs_label(ref, labels, size);
|
*cur = get_abs_label(ref, labels, size);
|
||||||
@@ -206,3 +144,40 @@ void ast_ref_to_asm_label(u64 ref, struct Label *labels, u64 size, i64 *cur,
|
|||||||
return;
|
return;
|
||||||
*next = get_abs_label(labels[*cur].next, labels, size);
|
*next = get_abs_label(labels[*cur].next, labels, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The system calling code - not exactly pretty, but it is what it is. */
|
||||||
|
|
||||||
|
void asm_write(const char *asm_name, vec_t *asm_buffer)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(asm_name, "w");
|
||||||
|
fwrite(asm_buffer->data, asm_buffer->size, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int asm_assemble(const char *asm_name, const char *objname)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
char *format_str = "yasm -f elf64 -g dwarf2 -o %s %s";
|
||||||
|
#else
|
||||||
|
char *format_str = "yasm -f elf64 -o %s %s";
|
||||||
|
#endif
|
||||||
|
char command[SIZE_FMT(format_str, objname, asm_name) + 1];
|
||||||
|
sprintf(command, format_str, objname, asm_name);
|
||||||
|
return system(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
int asm_link(const char *objname, const char *outname)
|
||||||
|
{
|
||||||
|
char *format_str = "ld -o %s %s";
|
||||||
|
char command[SIZE_FMT(format_str, outname, objname) + 1];
|
||||||
|
sprintf(command, format_str, outname, objname);
|
||||||
|
return system(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
int asm_compile(vec_t *asm_buffer, const char *asm_name, const char *objname,
|
||||||
|
const char *outname)
|
||||||
|
{
|
||||||
|
asm_write(asm_name, asm_buffer);
|
||||||
|
asm_assemble(asm_name, objname);
|
||||||
|
return asm_link(objname, outname);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,14 +4,13 @@
|
|||||||
#include "./lib.h"
|
#include "./lib.h"
|
||||||
#include "./parser.h"
|
#include "./parser.h"
|
||||||
|
|
||||||
void asm_setup_buffer(buffer_t **asm_buffer, const char *outname);
|
void asm_translate_nodes(vec_t *asm_buffer, struct PResult nodes,
|
||||||
void asm_translate_nodes(buffer_t **asm_buffer, struct PResult nodes,
|
|
||||||
const char *src_name);
|
const char *src_name);
|
||||||
|
|
||||||
void asm_write(buffer_t **asm_buffer);
|
void asm_write(const char *asm_name, vec_t *asm_buffer);
|
||||||
int asm_assemble(const char *srcname, const char *objname);
|
int asm_assemble(const char *asm_name, const char *objname);
|
||||||
int asm_link(const char *objname, const char *outname);
|
int asm_link(const char *objname, const char *outname);
|
||||||
int asm_compile(buffer_t **asm_buffer, const char *objname,
|
int asm_compile(vec_t *asm_buffer, const char *asm_name, const char *objname,
|
||||||
const char *outname);
|
const char *outname);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
38
lib.c
38
lib.c
@@ -8,6 +8,12 @@
|
|||||||
|
|
||||||
#include "./lib.h"
|
#include "./lib.h"
|
||||||
|
|
||||||
|
bool usable_character(char c)
|
||||||
|
{
|
||||||
|
return c == '>' || c == '<' || c == '+' || c == '-' || c == '-' || c == '.' ||
|
||||||
|
c == ',' || c == '[' || c == ']';
|
||||||
|
}
|
||||||
|
|
||||||
buffer_t *buffer_init_str(const char *name, const char *str, size_t str_size)
|
buffer_t *buffer_init_str(const char *name, const char *str, size_t str_size)
|
||||||
{
|
{
|
||||||
buffer_t *buf = malloc(sizeof(*buf) + str_size + 1);
|
buffer_t *buf = malloc(sizeof(*buf) + str_size + 1);
|
||||||
@@ -61,8 +67,34 @@ char *fread_all(FILE *fp)
|
|||||||
return buffer.data;
|
return buffer.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usable_character(char c)
|
void vec_append(vec_t *vec, const void *const ptr, u64 size)
|
||||||
{
|
{
|
||||||
return c == '>' || c == '<' || c == '+' || c == '-' || c == '-' || c == '.' ||
|
vec_ensure_free(vec, size);
|
||||||
c == ',' || c == '[' || c == ']';
|
memcpy(vec->data + vec->size, ptr, size);
|
||||||
|
vec->size += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vec_ensure(vec_t *vec, u64 abs_size)
|
||||||
|
{
|
||||||
|
if (vec->capacity < abs_size)
|
||||||
|
{
|
||||||
|
vec->capacity = MAX(vec->capacity * 2, abs_size);
|
||||||
|
vec->data = realloc(vec->data, vec->capacity);
|
||||||
|
}
|
||||||
|
else if (!vec->data)
|
||||||
|
{
|
||||||
|
vec->data = calloc(1, vec->capacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vec_ensure_free(vec_t *vec, u64 rel_size)
|
||||||
|
{
|
||||||
|
vec_ensure(vec, vec->size + rel_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vec_free(vec_t *vec)
|
||||||
|
{
|
||||||
|
if (vec->data)
|
||||||
|
free(vec->data);
|
||||||
|
memset(vec, 0, sizeof(*vec));
|
||||||
}
|
}
|
||||||
|
|||||||
22
lib.h
22
lib.h
@@ -26,6 +26,8 @@ char *fread_all(FILE *fp);
|
|||||||
void print_error(const char *handle, size_t row, size_t column,
|
void print_error(const char *handle, size_t row, size_t column,
|
||||||
const char *reason);
|
const char *reason);
|
||||||
|
|
||||||
|
#define SIZE_FMT(FMT, ...) (snprintf(NULL, 0, (FMT), __VA_ARGS__))
|
||||||
|
|
||||||
typedef struct Buffer
|
typedef struct Buffer
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -34,4 +36,24 @@ typedef struct Buffer
|
|||||||
} buffer_t;
|
} buffer_t;
|
||||||
|
|
||||||
buffer_t *buffer_init_str(const char *name, const char *str, size_t str_size);
|
buffer_t *buffer_init_str(const char *name, const char *str, size_t str_size);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u64 size, capacity;
|
||||||
|
u8 *data;
|
||||||
|
} vec_t;
|
||||||
|
|
||||||
|
void vec_append(vec_t *vec, const void *const ptr, u64 size);
|
||||||
|
void vec_ensure(vec_t *vec, u64 abs_size);
|
||||||
|
void vec_ensure_free(vec_t *vec, u64 rel_size);
|
||||||
|
void vec_free(vec_t *vec);
|
||||||
|
|
||||||
|
#define vec_append_fmt(VEC, FMT, ...) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
char f[SIZE_FMT(FMT, __VA_ARGS__) + 1]; \
|
||||||
|
snprintf(f, sizeof(f), (FMT), __VA_ARGS__); \
|
||||||
|
vec_append((VEC), f, sizeof(f) - 1); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
21
obc.c
21
obc.c
@@ -59,6 +59,7 @@ int parse_config(struct Config *config, int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
if (!config->prog_name)
|
if (!config->prog_name)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +71,9 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *file_data = NULL;
|
char *file_data = NULL;
|
||||||
buffer_t *buffer = NULL, *asm_buffer = NULL;
|
buffer_t *buffer = NULL;
|
||||||
|
vec_t asm_buffer = {0};
|
||||||
struct PResult res = {0};
|
struct PResult res = {0};
|
||||||
|
|
||||||
struct Config config = {0};
|
struct Config config = {0};
|
||||||
@@ -81,6 +83,12 @@ int main(int argc, char *argv[])
|
|||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
if (!config.asm_name)
|
||||||
|
config.asm_name = "a.asm";
|
||||||
|
if (!config.obj_name)
|
||||||
|
config.obj_name = "a.o";
|
||||||
|
if (!config.exec_name)
|
||||||
|
config.exec_name = "a.out";
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
FILE *handle = fopen(config.prog_name, "r");
|
FILE *handle = fopen(config.prog_name, "r");
|
||||||
@@ -102,15 +110,10 @@ int main(int argc, char *argv[])
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
asm_setup_buffer(&asm_buffer, config.asm_name ? config.asm_name : "a.asm");
|
|
||||||
asm_translate_nodes(&asm_buffer, res, config.prog_name);
|
asm_translate_nodes(&asm_buffer, res, config.prog_name);
|
||||||
asm_write(&asm_buffer);
|
asm_compile(&asm_buffer, config.asm_name, config.obj_name, config.exec_name);
|
||||||
asm_assemble(asm_buffer->name, config.obj_name ? config.obj_name : "a.o");
|
|
||||||
asm_link(config.obj_name ? config.obj_name : "a.o",
|
|
||||||
config.exec_name ? config.exec_name : "a.out");
|
|
||||||
end:
|
end:
|
||||||
if (asm_buffer)
|
vec_free(&asm_buffer);
|
||||||
free(asm_buffer);
|
|
||||||
if (res.nodes)
|
if (res.nodes)
|
||||||
free(res.nodes);
|
free(res.nodes);
|
||||||
if (buffer)
|
if (buffer)
|
||||||
|
|||||||
4
obi.c
4
obi.c
@@ -25,11 +25,11 @@ typedef struct
|
|||||||
#endif
|
#endif
|
||||||
} machine_t;
|
} machine_t;
|
||||||
|
|
||||||
void interpret(machine_t *cpu, node_t *ast, size_t num)
|
void interpret(machine_t *cpu, ast_node_t *ast, size_t num)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < num; ++i)
|
for (size_t i = 0; i < num; ++i)
|
||||||
{
|
{
|
||||||
node_t node = ast[i];
|
ast_node_t node = ast[i];
|
||||||
switch (node.type)
|
switch (node.type)
|
||||||
{
|
{
|
||||||
case NEXT:
|
case NEXT:
|
||||||
|
|||||||
10
parser.c
10
parser.c
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "./parser.h"
|
#include "./parser.h"
|
||||||
|
|
||||||
char *ast_to_str(node_t *ast, size_t size)
|
char *ast_to_str(ast_node_t *ast, size_t size)
|
||||||
{
|
{
|
||||||
char *out = calloc(size + 1, 1);
|
char *out = calloc(size + 1, 1);
|
||||||
if (!out)
|
if (!out)
|
||||||
@@ -54,7 +54,7 @@ char *ast_to_str(node_t *ast, size_t size)
|
|||||||
|
|
||||||
struct PResult parse_buffer(buffer_t *buffer)
|
struct PResult parse_buffer(buffer_t *buffer)
|
||||||
{
|
{
|
||||||
node_t *nodes = NULL;
|
ast_node_t *nodes = NULL;
|
||||||
size_t usable = 0, loops = 0, loop_ends = 0;
|
size_t usable = 0, loops = 0, loop_ends = 0;
|
||||||
|
|
||||||
// First pass: Compute |nodes|
|
// First pass: Compute |nodes|
|
||||||
@@ -161,11 +161,11 @@ struct PResult parse_buffer(buffer_t *buffer)
|
|||||||
size_t stackptr = 0;
|
size_t stackptr = 0;
|
||||||
if (loops)
|
if (loops)
|
||||||
{
|
{
|
||||||
node_t *stack[loops];
|
ast_node_t *stack[loops];
|
||||||
memset(stack, 0, loops);
|
memset(stack, 0, loops);
|
||||||
for (size_t i = 0; i < usable; ++i)
|
for (size_t i = 0; i < usable; ++i)
|
||||||
{
|
{
|
||||||
node_t *node = nodes + i;
|
ast_node_t *node = nodes + i;
|
||||||
if (node->type == LIN)
|
if (node->type == LIN)
|
||||||
stack[stackptr++] = node;
|
stack[stackptr++] = node;
|
||||||
else if (node->type == LOUT)
|
else if (node->type == LOUT)
|
||||||
@@ -180,7 +180,7 @@ struct PResult parse_buffer(buffer_t *buffer)
|
|||||||
|
|
||||||
if (stackptr > 0)
|
if (stackptr > 0)
|
||||||
{
|
{
|
||||||
node_t *node = nodes + usable - 1;
|
ast_node_t *node = nodes + usable - 1;
|
||||||
print_error(buffer->name, node->row, node->col,
|
print_error(buffer->name, node->row, node->col,
|
||||||
"ERROR: Unbalanced square brackets!");
|
"ERROR: Unbalanced square brackets!");
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
30
parser.h
30
parser.h
@@ -3,31 +3,33 @@
|
|||||||
|
|
||||||
#include "./lib.h"
|
#include "./lib.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
NEXT = 0,
|
||||||
|
PREV,
|
||||||
|
INC,
|
||||||
|
DEC,
|
||||||
|
OUT,
|
||||||
|
READ,
|
||||||
|
LIN,
|
||||||
|
LOUT
|
||||||
|
} node_type_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
size_t col, row;
|
size_t col, row;
|
||||||
enum
|
node_type_t type;
|
||||||
{
|
|
||||||
NEXT = 0,
|
|
||||||
PREV,
|
|
||||||
INC,
|
|
||||||
DEC,
|
|
||||||
OUT,
|
|
||||||
READ,
|
|
||||||
LIN,
|
|
||||||
LOUT
|
|
||||||
} type;
|
|
||||||
int loop_ref;
|
int loop_ref;
|
||||||
} node_t;
|
} ast_node_t;
|
||||||
|
|
||||||
struct PResult
|
struct PResult
|
||||||
{
|
{
|
||||||
node_t *nodes;
|
ast_node_t *nodes;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t labels;
|
size_t labels;
|
||||||
};
|
};
|
||||||
|
|
||||||
char *ast_to_str(node_t *ast, size_t size);
|
char *ast_to_str(ast_node_t *ast, size_t size);
|
||||||
struct PResult parse_buffer(buffer_t *buffer);
|
struct PResult parse_buffer(buffer_t *buffer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user