cc -std=c99 -Wall hello.c -o hello
Last active
November 14, 2015 03:36
-
-
Save mdaisuke/d01646746f3a1485d9cf to your computer and use it in GitHub Desktop.
buildyourownlisp http://www.buildyourownlisp.com/contents
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[submodule "mpc"] | |
path = mpc | |
url = https://github.com/orangeduck/mpc |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// cc -std=c99 -Wall error_handling.c ./mpc/mpc.c -ledit -lm -o error_handling | |
// | |
#include "./mpc/mpc.h" | |
#include <editline/readline.h> | |
enum { LERR_DIV_ZERO, LERR_BAD_OP, LERR_BAD_NUM }; | |
enum { LVAL_NUM, LVAL_ERR }; | |
typedef struct { | |
int type; | |
long num; | |
int err; | |
} lval; | |
lval lval_num(long x) { | |
lval v; | |
v.type = LVAL_NUM; | |
v.num = x; | |
return v; | |
} | |
lval lval_err(int x) { | |
lval v; | |
v.type = LVAL_ERR; | |
v.err = x; | |
return v; | |
} | |
void lval_print(lval v) { | |
switch (v.type) { | |
case LVAL_NUM: printf("%li", v.num); break; | |
case LVAL_ERR: | |
if (v.err == LERR_DIV_ZERO) { printf("Error: Division By Zero!"); } | |
if (v.err == LERR_BAD_OP) { printf("Error: Invalid Operator!"); } | |
if (v.err == LERR_BAD_NUM) { printf("Error: Invalid Number!"); } | |
break; | |
} | |
} | |
void lval_println(lval v) { lval_print(v); putchar('\n'); } | |
lval eval_op(lval x, char* op, lval y) { | |
if (x.type == LVAL_ERR) { return x; } | |
if (y.type == LVAL_ERR) { return y; } | |
if (strcmp(op, "+") == 0) { return lval_num(x.num + y.num); } | |
if (strcmp(op, "-") == 0) { return lval_num(x.num - y.num); } | |
if (strcmp(op, "*") == 0) { return lval_num(x.num * y.num); } | |
if (strcmp(op, "/") == 0) { | |
return y.num == 0 ? lval_err(LERR_DIV_ZERO) : lval_num(x.num / y.num); | |
} | |
return lval_err(LERR_BAD_OP); | |
} | |
lval eval(mpc_ast_t* t) { | |
if (strstr(t->tag, "number")) { | |
errno = 0; | |
long x = strtol(t->contents, NULL, 10); | |
return errno != ERANGE ? lval_num(x) : lval_err(LERR_BAD_NUM); | |
} | |
char* op = t->children[1]->contents; | |
lval x = eval(t->children[2]); | |
int i = 3; | |
while (strstr(t->children[i]->tag, "expr")) { | |
x = eval_op(x, op, eval(t->children[i])); | |
i++; | |
} | |
return x; | |
} | |
int main(int argc, char** argv) { | |
mpc_parser_t* Number = mpc_new("number"); | |
mpc_parser_t* Operator = mpc_new("operator"); | |
mpc_parser_t* Expr = mpc_new("expr"); | |
mpc_parser_t* Lispy = mpc_new("lispy"); | |
mpca_lang(MPCA_LANG_DEFAULT, | |
" \ | |
number : /-?[0-9]+/ ; \ | |
operator : '+' | '-' | '*' | '/' ; \ | |
expr : <number> | '(' <operator> <expr>+ ')' ; \ | |
lispy : /^/ <operator> <expr>+ /$/ ; \ | |
", | |
Number, Operator, Expr, Lispy); | |
puts("Lispy Version 0.0.0.0.4"); | |
puts("Press Ctrl+c to Exit\n"); | |
while (1) { | |
char* input = readline("lispy> "); | |
add_history(input); | |
mpc_result_t r; | |
if (mpc_parse("<stdin>", input, Lispy, &r)) { | |
lval result = eval(r.output); | |
lval_println(result); | |
mpc_ast_delete(r.output); | |
} else { | |
mpc_err_print(r.error); | |
mpc_err_delete(r.error); | |
} | |
free(input); | |
} | |
mpc_cleanup(4, Number, Operator, Expr, Lispy); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// cc -std=c99 -Wall parsing.c ./mpc/mpc.c -ledit -lm -o parsing | |
// | |
#include "./mpc/mpc.h" | |
#include <editline/readline.h> | |
long eval_op(long x, char* op, long y) { | |
if (strcmp(op, "+") == 0) { return x + y; } | |
if (strcmp(op, "-") == 0) { return x - y; } | |
if (strcmp(op, "*") == 0) { return x * y; } | |
if (strcmp(op, "/") == 0) { return x / y; } | |
return 0; | |
} | |
long eval(mpc_ast_t* t) { | |
if (strstr(t->tag, "number")) { return atoi(t->contents); } | |
char* op = t->children[1]->contents; | |
long x = eval(t->children[2]); | |
int i = 3; | |
while (strstr(t->children[i]->tag, "expr")) { | |
x = eval_op(x, op, eval(t->children[i])); | |
i++; | |
} | |
return x; | |
} | |
int main(int argc, char** argv) { | |
mpc_parser_t* Number = mpc_new("number"); | |
mpc_parser_t* Operator = mpc_new("operator"); | |
mpc_parser_t* Expr = mpc_new("expr"); | |
mpc_parser_t* Lispy = mpc_new("lispy"); | |
mpca_lang(MPCA_LANG_DEFAULT, | |
" \ | |
number : /-?[0-9]+/ ; \ | |
operator : '+' | '-' | '*' | '/' ; \ | |
expr : <number> | '(' <operator> <expr>+ ')' ; \ | |
lispy : /^/ <operator> <expr>+ /$/ ; \ | |
", | |
Number, Operator, Expr, Lispy); | |
puts("Lispy Version 0.0.0.0.3"); | |
puts("Press Ctrl+c to Exit\n"); | |
while (1) { | |
char* input = readline("lispy> "); | |
add_history(input); | |
mpc_result_t r; | |
if (mpc_parse("<stdin>", input, Lispy, &r)) { | |
long result = eval(r.output); | |
printf("%li\n", result); | |
mpc_ast_delete(r.output); | |
} else { | |
mpc_err_print(r.error); | |
mpc_err_delete(r.error); | |
} | |
free(input); | |
} | |
mpc_cleanup(4, Number, Operator, Expr, Lispy); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
int main() { | |
printf("hello world :)\n"); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// cc -std=c99 -Wall parsing.c ./mpc/mpc.c -ledit -lm -o parsing | |
// | |
#include "./mpc/mpc.h" | |
#include <editline/readline.h> | |
int main(int argc, char** argv) { | |
mpc_parser_t* Number = mpc_new("number"); | |
mpc_parser_t* Operator = mpc_new("operator"); | |
mpc_parser_t* Expr = mpc_new("expr"); | |
mpc_parser_t* Lispy = mpc_new("lispy"); | |
mpca_lang(MPCA_LANG_DEFAULT, | |
" \ | |
number : /-?[0-9]+/ ; \ | |
operator : '+' | '-' | '*' | '/' ; \ | |
expr : <number> | '(' <operator> <expr>+ ')' ; \ | |
lispy : /^/ <operator> <expr>+ /$/ ; \ | |
", | |
Number, Operator, Expr, Lispy); | |
puts("Lispy Version 0.0.0.0.2"); | |
puts("Press Ctrl+c to Exit\n"); | |
while (1) { | |
char* input = readline("lispy> "); | |
add_history(input); | |
mpc_result_t r; | |
if (mpc_parse("<stdin>", input, Lispy, &r)) { | |
mpc_ast_print(r.output); | |
mpc_ast_delete(r.output); | |
} else { | |
mpc_err_print(r.error); | |
mpc_err_delete(r.error); | |
} | |
free(input); | |
} | |
mpc_cleanup(4, Number, Operator, Expr, Lispy); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// $ cc -std=c99 -Wall -lreadline prompt.c -o prompt | |
// | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <editline/readline.h> | |
int main(int argc, char** argv) { | |
puts("Lispy Version 0.0.0.0.1"); | |
puts("Press Ctrl+c to Exit\n"); | |
while (1) { | |
char* input = readline("lispy> "); | |
add_history(input); | |
printf("No you're a %s\n", input); | |
free(input); | |
} | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "./mpc/mpc.h" | |
#include <editline/readline.h> | |
enum { LVAL_ERR, LVAL_NUM, LVAL_SYM, LVAL_SEXPR, LVAL_QEXPR }; | |
typedef struct lval { | |
int type; | |
long num; | |
char* err; | |
char* sym; | |
int count; | |
struct lval** cell; | |
} lval; | |
lval* lval_num(long x) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_NUM; | |
v->num = x; | |
return v; | |
} | |
lval* lval_err(char* m) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_ERR; | |
v->err = malloc(strlen(m) + 1); | |
strcpy(v->err, m); | |
return v; | |
} | |
lval* lval_sym(char* s) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_SYM; | |
v->sym = malloc(strlen(s) + 1); | |
strcpy(v->sym, s); | |
return v; | |
} | |
lval* lval_sexpr(void) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_SEXPR; | |
v->count = 0; | |
v->cell = NULL; | |
return v; | |
} | |
lval* lval_qexpr(void) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_QEXPR; | |
v->count = 0; | |
v->cell = NULL; | |
return v; | |
} | |
void lval_del(lval* v) { | |
switch (v->type) { | |
case LVAL_NUM: break; | |
case LVAL_ERR: free(v->err); break; | |
case LVAL_SYM: free(v->sym); break; | |
case LVAL_QEXPR: | |
case LVAL_SEXPR: | |
for (int i = 0; i < v->count; i++) { | |
lval_del(v->cell[i]); | |
} | |
free(v->cell); | |
break; | |
} | |
free(v); | |
} | |
lval* lval_add(lval* v, lval* x) { | |
v->count++; | |
v->cell = realloc(v->cell, sizeof(lval*) * v->count); | |
v->cell[v->count-1] = x; | |
return v; | |
} | |
lval* lval_pop(lval* v, int i) { | |
lval* x = v->cell[i]; | |
memmove(&v->cell[i], &v->cell[i+1], sizeof(lval*) * (v->count-i-1)); | |
v->count--; | |
v->cell = realloc(v->cell, sizeof(lval*) * v->count); | |
return x; | |
} | |
lval* lval_take(lval* v, int i) { | |
lval* x = lval_pop(v, i); | |
lval_del(v); | |
return x; | |
} | |
void lval_print(lval* v); | |
void lval_expr_print(lval* v, char open, char close) { | |
putchar(open); | |
for (int i = 0; i < v->count; i++) { | |
lval_print(v->cell[i]); | |
if (i != (v->count-1)) { | |
putchar(' '); | |
} | |
} | |
putchar(close); | |
} | |
void lval_print(lval* v) { | |
switch (v->type) { | |
case LVAL_NUM: printf("%li", v->num); break; | |
case LVAL_ERR: printf("Error: %s", v->err); break; | |
case LVAL_SYM: printf("%s", v->sym); break; | |
case LVAL_SEXPR: lval_expr_print(v, '(', ')'); break; | |
case LVAL_QEXPR: lval_expr_print(v, '{', '}'); break; | |
} | |
} | |
void lval_println(lval* v) { lval_print(v); putchar('\n'); } | |
lval* buildin_op(lval* a, char* op) { | |
for (int i = 0; i < a->count; i++) { | |
if (a->cell[i]->type != LVAL_NUM) { | |
lval_del(a); | |
return lval_err("Cannot operate on non-number!"); | |
} | |
} | |
lval* x = lval_pop(a, 0); | |
if ((strcmp(op, "-") == 0) && a->count == 0) { x->num = -x->num; } | |
while (a->count > 0) { | |
lval* y = lval_pop(a, 0); | |
if (strcmp(op, "+") == 0) { x->num += y->num; } | |
if (strcmp(op, "-") == 0) { x->num -= y->num; } | |
if (strcmp(op, "*") == 0) { x->num *= y->num; } | |
if (strcmp(op, "/") == 0) { | |
if (y->num == 0) { | |
lval_del(x); lval_del(y); | |
x = lval_err("Division By Zero."); | |
break; | |
} | |
x->num /= y->num; | |
} | |
lval_del(y); | |
} | |
lval_del(a); | |
return x; | |
} | |
lval* lval_eval(lval* v); | |
lval* lval_eval_sexpr(lval* v) { | |
for (int i = 0; i < v->count; i++) { | |
v->cell[i] = lval_eval(v->cell[i]); | |
} | |
for (int i = 0; i < v->count; i++) { | |
if (v->cell[i]->type == LVAL_ERR) { return lval_take(v, i); } | |
} | |
if (v->count == 0) { return v; } | |
if (v->count == 1) { return lval_take(v, 0); } | |
lval* f = lval_pop(v, 0); | |
if (f->type != LVAL_SYM) { | |
lval_del(f); lval_del(v); | |
return lval_err("S-expression Does not start with symbol."); | |
} | |
lval* result = buildin_op(v, f->sym); | |
lval_del(f); | |
return result; | |
} | |
lval* lval_eval(lval* v) { | |
if (v->type == LVAL_SEXPR) { return lval_eval_sexpr(v); } | |
return v; | |
} | |
lval* lval_read_num(mpc_ast_t* t) { | |
errno = 0; | |
long x = strtol(t->contents, NULL, 10); | |
return errno != ERANGE ? lval_num(x) : lval_err("invalid number"); | |
} | |
lval* lval_read(mpc_ast_t* t) { | |
if (strstr(t->tag, "number")) { return lval_read_num(t); } | |
if (strstr(t->tag, "symbol")) { return lval_sym(t->contents); } | |
lval* x = NULL; | |
if (strcmp(t->tag, ">") == 0) { x = lval_sexpr(); } | |
if (strcmp(t->tag, "sexpr")) { x = lval_sexpr(); } | |
if (strstr(t->tag, "qexpr")) { x = lval_qexpr(); } | |
for (int i = 0; i < t->children_num; i++) { | |
if (strcmp(t->children[i]->contents, "(") == 0) { continue; } | |
if (strcmp(t->children[i]->contents, ")") == 0) { continue; } | |
if (strcmp(t->children[i]->contents, "}") == 0) { continue; } | |
if (strcmp(t->children[i]->contents, "{") == 0) { continue; } | |
if (strcmp(t->children[i]->tag, "regex") == 0) { continue; } | |
x = lval_add(x, lval_read(t->children[i])); | |
} | |
return x; | |
} | |
int main(int argc, char** argv) { | |
mpc_parser_t* Number = mpc_new("number"); | |
mpc_parser_t* Symbol = mpc_new("symbol"); | |
mpc_parser_t* Sexpr = mpc_new("sexpr"); | |
mpc_parser_t* Qexpr = mpc_new("qexpr"); | |
mpc_parser_t* Expr = mpc_new("expr"); | |
mpc_parser_t* Lispy = mpc_new("lispy"); | |
mpca_lang(MPCA_LANG_DEFAULT, | |
" \ | |
number : /-?[0-9]+/ ; \ | |
symbol : \"list\" | \"head\" | \"tail\" | \"join\" | \"eval\" | '+' | '-' | '*' | '/' ; \ | |
sexpr : '(' <expr>* ')' ; \ | |
qexpr : '{' <expr>* '}' ; \ | |
expr : <number> | <symbol> | <sexpr> | <qexpr> ; \ | |
lispy : /^/ <expr>* /$/ ; \ | |
", | |
Number, Symbol, Sexpr, Qexpr, Expr, Lispy); | |
puts("Lispy Version 0.0.0.0.5"); | |
puts("Press Ctrl+c to Exit\n"); | |
while (1) { | |
char* input = readline("lispy> "); | |
add_history(input); | |
mpc_result_t r; | |
if (mpc_parse("<stdin>", input, Lispy, &r)) { | |
lval* x = lval_eval(lval_read(r.output)); | |
lval_println(x); | |
lval_del(x); | |
mpc_ast_delete(r.output); | |
} else { | |
mpc_err_print(r.error); | |
mpc_err_delete(r.error); | |
} | |
free(input); | |
} | |
mpc_cleanup(6, Number, Symbol, Sexpr, Qexpr, Expr, Lispy); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "./mpc/mpc.h" | |
#include <editline/readline.h> | |
enum { LVAL_ERR, LVAL_NUM, LVAL_SYM, LVAL_SEXPR }; | |
typedef struct lval { | |
int type; | |
long num; | |
char* err; | |
char* sym; | |
int count; | |
struct lval** cell; | |
} lval; | |
lval* lval_num(long x) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_NUM; | |
v->num = x; | |
return v; | |
} | |
lval* lval_err(char* m) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_ERR; | |
v->err = malloc(strlen(m) + 1); | |
strcpy(v->err, m); | |
return v; | |
} | |
lval* lval_sym(char* s) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_SYM; | |
v->sym = malloc(strlen(s) + 1); | |
strcpy(v->sym, s); | |
return v; | |
} | |
lval* lval_sexpr(void) { | |
lval* v = malloc(sizeof(lval)); | |
v->type = LVAL_SEXPR; | |
v->count = 0; | |
v->cell = NULL; | |
return v; | |
} | |
void lval_del(lval* v) { | |
switch (v->type) { | |
case LVAL_NUM: break; | |
case LVAL_ERR: free(v->err); break; | |
case LVAL_SYM: free(v->sym); break; | |
case LVAL_SEXPR: | |
for (int i = 0; i < v->count; i++) { | |
lval_del(v->cell[i]); | |
} | |
free(v->cell); | |
break; | |
} | |
free(v); | |
} | |
lval* lval_add(lval* v, lval* x) { | |
v->count++; | |
v->cell = realloc(v->cell, sizeof(lval*) * v->count); | |
v->cell[v->count-1] = x; | |
return v; | |
} | |
lval* lval_pop(lval* v, int i) { | |
lval* x = v->cell[i]; | |
memmove(&v->cell[i], &v->cell[i+1], sizeof(lval*) * (v->count-i-1)); | |
v->count--; | |
v->cell = realloc(v->cell, sizeof(lval*) * v->count); | |
return x; | |
} | |
lval* lval_take(lval* v, int i) { | |
lval* x = lval_pop(v, i); | |
lval_del(v); | |
return x; | |
} | |
void lval_print(lval* v); | |
void lval_expr_print(lval* v, char open, char close) { | |
putchar(open); | |
for (int i = 0; i < v->count; i++) { | |
lval_print(v->cell[i]); | |
if (i != (v->count-1)) { | |
putchar(' '); | |
} | |
} | |
putchar(close); | |
} | |
void lval_print(lval* v) { | |
switch (v->type) { | |
case LVAL_NUM: printf("%li", v->num); break; | |
case LVAL_ERR: printf("Error: %s", v->err); break; | |
case LVAL_SYM: printf("%s", v->sym); break; | |
case LVAL_SEXPR: lval_expr_print(v, '(', ')'); break; | |
} | |
} | |
void lval_println(lval* v) { lval_print(v); putchar('\n'); } | |
lval* buildin_op(lval* a, char* op) { | |
for (int i = 0; i < a->count; i++) { | |
if (a->cell[i]->type != LVAL_NUM) { | |
lval_del(a); | |
return lval_err("Cannot operate on non-number!"); | |
} | |
} | |
lval* x = lval_pop(a, 0); | |
if ((strcmp(op, "-") == 0) && a->count == 0) { x->num = -x->num; } | |
while (a->count > 0) { | |
lval* y = lval_pop(a, 0); | |
if (strcmp(op, "+") == 0) { x->num += y->num; } | |
if (strcmp(op, "-") == 0) { x->num -= y->num; } | |
if (strcmp(op, "*") == 0) { x->num *= y->num; } | |
if (strcmp(op, "/") == 0) { | |
if (y->num == 0) { | |
lval_del(x); lval_del(y); | |
x = lval_err("Division By Zero."); | |
break; | |
} | |
x->num /= y->num; | |
} | |
lval_del(y); | |
} | |
lval_del(a); | |
return x; | |
} | |
lval* lval_eval(lval* v); | |
lval* lval_eval_sexpr(lval* v) { | |
for (int i = 0; i < v->count; i++) { | |
v->cell[i] = lval_eval(v->cell[i]); | |
} | |
for (int i = 0; i < v->count; i++) { | |
if (v->cell[i]->type == LVAL_ERR) { return lval_take(v, i); } | |
} | |
if (v->count == 0) { return v; } | |
if (v->count == 1) { return lval_take(v, 0); } | |
lval* f = lval_pop(v, 0); | |
if (f->type != LVAL_SYM) { | |
lval_del(f); lval_del(v); | |
return lval_err("S-expression Does not start with symbol."); | |
} | |
lval* result = buildin_op(v, f->sym); | |
lval_del(f); | |
return result; | |
} | |
lval* lval_eval(lval* v) { | |
if (v->type == LVAL_SEXPR) { return lval_eval_sexpr(v); } | |
return v; | |
} | |
lval* lval_read_num(mpc_ast_t* t) { | |
errno = 0; | |
long x = strtol(t->contents, NULL, 10); | |
return errno != ERANGE ? lval_num(x) : lval_err("invalid number"); | |
} | |
lval* lval_read(mpc_ast_t* t) { | |
if (strstr(t->tag, "number")) { return lval_read_num(t); } | |
if (strstr(t->tag, "symbol")) { return lval_sym(t->contents); } | |
lval* x = NULL; | |
if (strcmp(t->tag, ">") == 0) { x = lval_sexpr(); } | |
if (strcmp(t->tag, "sexpr")) { x = lval_sexpr(); } | |
for (int i = 0; i < t->children_num; i++) { | |
if (strcmp(t->children[i]->contents, "(") == 0) { continue; } | |
if (strcmp(t->children[i]->contents, ")") == 0) { continue; } | |
if (strcmp(t->children[i]->contents, "}") == 0) { continue; } | |
if (strcmp(t->children[i]->contents, "{") == 0) { continue; } | |
if (strcmp(t->children[i]->tag, "regex") == 0) { continue; } | |
x = lval_add(x, lval_read(t->children[i])); | |
} | |
return x; | |
} | |
int main(int argc, char** argv) { | |
mpc_parser_t* Number = mpc_new("number"); | |
mpc_parser_t* Symbol = mpc_new("symbol"); | |
mpc_parser_t* Sexpr = mpc_new("sexpr"); | |
mpc_parser_t* Expr = mpc_new("expr"); | |
mpc_parser_t* Lispy = mpc_new("lispy"); | |
mpca_lang(MPCA_LANG_DEFAULT, | |
" \ | |
number : /-?[0-9]+/ ; \ | |
symbol : '+' | '-' | '*' | '/' ; \ | |
sexpr : '(' <expr>* ')' ; \ | |
expr : <number> | <symbol> | <sexpr> ; \ | |
lispy : /^/ <expr>* /$/ ; \ | |
", | |
Number, Symbol, Sexpr, Expr, Lispy); | |
puts("Lispy Version 0.0.0.0.5"); | |
puts("Press Ctrl+c to Exit\n"); | |
while (1) { | |
char* input = readline("lispy> "); | |
add_history(input); | |
mpc_result_t r; | |
if (mpc_parse("<stdin>", input, Lispy, &r)) { | |
lval* x = lval_eval(lval_read(r.output)); | |
lval_println(x); | |
lval_del(x); | |
mpc_ast_delete(r.output); | |
} else { | |
mpc_err_print(r.error); | |
mpc_err_delete(r.error); | |
} | |
free(input); | |
} | |
mpc_cleanup(5, Number, Symbol, Sexpr, Expr, Lispy); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment