shuntyard.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdbool.h>
  5. #include "stack.h"
  6. char isop(char c);
  7. int op_isleft(char c); // associativity (left/right)
  8. int op_prec(char c); // precendence
  9. int main(int argc, char *argv[])
  10. {
  11. size_t len = 0;
  12. for (int i = 1; i < argc; ++i) {
  13. if (argv[i])
  14. len += strlen(argv[i]);
  15. }
  16. char *input = calloc(1, len+1);
  17. for (int i = 1; i < argc; ++i) {
  18. strcat(input, argv[i]);
  19. }
  20. puts(input);
  21. struct stack *ops = stack_new();
  22. struct stack *out = stack_new();
  23. int tok;
  24. for (size_t i = 0; i < len+1; ++i) {
  25. tok = input[i];
  26. if (isop(tok)) {
  27. while (!stack_isempty(ops)) {
  28. int assoc = op_isleft(tok);
  29. int prec = op_prec(tok);
  30. if ((assoc && prec <= op_prec(stack_peek(ops))) ||
  31. (!assoc && prec < op_prec(stack_peek(ops)))) {
  32. stack_push(out, stack_pop(ops));
  33. } else {
  34. break;
  35. }
  36. }
  37. stack_push(ops, tok);
  38. } else if (tok == '(') {
  39. stack_push(ops, tok);
  40. } else if (tok == ')') {
  41. while (stack_peek(ops) != '(')
  42. stack_push(out, stack_pop(ops));
  43. stack_pop(ops);
  44. } else {
  45. stack_push(out, tok);
  46. }
  47. }
  48. while (!stack_isempty(ops))
  49. stack_push(out, stack_pop(ops));
  50. for (int i = 0; i <= out->sp; ++i)
  51. putchar(out->s[i]);
  52. puts("");
  53. return 0;
  54. }
  55. char isop(char c)
  56. {
  57. char ret = 0;
  58. switch (c) {
  59. case '*':
  60. case '/':
  61. case '-':
  62. case '+':
  63. case '^':
  64. ret = c;
  65. break;
  66. }
  67. return ret;
  68. }
  69. int op_isleft(char op)
  70. {
  71. int ret = 0;
  72. switch (op) {
  73. case '*':
  74. case '/':
  75. case '+':
  76. case '-':
  77. ret = 1;
  78. break;
  79. case '^':
  80. break;
  81. }
  82. return ret;
  83. }
  84. int op_prec(char op)
  85. {
  86. int ret = 0;
  87. switch (op) {
  88. case '^':
  89. ret = 4;
  90. break;
  91. case '*':
  92. case '/':
  93. ret = 3;
  94. break;
  95. case '+':
  96. case '-':
  97. ret = 2;
  98. break;
  99. }
  100. return ret;
  101. }