summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthing 1 <thing1@seacrossedlovers.xyz>2025-01-10 17:38:56 +0000
committerthing 1 <thing1@seacrossedlovers.xyz>2025-01-10 17:38:56 +0000
commite46e08fceff29622399855043554635d6e33c3c4 (patch)
treeb8074819364bd54b54b4798f07002fe234c506ac
init commit
-rw-r--r--Makefile21
-rw-r--r--builtin.c136
-rw-r--r--builtin.h3
-rw-r--r--builtin.obin0 -> 10456 bytes
-rw-r--r--eval.c69
-rw-r--r--eval.h18
-rw-r--r--eval.obin0 -> 8416 bytes
-rwxr-xr-xluckybin0 -> 34784 bytes
-rw-r--r--lucky.c32
-rw-r--r--lucky.obin0 -> 7672 bytes
-rw-r--r--parser.c116
-rw-r--r--parser.h36
-rw-r--r--parser.obin0 -> 10200 bytes
-rw-r--r--stack.c45
-rw-r--r--stack.h14
-rw-r--r--stack.obin0 -> 4904 bytes
-rw-r--r--test.lk3
17 files changed, 493 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..773b473
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+CC=cc
+CFLAGS=-ggdb -Wall
+LIBS=
+
+SRC = stack.c parser.c eval.c builtin.c lucky.c
+OBJ = ${SRC:.c=.o}
+
+all: lucky
+
+.c.o:
+ ${CC} -c ${CFLAGS} $<
+lucky: ${OBJ}
+ ${CC} -o $@ ${OBJ} ${LIBS}
+install: all
+ cp lucky /usr/local/bin/lucky
+clean:
+ rm -rf lucky *.o
+uninstall:
+ rm /usr/local/bin/lucky
+
+.PHONY: all clean install uninstall
diff --git a/builtin.c b/builtin.c
new file mode 100644
index 0000000..89995a3
--- /dev/null
+++ b/builtin.c
@@ -0,0 +1,136 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include "parser.h"
+#include "eval.h"
+
+bool arithmetic(luckytree *tree, luckyval *out){
+ if (strcmp(tree->function, "+") == 0){
+ argcounterror(tree, 2);
+ if (tree->arguments->type == LUCKYINT && tree->arguments->nextelement->type == LUCKYINT){
+ out->i = tree->arguments->i + tree->arguments->nextelement->i;
+ out->type = LUCKYINT;
+ }else if (tree->arguments->type == LUCKYFLOAT && tree->arguments->nextelement->type == LUCKYFLOAT){
+ out->f = tree->arguments->f + tree->arguments->nextelement->f;
+ out->type = LUCKYFLOAT;
+ }else if (tree->arguments->type == LUCKYFLOAT && tree->arguments->nextelement->type == LUCKYINT){
+ out->f = tree->arguments->f + tree->arguments->nextelement->i;
+ out->type = LUCKYFLOAT;
+ }else if (tree->arguments->type == LUCKYINT && tree->arguments->nextelement->type == LUCKYFLOAT){
+ out->f = tree->arguments->i + tree->arguments->nextelement->f;
+ out->type = LUCKYFLOAT;
+ }
+ else {
+ printf("invalid types given!\n");
+ exit(1);
+ }
+ }
+ else if (strcmp(tree->function, "-") == 0){
+ argcounterror(tree, 2);
+ if (tree->arguments->type == LUCKYINT && tree->arguments->nextelement->type == LUCKYINT){
+ out->i = tree->arguments->i - tree->arguments->nextelement->i;
+ out->type = LUCKYINT;
+ }else if (tree->arguments->type == LUCKYFLOAT && tree->arguments->nextelement->type == LUCKYFLOAT){
+ out->f = tree->arguments->f - tree->arguments->nextelement->f;
+ out->type = LUCKYFLOAT;
+ }else if (tree->arguments->type == LUCKYFLOAT && tree->arguments->nextelement->type == LUCKYINT){
+ out->f = tree->arguments->f - tree->arguments->nextelement->i;
+ out->type = LUCKYFLOAT;
+ }else if (tree->arguments->type == LUCKYINT && tree->arguments->nextelement->type == LUCKYFLOAT){
+ out->f = tree->arguments->i - tree->arguments->nextelement->f;
+ out->type = LUCKYFLOAT;
+ }
+ else {
+ printf("invalid types given!\n");
+ exit(1);
+ }
+ }
+ else if (strcmp(tree->function, "*") == 0){
+ argcounterror(tree, 2);
+ if (tree->arguments->type == LUCKYINT && tree->arguments->nextelement->type == LUCKYINT){
+ out->i = tree->arguments->i * tree->arguments->nextelement->i;
+ out->type = LUCKYINT;
+ }else if (tree->arguments->type == LUCKYFLOAT && tree->arguments->nextelement->type == LUCKYFLOAT){
+ out->f = tree->arguments->f * tree->arguments->nextelement->f;
+ out->type = LUCKYFLOAT;
+ }else if (tree->arguments->type == LUCKYFLOAT && tree->arguments->nextelement->type == LUCKYINT){
+ out->f = tree->arguments->f * tree->arguments->nextelement->i;
+ out->type = LUCKYFLOAT;
+ }else if (tree->arguments->type == LUCKYINT && tree->arguments->nextelement->type == LUCKYFLOAT){
+ out->f = tree->arguments->i * tree->arguments->nextelement->f;
+ out->type = LUCKYFLOAT;
+ }
+ else {
+ printf("invalid types given!\n");
+ exit(1);
+ }
+ }
+ else if (strcmp(tree->function, "/") == 0){
+ argcounterror(tree, 2);
+ if (tree->arguments->type == LUCKYINT && tree->arguments->nextelement->type == LUCKYINT){
+ out->i = tree->arguments->i / tree->arguments->nextelement->i;
+ out->type = LUCKYINT;
+ }else if (tree->arguments->type == LUCKYFLOAT && tree->arguments->nextelement->type == LUCKYFLOAT){
+ out->f = tree->arguments->f / tree->arguments->nextelement->f;
+ out->type = LUCKYFLOAT;
+ }else if (tree->arguments->type == LUCKYFLOAT && tree->arguments->nextelement->type == LUCKYINT){
+ out->f = tree->arguments->f / tree->arguments->nextelement->i;
+ out->type = LUCKYFLOAT;
+ }else if (tree->arguments->type == LUCKYINT && tree->arguments->nextelement->type == LUCKYFLOAT){
+ out->f = tree->arguments->i / tree->arguments->nextelement->f;
+ out->type = LUCKYFLOAT;
+ }
+ else {
+ printf("invalid types given!\n");
+ exit(1);
+ }
+ }
+ else return false;
+ return true;
+}
+
+bool variableops(luckytree *tree, luckyval *out){
+ if (strcmp(tree->function, "let") == 0){
+ argcounterror(tree, 2);
+ if (tree->arguments->type == LUCKYVAR) {
+ variables[varcount] = malloc(sizeof(luckyvar));
+ variables[varcount]->name = strdup(tree->arguments->var);
+
+ variables[varcount]->val = malloc(sizeof(luckyval));
+ memcpy(variables[varcount]->val, tree->arguments->nextelement, sizeof(luckyval));
+ varcount++;
+ } else {
+ printf("expected var name as the first argument!\n");
+ exit(1);
+ }
+ }
+ else return false;
+ return true;
+}
+
+bool io(luckytree *tree, luckyval *out){
+ if (strcmp(tree->function, "print") == 0){
+ argcounterror(tree, 1);
+ if (tree->arguments->type == LUCKYINT)
+ printf("%d\n", tree->arguments->i);
+ if (tree->arguments->type == LUCKYFLOAT)
+ printf("%f\n", tree->arguments->f);
+ }
+ else if (strcmp(tree->function, "readint") == 0){
+ argcounterror(tree, 0);
+ int i;
+ scanf("%d", &i);
+ out->i = i;
+ out->type = LUCKYINT;
+ }
+ else if (strcmp(tree->function, "readfloat") == 0){
+ argcounterror(tree, 0);
+ float f;
+ scanf("%f", &f);
+ out->f = f;
+ out->type = LUCKYFLOAT;
+ }
+ else return false;
+ return true;
+}
diff --git a/builtin.h b/builtin.h
new file mode 100644
index 0000000..acbfd31
--- /dev/null
+++ b/builtin.h
@@ -0,0 +1,3 @@
+bool arithmetic(luckytree *tree, luckyval *out);
+bool variableops(luckytree *tree, luckyval *out);
+bool io(luckytree *tree, luckyval *out);
diff --git a/builtin.o b/builtin.o
new file mode 100644
index 0000000..5a57c5b
--- /dev/null
+++ b/builtin.o
Binary files differ
diff --git a/eval.c b/eval.c
new file mode 100644
index 0000000..4f4b1e2
--- /dev/null
+++ b/eval.c
@@ -0,0 +1,69 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include "parser.h"
+#include "builtin.h"
+#include "eval.h"
+
+int varcount = 0;
+luckyvar *variables[10000];
+
+int funccount= 0;
+luckytree *functions[10000];
+
+int argcount(luckyval *tree){
+ if (tree == NULL) return 0;
+ else return 1 + argcount(tree->nextelement);
+}
+
+bool checkargcount(luckytree *tree, int i){
+ return !(argcount(tree->arguments) == i);
+}
+
+void argcounterror(luckytree *tree, int expected){
+ if (checkargcount(tree, expected)) {
+ printf("expected %d args to function %s, got %d\n",expected, tree->function, argcount(tree->arguments));
+ exit(1);
+ }
+}
+
+luckyval *lookupvar(char *name){
+ for (int i = 0; i < 10000; i++){
+ if (variables[i] != NULL && strcmp(variables[i]->name, name) == 0){
+ return variables[i]->val;
+ }
+ }
+ printf("no such variable %s exists!\n", name);
+ exit(1);
+}
+
+luckyval *eval(luckytree *tree){
+ int i = 0;
+ for (luckyval *current = tree->arguments; i < argcount(tree->arguments); current = current->nextelement){
+ if (current->type == LUCKYTREE){
+ luckyval *var = malloc(sizeof(luckyval));
+ var = eval(current->tree);
+ memcpy(&current->d, &var->d, sizeof(double));
+ current->type = var->type;
+ free(var);
+ }
+ else if (strcmp(tree->function, "let") != 0) {
+ if (current->type == LUCKYVAR){
+ luckyval *tmp = lookupvar(current->var);
+ memcpy(&current->d, &tmp->d, sizeof(double));
+ current->type = tmp->type;
+ }
+ }
+ i++;
+ }
+
+ luckyval *out = malloc(sizeof(luckyval));
+
+ if (arithmetic(tree, out)) return out;
+ else if (io(tree, out)) return out;
+ else if (variableops(tree, out)) return out;
+
+ printf("Unknown function!\n");
+ exit(1);
+}
diff --git a/eval.h b/eval.h
new file mode 100644
index 0000000..fa6523a
--- /dev/null
+++ b/eval.h
@@ -0,0 +1,18 @@
+typedef struct luckyvar luckyvar;
+
+typedef struct luckyvar {
+ luckyval *val;
+ char *name;
+} luckyvar;
+
+
+int argcount(luckyval *tree);
+bool checkargcount(luckytree *tree, int i);
+void argcounterror(luckytree *tree, int expected);
+luckyval *eval(luckytree *tree);
+
+extern luckyvar *variables[10000];
+extern int varcount;
+
+extern luckytree *functions[10000];
+extern int funccount;
diff --git a/eval.o b/eval.o
new file mode 100644
index 0000000..3a40933
--- /dev/null
+++ b/eval.o
Binary files differ
diff --git a/lucky b/lucky
new file mode 100755
index 0000000..59df94c
--- /dev/null
+++ b/lucky
Binary files differ
diff --git a/lucky.c b/lucky.c
new file mode 100644
index 0000000..7566895
--- /dev/null
+++ b/lucky.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include "parser.h"
+#include "eval.h"
+
+void strip(char *s, char c){
+ for (int i = 0; i < strlen(s); i++){
+ if (s[i] == c) {
+ s[i] = 0;
+ return;
+ }
+ }
+ return;
+
+}
+
+int main(int argc, char **argv){
+ FILE *f = fopen(argv[1], "r");
+ char *line = malloc(256);
+ while (fgets(line, 256, f) != NULL){
+ strip(line, '\n');
+ if (strlen(line) == 0) goto skip;
+
+ luckytree *tree = parse(line);
+ luckyval *ret = eval(tree);
+ free(tree);
+ free(ret);
+skip:
+ }
+}
diff --git a/lucky.o b/lucky.o
new file mode 100644
index 0000000..47324b3
--- /dev/null
+++ b/lucky.o
Binary files differ
diff --git a/parser.c b/parser.c
new file mode 100644
index 0000000..9bbc50b
--- /dev/null
+++ b/parser.c
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <ctype.h>
+#include "stack.h"
+#include "parser.h"
+#include "eval.h"
+
+static unsigned int jumpdist;
+
+static char *readexpr(char *expr){
+ char *out = malloc(strlen(expr+1));
+ char *c = expr;
+ stack *s = push(NULL, *c);
+ int i;
+
+ for (i = 0; s->len != 0; i++){
+ out[i] = *c;
+ c++;
+ if (*c == '(') s = push(s, '(');
+ else if (*c == ')' && peek(s) == '(') pop(s);
+ }
+ cleanstack(s);
+
+ out[i] = ')';
+ out[i+1] = 0;
+ out = realloc(out, strlen(out));
+ jumpdist = i+1;
+ return out;
+}
+
+static char *readval(char *expr){
+ char *out = strdup(expr);
+ char *gap = strchr(out, ' ');
+ if (gap == NULL) gap = strchr(out, ')');
+ jumpdist = (gap - out)+1;
+ *gap = 0;
+ out = realloc(out, strlen(out));
+ return out;
+}
+
+static luckyval *readargs(char *expr){
+ luckyval *head = malloc(sizeof(luckyval));
+
+ if (*expr != ')' && expr[0] != 0){
+ if (expr[0] == '(' ){ // nested function
+ char *subexpr = readexpr(expr);
+ expr += jumpdist + 1;
+ head->tree = parse(subexpr);
+ head->type = LUCKYTREE;
+ free(subexpr);
+ }
+ else if (strchr(expr, '.') != NULL){ // float
+ char *val = readval(expr);
+ expr += jumpdist;
+ head->f = atof(val);
+ head->type = LUCKYFLOAT;
+ free(val);
+ }
+ else if (isdigit(expr[0])){ // int
+ char *val = readval(expr);
+ expr += jumpdist;
+ head->i = atoi(val);
+ head->type = LUCKYINT;
+ free(val);
+ }
+ else { // var name
+ char *val = readval(expr);
+ expr += jumpdist;
+ head->var = strdup(val);
+ head->type = LUCKYVAR;
+ }
+ } else return NULL;
+
+ head->nextelement = readargs(expr);
+ return head;
+}
+
+luckytree *parse(char *expr){
+ char *c = expr;
+ stack *s = push(NULL, *c);
+ while (*c != 0){
+ c++;
+ if (*c == '(') s = push(s, '(');
+ else if (*c == ')' && peek(s) == '(') pop(s);
+ }
+ if (s->len != 0){
+ printf("%s\n", expr);
+ for (int i = 0; i < (c - expr) - 1; i++) printf(" ");
+ printf("^\n");
+ printf("bracket mismatch!\n");
+ exit(1);
+ }
+ cleanstack(s);
+
+ luckytree *tree = malloc(sizeof(luckytree));
+
+ int funcnamelen;
+ if (strchr(expr+1, ' ') == NULL)
+ funcnamelen = (strchr(expr+1, ')') - expr) - 1;
+ else
+ funcnamelen = (strchr(expr+1, ' ') - expr) - 1;
+
+ tree->function = malloc(funcnamelen + 1);
+
+ memcpy(tree->function, expr + 1, funcnamelen);
+ tree->function[funcnamelen] = 0;
+
+ expr += funcnamelen + 2;
+
+ tree->arguments = readargs(expr);
+
+ return tree;
+}
+
diff --git a/parser.h b/parser.h
new file mode 100644
index 0000000..3f6e2e3
--- /dev/null
+++ b/parser.h
@@ -0,0 +1,36 @@
+typedef struct luckyval luckyval;
+typedef struct luckytree luckytree;
+
+typedef enum luckytypes {
+ LUCKYCHAR,
+ LUCKYINT,
+ LUCKYLONG,
+ LUCKYFLOAT,
+ LUCKYDOUBLE,
+ LUCKYARR,
+ LUCKYVAR,
+ LUCKYTREE,
+} luckytypes;
+
+typedef struct luckyval {
+ union {
+ char c;
+ int i;
+ long l;
+ float f;
+ double d;
+ luckyval *arr;
+ luckytree *tree;
+ char *var;
+ };
+ luckytypes type;
+ luckyval *nextelement;
+} luckyval;
+
+typedef struct luckytree {
+ char *function;
+ luckyval *arguments;
+ luckytree *next;
+} luckytree;
+
+luckytree *parse(char *expr);
diff --git a/parser.o b/parser.o
new file mode 100644
index 0000000..ec08f0c
--- /dev/null
+++ b/parser.o
Binary files differ
diff --git a/stack.c b/stack.c
new file mode 100644
index 0000000..c07c7fc
--- /dev/null
+++ b/stack.c
@@ -0,0 +1,45 @@
+#include <stdlib.h>
+
+typedef struct stack stack;
+
+typedef struct stack {
+ char *tape;
+ int len;
+ char *ptr;
+} stack;
+
+stack *push(stack *s, char c){
+ if (s == NULL) {
+ stack *outstack = malloc(sizeof(stack));
+ outstack->tape = malloc(1);
+ outstack->tape[0] = c;
+ outstack->ptr = outstack->tape;
+ outstack->len = 1;
+ return outstack;
+ }
+ s->len++;
+ s->ptr++;
+ s->tape = realloc(s->tape, s->len);
+ *s->ptr = c;
+
+ return s;
+}
+
+char pop(stack *s){
+ char c = *s->ptr;
+ *s->ptr = 0;
+ s->len--;
+ s->ptr--;
+ s->tape = realloc(s->tape, s->len);
+
+ return c;
+}
+
+char peek(stack *s){
+ return *s->ptr;
+}
+
+void cleanstack(stack *s){
+ free(s->tape);
+ free(s);
+}
diff --git a/stack.h b/stack.h
new file mode 100644
index 0000000..ab3491b
--- /dev/null
+++ b/stack.h
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+
+typedef struct stack stack;
+
+typedef struct stack {
+ char *tape;
+ int len;
+ char *ptr;
+} stack;
+
+stack *push(stack *s, char c);
+char pop(stack *s);
+char peek(stack *s);
+void cleanstack(stack *s);
diff --git a/stack.o b/stack.o
new file mode 100644
index 0000000..e4d1968
--- /dev/null
+++ b/stack.o
Binary files differ
diff --git a/test.lk b/test.lk
new file mode 100644
index 0000000..77233bc
--- /dev/null
+++ b/test.lk
@@ -0,0 +1,3 @@
+(let a (readint))
+(let b (+ a 2))
+(print b