about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNakidai <plaza521@inbox.ru>2024-08-23 16:48:01 +0300
committerNakidai <plaza521@inbox.ru>2024-08-23 16:48:01 +0300
commit9e4058194742794f7742f19cb1a0bb3451ce22ea (patch)
tree5f384d8624501c14db1040e19ca48d9542c92404
parentf4d71aa4a0f4d71104736e3d254d4b9a556e6170 (diff)
download3cl-9e4058194742794f7742f19cb1a0bb3451ce22ea.tar.gz
3cl-9e4058194742794f7742f19cb1a0bb3451ce22ea.zip
add operation.h
-rw-r--r--include/operation.h12
-rw-r--r--src/cccl.c2
-rw-r--r--src/operation.c133
3 files changed, 147 insertions, 0 deletions
diff --git a/include/operation.h b/include/operation.h
new file mode 100644
index 0000000..ce487da
--- /dev/null
+++ b/include/operation.h
@@ -0,0 +1,12 @@
+#ifndef __OPERATION_H__
+#define __OPERATION_H__
+
+#include "cccl.h"
+
+
+typedef void (*cccl_operation)(void);
+
+void cccl_operation_init(cccl *pc);
+cccl_operation cccl_select_operation(void);
+
+#endif /* __OPERATION_H__ */
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!");
+    }
+}