diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cccl.c | 2 | ||||
| -rw-r--r-- | src/operation.c | 133 |
2 files changed, 135 insertions, 0 deletions
diff --git a/src/cccl.c b/src/cccl.c index 680ead4..e2bb788 100644 --- a/src/cccl.c +++ b/src/cccl.c @@ -8,6 +8,7 @@ #include <stdlib.h> #include <string.h> +#include "operation.h" #include "platform/getch.h" #include "utils.h" @@ -37,6 +38,7 @@ void cccl_init(s8 *filename) if (errno) die(1, strerror(errno)); pc.filename = filename; + cccl_operation_init(&pc); } void cccl_free() diff --git a/src/operation.c b/src/operation.c new file mode 100644 index 0000000..c56e381 --- /dev/null +++ b/src/operation.c @@ -0,0 +1,133 @@ +#include "operation.h" +#include "types.h" + +#include <cvector/cvector.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include "cccl.h" +#include "utils.h" + + +static cccl *pc; +static bool is_comment; +static i32 current; + +static const s8 *const name_allowed = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const s8 *const all_allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}[]()?;@=!&$%<>^+-*~#:/ \n\t"; +static const s8 *const skippable = " \t\n"; +static const s8 *const open_brackets = "[({?"; +static const s8 *const close_brackets = "])};"; + +static void check_symbol(void) +{ + if (!strchr(all_allowed, pc->code[pc->ep])) + die(1, "illegal character (%u at %d)", pc->code[pc->ep], pc->ep); +} + +static s8 read_operand(bool allow_underscore) +{ + i32 start = pc->ep; + for (++pc->ep; pc->ep < pc->size; ++pc->ep) + { + check_symbol(); + if (strchr(skippable, pc->code[pc->ep])) + continue; + if (!strchr(allow_underscore ? name_allowed : name_allowed + 1, pc->code[pc->ep])) + die( + 1, "invalid operand name (%c at %d for %c at %d)", + pc->code[pc->ep], pc->ep, + pc->code[start], start + ); + return pc->code[pc->ep]; + } + die( + 1, "no operand (for %c at %d)", + pc->code[start], start + ); +} + +static void require_stack_size(u32 size) +{ + if (cvector_size(pc->stack) < size) + die(1, "stack size is %d, but %d is required (%c at %d)", cvector_size(pc->stack), size, pc->code[current], current); +} + +static void op_noth(void) {} + +static void op_comment(void) +{ + is_comment = !is_comment; +} + +static void op_pushzero(void) +{ + cvector_push_back(pc->stack, 0); +} + +static void op_increment(void) +{ + require_stack_size(1); + ++*cvector_back(pc->stack); +} + +static void op_decrement(void) +{ + require_stack_size(1); + --*cvector_back(pc->stack); +} + +static void op_add(void) +{ + require_stack_size(2); + *(cvector_back(pc->stack) - 1) += *cvector_back(pc->stack); + cvector_pop_back(pc->stack); +} + +static void op_sub(void) +{ + require_stack_size(2); + *(cvector_back(pc->stack) - 1) -= *cvector_back(pc->stack); + cvector_pop_back(pc->stack); +} + +static void op_reverse(void) +{ + s8 operand = read_operand(true); + i16 *to_reverse = NULL; + i32 size; + + if (operand == '_') + size = cvector_size(pc->stack); +} + +void cccl_operation_init(cccl *pcp) +{ + pc = pcp; + is_comment = false; + current = 0; +} + +cccl_operation cccl_select_operation(void) +{ + if (is_comment && pc->code[pc->ep] == '\n') + return op_comment; + if (is_comment) + return op_noth; + + current = pc->ep; + check_symbol(); + + switch (pc->code[pc->ep]) + { + case ' ': /* FALLTHROUGH */ + case '\t': /* FALLTHROUGH */ + case ';': return op_noth; + case '/': return op_comment; + case '^': return op_pushzero; + case '+': return op_increment; + case '-': return op_decrement; + default: die(1, "You shouldn't be there!"); + } +} |