From 56cde27ed3f0038095ec9ea37e57cb1fc550a7d5 Mon Sep 17 00:00:00 2001 From: nishi Date: Tue, 23 Apr 2024 05:04:40 +0000 Subject: [PATCH] parser kinda works git-svn-id: file:///raid/svn-main/nishi-serenade/trunk@11 0f02c867-ac3d-714e-8a88-971ba1f6efcf --- Serenade/Makefile | 2 +- Serenade/main.c | 28 ++++++++++ Serenade/parser.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++ Serenade/parser.h | 11 +++- Serenade/util.c | 23 ++++++++ Serenade/util.h | 11 ++++ Tool/configgen.c | 5 ++ 7 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 Serenade/util.c create mode 100644 Serenade/util.h diff --git a/Serenade/Makefile b/Serenade/Makefile index a2412fc..9a8de38 100644 --- a/Serenade/Makefile +++ b/Serenade/Makefile @@ -1,6 +1,6 @@ # $Id$ -SERENADE_OBJS = main.o parser.o +SERENADE_OBJS = main.o parser.o util.o .PHONY: all clean .SUFFIXES: .o .c diff --git a/Serenade/main.c b/Serenade/main.c index e79e2be..ac211f1 100644 --- a/Serenade/main.c +++ b/Serenade/main.c @@ -29,11 +29,14 @@ /* --- END LICENSE --- */ #include "serenade.h" +#include "parser.h" #include "../config.h" #include #include #include +#include +#include int main(int argc, char** argv){ int i; @@ -43,6 +46,7 @@ int main(int argc, char** argv){ if(strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-V") == 0){ printf("Serenade LISP %s\n", SERENADE_VERSION); printf("Support: %s\n", SUPPORT); + printf("Stack size: %d\n", STACK_SIZE); return 1; }else{ fprintf(stderr, "%s: %s: invalid option\n", argv[0], argv[i]); @@ -51,12 +55,36 @@ int main(int argc, char** argv){ }else{ /* file input */ loaded = true; + struct stat s; + if(stat(argv[i], &s) == 0){ + char* str = malloc(s.st_size); + FILE* f = fopen(argv[i], "rb"); + if(f == NULL){ + fprintf(stderr, "%s: %s: fopen fail\n", argv[0], argv[i]); + free(str); + return 1; + } + fread(str, 1, s.st_size, f); + struct sn_generic** t = sn_parse(str, s.st_size); + if(t != NULL){ + int j; + for(j = 0; t[j] != NULL; j++){ + sn_generic_free(t[j]); + } + free(t); + } + free(str); + }else{ + fprintf(stderr, "%s: %s: stat fail\n", argv[0], argv[i]); + return 1; + } } } #ifdef HAS_REPL_SUPPORT if(!loaded){ printf("Welcome to Serenade LISP %s\n", SERENADE_VERSION); printf("Support: %s\n", SUPPORT); + printf("Stack size: %d\n", STACK_SIZE); } return 0; #else diff --git a/Serenade/parser.c b/Serenade/parser.c index f96c9ec..263b8a9 100644 --- a/Serenade/parser.c +++ b/Serenade/parser.c @@ -29,3 +29,140 @@ /* --- END LICENSE --- */ #include "parser.h" +#include "util.h" +#include "../config.h" + +#include +#include +#include +#include + +/* +struct sn_generic { + int type; + double number; + char* string; + unsigned long long string_length; + void* ptr; + struct sn_tree* tree; +}; +*/ + +struct sn_generic* sn_expr_parse(char* data, unsigned long long size){ + int i; + int br = 0; + bool dq = false; + int* br_stack = malloc(sizeof(*br_stack) * STACK_SIZE); + char** op_stack = malloc(sizeof(*op_stack) * STACK_SIZE); + struct sn_generic** gn_stack = malloc(sizeof(*gn_stack) * STACK_SIZE); + for(i = 0; i < STACK_SIZE; i++){ + br_stack[i] = 0; + op_stack[i] = NULL; + gn_stack[i] = NULL; + } + for(i = 0; i < size; i++){ + char c = data[i]; + if(c == '"'){ + dq = !dq; + }else if(dq){ + }else if(c == '('){ + br++; + gn_stack[br - 1] = malloc(sizeof(*gn_stack)); + gn_stack[br - 1]->type = SN_TYPE_TREE; + gn_stack[br - 1]->tree = malloc(sizeof(*gn_stack[br - 1]->tree)); + gn_stack[br - 1]->tree->op = malloc(sizeof(*gn_stack[br - 1]->tree->op)); + gn_stack[br - 1]->tree->op->type = SN_TYPE_FUNCTION; + gn_stack[br - 1]->tree->args = malloc(sizeof(*gn_stack[br - 1]->tree->args)); + gn_stack[br - 1]->tree->args[0] = NULL; + op_stack[br - 1] = malloc(1); + op_stack[br - 1][0] = 0; + }else if(c == ')'){ + if(br == 1){ + gn_stack[br - 1]->tree->op->name = sn_strdup(op_stack[br - 1]); + } + br_stack[br - 1] = 0; + if(br_stack[br - 2] > 0){ + int j; + struct sn_generic** old_args = gn_stack[br - 2]->tree->args; + for(j = 0; old_args[j] != NULL; j++); + gn_stack[br - 2]->tree->args = malloc(sizeof(*gn_stack[br - 2]->tree->args) * (j + 2)); + for(j = 0; old_args[j] != NULL; j++){ + gn_stack[br - 2]->tree->args[j] = old_args[j]; + } + gn_stack[br - 2]->tree->args[j] = gn_stack[br - 1]; + gn_stack[br - 2]->tree->args[j + 1] = NULL; + free(old_args); + } + br--; + }else if(br > 0){ + if(c == ' '){ + br_stack[br - 1]++; + }else if(br_stack[br - 1] == 0){ + char cbuf[2]; + cbuf[0] = c; + cbuf[1] = 0; + char* tmp = op_stack[br - 1]; + op_stack[br - 1] = sn_strcat(tmp, cbuf); + free(tmp); + } + } + } + struct sn_generic* gen = gn_stack[0]; + free(gn_stack); + free(br_stack); + free(op_stack); + return gen; +} + +struct sn_generic** sn_parse(char* data, unsigned long long size){ + int br = 0; + int i; + int start = 0; + bool dq = false; + for(i = 0; i < size; i++){ + char c = data[i]; + if(c == '"'){ + dq = !dq; + }else if(dq){ + }else if(c == '('){ + if(br == 0){ + start = i; + } + br++; + }else if(c == ')'){ + br--; + if(br == 0){ + char* d = malloc(i - start + 1); + memcpy(d, data + start, i - start + 1); + struct sn_generic* gen = sn_expr_parse(d, i - start + 1); + if(gen != NULL){ + sn_generic_free(gen); + } + free(d); + } + } + } + return NULL; +} + +void sn_generic_free(struct sn_generic* g){ + if(g->type == SN_TYPE_STRING){ + free(g->string); + }else if(g->type == SN_TYPE_TREE){ + sn_tree_free(g->tree); + } + free(g); +} + +void sn_tree_free(struct sn_tree* t){ + if(t->op != NULL){ + sn_generic_free(t->op); + } + if(t->args != NULL){ + int i; + for(i = 0; t->args[i] != NULL; i++){ + sn_generic_free(t->args[i]); + } + free(t->args); + } +} diff --git a/Serenade/parser.h b/Serenade/parser.h index eb14ffb..08b21f1 100644 --- a/Serenade/parser.h +++ b/Serenade/parser.h @@ -35,6 +35,8 @@ enum types { SN_TYPE_DOUBLE, SN_TYPE_STRING, SN_TYPE_TREE, + SN_TYPE_PTR, + SN_TYPE_FUNCTION, SN_TYPE_VOID }; @@ -42,12 +44,19 @@ struct sn_generic { int type; double number; char* string; + unsigned long long string_length; + void* ptr; + char* name; struct sn_tree* tree; }; struct sn_tree { - struct sn_generic* type; + struct sn_generic* op; struct sn_generic** args; }; +struct sn_generic** sn_parse(char* data, unsigned long long size); +void sn_generic_free(struct sn_generic* g); +void sn_tree_free(struct sn_tree* t); + #endif diff --git a/Serenade/util.c b/Serenade/util.c new file mode 100644 index 0000000..cb87438 --- /dev/null +++ b/Serenade/util.c @@ -0,0 +1,23 @@ +/* $Id$ */ +/* --- START LICENSE --- */ +/* --- END LICENSE --- */ + +#include "util.h" + +#include +#include + +char* sn_strcat(const char* str1, const char* str2){ + char* str = malloc(strlen(str1) + strlen(str2) + 1); + memcpy(str, str1, strlen(str1)); + memcpy(str + strlen(str1), str2, strlen(str2)); + str[strlen(str1) + strlen(str2)] = 0; + return str; +} + +char* sn_strdup(const char* str1){ + char* str = malloc(strlen(str1) + 1); + memcpy(str, str1, strlen(str1)); + str[strlen(str1)] = 0; + return str; +} diff --git a/Serenade/util.h b/Serenade/util.h new file mode 100644 index 0000000..c27e43c --- /dev/null +++ b/Serenade/util.h @@ -0,0 +1,11 @@ +/* $Id$ */ +/* --- START LICENSE --- */ +/* --- END LICENSE --- */ + +#ifndef __SERENADE_UTIL_H__ +#define __SERENADE_UTIL_H__ + +char* sn_strcat(const char* str1, const char* str2); +char* sn_strdup(const char* str1); + +#endif diff --git a/Tool/configgen.c b/Tool/configgen.c index 2a6f6c6..87082c4 100644 --- a/Tool/configgen.c +++ b/Tool/configgen.c @@ -89,6 +89,11 @@ int main(int argc, char** argv){ nl = true; } } + int stack_size = 1024; + fprintf(stderr, "[recommended: 1024] Stack size? "); + fflush(stderr); + scanf("%d", &stack_size); + fprintf(out, "#define STACK_SIZE %d\n", stack_size); fprintf(out, "#define SUPPORT \""); for(n = 0; asks[n * 4] != NULL; n++){ if(n > 0) fprintf(out, " "); -- 2.43.0