参考

{% collapse title=”evaluation.c” %}

  1. #include "mpc.h"
  2. #ifdef _WIN32
  3. static char buffer[2048];
  4. char* readline(char* prompt) {
  5. fputs(prompt, stdout);
  6. fgets(buffer, 2048, stdin);
  7. char* cpy = malloc(strlen(buffer)+1);
  8. strcpy(cpy, buffer);
  9. cpy[strlen(cpy)-1] = '\0';
  10. return cpy;
  11. }
  12. void add_history(char* unused) {}
  13. #else
  14. #include <editline/readline.h>
  15. #include <editline/history.h>
  16. #endif
  17. /* Use operator string to see which operation to perform */
  18. long eval_op(long x, char* op, long y) {
  19. if (strcmp(op, "+") == 0) { return x + y; }
  20. if (strcmp(op, "-") == 0) { return x - y; }
  21. if (strcmp(op, "*") == 0) { return x * y; }
  22. if (strcmp(op, "/") == 0) { return x / y; }
  23. return 0;
  24. }
  25. long eval(mpc_ast_t* t) {
  26. /* If tagged as number return it directly. */
  27. if (strstr(t->tag, "number")) {
  28. return atoi(t->contents);
  29. }
  30. /* The operator is always second child. */
  31. char* op = t->children[1]->contents;
  32. /* We store the third child in `x` */
  33. long x = eval(t->children[2]);
  34. /* Iterate the remaining children and combining. */
  35. int i = 3;
  36. while (strstr(t->children[i]->tag, "expr")) {
  37. x = eval_op(x, op, eval(t->children[i]));
  38. i++;
  39. }
  40. return x;
  41. }
  42. int main(int argc, char** argv) {
  43. mpc_parser_t* Number = mpc_new("number");
  44. mpc_parser_t* Operator = mpc_new("operator");
  45. mpc_parser_t* Expr = mpc_new("expr");
  46. mpc_parser_t* Lispy = mpc_new("lispy");
  47. mpca_lang(MPCA_LANG_DEFAULT,
  48. " \
  49. number : /-?[0-9]+/ ; \
  50. operator : '+' | '-' | '*' | '/' ; \
  51. expr : <number> | '(' <operator> <expr>+ ')' ; \
  52. lispy : /^/ <operator> <expr>+ /$/ ; \
  53. ",
  54. Number, Operator, Expr, Lispy);
  55. puts("Lispy Version 0.0.0.0.3");
  56. puts("Press Ctrl+c to Exit\n");
  57. while (1) {
  58. char* input = readline("lispy> ");
  59. add_history(input);
  60. mpc_result_t r;
  61. if (mpc_parse("<stdin>", input, Lispy, &r)) {
  62. long result = eval(r.output);
  63. printf("%li\n", result);
  64. mpc_ast_delete(r.output);
  65. } else {
  66. mpc_err_print(r.error);
  67. mpc_err_delete(r.error);
  68. }
  69. free(input);
  70. }
  71. mpc_cleanup(4, Number, Operator, Expr, Lispy);
  72. return 0;
  73. }

{% endcollapse %}