diff options
-rw-r--r-- | Makefile | 21 | ||||
-rw-r--r-- | builtin.c | 136 | ||||
-rw-r--r-- | builtin.h | 3 | ||||
-rw-r--r-- | builtin.o | bin | 0 -> 10456 bytes | |||
-rw-r--r-- | eval.c | 69 | ||||
-rw-r--r-- | eval.h | 18 | ||||
-rw-r--r-- | eval.o | bin | 0 -> 8416 bytes | |||
-rwxr-xr-x | lucky | bin | 0 -> 34784 bytes | |||
-rw-r--r-- | lucky.c | 32 | ||||
-rw-r--r-- | lucky.o | bin | 0 -> 7672 bytes | |||
-rw-r--r-- | parser.c | 116 | ||||
-rw-r--r-- | parser.h | 36 | ||||
-rw-r--r-- | parser.o | bin | 0 -> 10200 bytes | |||
-rw-r--r-- | stack.c | 45 | ||||
-rw-r--r-- | stack.h | 14 | ||||
-rw-r--r-- | stack.o | bin | 0 -> 4904 bytes | |||
-rw-r--r-- | test.lk | 3 |
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 Binary files differnew file mode 100644 index 0000000..5a57c5b --- /dev/null +++ b/builtin.o @@ -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(¤t->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(¤t->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); +} @@ -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; Binary files differBinary files differ@@ -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: + } +} Binary files differdiff --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 Binary files differnew file mode 100644 index 0000000..ec08f0c --- /dev/null +++ b/parser.o @@ -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); +} @@ -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); Binary files differ@@ -0,0 +1,3 @@ +(let a (readint)) +(let b (+ a 2)) +(print b |