#include #include #include "../mpc/mpc.h" /* If we are on Windows compile these functions */ #ifdef _WIN32 #include #include static char buffer[2048]; /* Fake readline function */ char* readline(char* prompt) { fputs(prompt, stdout); fgets(buffer, 2048, stdin); char* cpy = malloc(strlen(buffer)+1); assert(cpy != NULL) strcpy(cpy, buffer); cpy[strlen(cpy)-1] = '\0'; return cpy; } /* Fake add_history function */ void add_history(char* unused) {} /* Otherwise include the editline headers could use __APPLE__ for detection of OSX */ #else #include #endif long min(long x, long y) { if (x <= y) { return x; } else { return y; } } long max(long x, long y) { if (x >= y) { return x; } else { return y; } } /* Use operator string to see which operation to perform */ 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;} if (strcmp(op, "%") == 0) {return x % y;} if (strcmp(op, "^") == 0) {return pow(x, y);} if (strcmp(op, "min") == 0) {return min(x, y);} if (strcmp(op, "max") == 0) {return max(x, y);} return 0; } long eval(mpc_ast_t* t) { /* If tagged as number return it directly */ if (strstr(t->tag, "number")) { return atoi(t->contents); } /* The operator is always second child */ char* op = t->children[1]->contents; /* We store the third children in x */ long x = eval(t->children[2]); /* Iterate the remaining children and combining */ unsigned 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 const *argv[]) { /* Create some parsers */ 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"); /* Define them with the following language */ mpca_lang(MPCA_LANG_DEFAULT, " \ number : /-?[0-9]+/ ; \ operator : '+' | '-' | '*' | '/' | '%' | '^' | \ \"min\" | \"max\" ; \ expr : | '(' + ')' ; \ lispy : /^/ + /$/ ; \ ", Number, Operator, Expr, Lispy); /* Print version and exit information */ puts("Lispy version 0.0.0.0.3"); puts("Press Ctrl+c to exit\n"); /* In a never ending loop */ while (1) { /* Output our prompt and get input */ char* input = readline("lispy> "); /* Add input to history */ add_history(input); /* Attempt to parse the user input */ mpc_result_t r; if (mpc_parse("", input, Lispy, &r)) { /* On success evaluate the user input */ long result = eval(r.output); printf("%li\n", result); mpc_ast_delete(r.output); } else { /* Otherwise print the error */ mpc_err_print(r.error); mpc_err_delete(r.error); } /* Free retrieved input */ free(input); } /* Undefine and delete our parsers */ mpc_cleanup(4, Number, Operator, Expr, Lispy); return 0; }