# $Id$
-SERENADE_OBJS = main.o parser.o
+SERENADE_OBJS = main.o parser.o util.o
.PHONY: all clean
.SUFFIXES: .o .c
/* --- END LICENSE --- */
#include "serenade.h"
+#include "parser.h"
#include "../config.h"
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
int main(int argc, char** argv){
int i;
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]);
}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
/* --- END LICENSE --- */
#include "parser.h"
+#include "util.h"
+#include "../config.h"
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+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);
+ }
+}
SN_TYPE_DOUBLE,
SN_TYPE_STRING,
SN_TYPE_TREE,
+ SN_TYPE_PTR,
+ SN_TYPE_FUNCTION,
SN_TYPE_VOID
};
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
--- /dev/null
+/* $Id$ */
+/* --- START LICENSE --- */
+/* --- END LICENSE --- */
+
+#include "util.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+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;
+}
--- /dev/null
+/* $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
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, " ");