Advertisement
Guest User

Untitled

a guest
Oct 15th, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.48 KB | None | 0 0
  1. // (Public domain, created by Ryan Johnson)
  2. // A simple recursive descent calculator in C.
  3. // compile with `cc -lm calc.c`
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <stdarg.h>
  8. #include <inttypes.h>
  9. #include <ctype.h>
  10. #include <math.h>
  11.  
  12. typedef double f64;
  13.  
  14. typedef struct {
  15. int type;
  16. f64 num;
  17. } Token;
  18.  
  19. // The current token.
  20. Token curr;
  21.  
  22. // Exit with an error
  23. void error(const char *fmt, ...) {
  24. va_list list;
  25. va_start(list, fmt);
  26. vfprintf(stderr, fmt, list);
  27. fputc('\n', stderr);
  28. exit(1);
  29. }
  30.  
  31. // Get the next token from stdin
  32. Token next(void) {
  33. for (;;) {
  34. int c = getchar();
  35.  
  36. if (isdigit(c)) {
  37. f64 num = 0;
  38. do num = num * 10 + (c - '0');
  39. while (isdigit(c = getchar()));
  40. ungetc(c, stdin);
  41. curr.type = 'n';
  42. curr.num = num;
  43. return curr;
  44. }
  45.  
  46. if (isspace(c))
  47. continue;
  48.  
  49. switch (c) {
  50. case '+':
  51. case '-':
  52. case '*':
  53. case '/':
  54. case '%':
  55. case '^':
  56. case '(':
  57. case ')':
  58. case EOF:
  59. curr.type = c;
  60. return curr;
  61. }
  62.  
  63. if (isprint(c))
  64. error("Unexpected character: \"%c\"", (char)c);
  65. else
  66. error("Unexpected character: 0x%2X", (unsigned int)c);
  67. }
  68. }
  69.  
  70. // Return the current Token as a string.
  71. const char *str_type(void) {
  72. switch (curr.type) {
  73. case '+':
  74. return "'+'";
  75. case '-':
  76. return "'-'";
  77. case '*':
  78. return "'*'";
  79. case '/':
  80. return "'/'";
  81. case '%':
  82. return "'%'";
  83. case '^':
  84. return "'^'";
  85. case 'n':
  86. return "number";
  87. case EOF:
  88. return "EOF";
  89. }
  90. return NULL;
  91. }
  92.  
  93. // Production Rules:
  94. // Add -> Mul (("+" | "-") Mul)*
  95. // Mul -> Unary (("*" | "/" | "%") Unary)*
  96. // Unary -> ("+" | "-")? Exp
  97. // Exp -> Primary ("^" Exp)?
  98. // Primary -> Number | "(" Add ")"
  99.  
  100. f64 p_add(void);
  101. f64 p_mul(void);
  102. f64 p_unary(void);
  103. f64 p_exp(void);
  104. f64 p_primary(void);
  105.  
  106. f64 p_add(void) {
  107. f64 v = p_mul();
  108. for (;;) {
  109. if (curr.type == '+') {
  110. next();
  111. v += p_mul();
  112. } else if (curr.type == '-') {
  113. next();
  114. v -= p_mul();
  115. } else break;
  116. }
  117. return v;
  118. }
  119.  
  120. f64 p_mul(void) {
  121. f64 v = p_unary();
  122. for (;;) {
  123. if (curr.type == '*') {
  124. next();
  125. v *= p_unary();
  126. } else if (curr.type == '/') {
  127. next();
  128. v /= p_unary();
  129. } else if (curr.type == '%') {
  130. next();
  131. v = fmod(v, p_unary());
  132. } else break;
  133. }
  134. return v;
  135. }
  136.  
  137. f64 p_unary(void) {
  138. if (curr.type == '+') {
  139. next();
  140. return p_exp();
  141. } else if (curr.type == '-') {
  142. next();
  143. return -p_exp();
  144. }
  145. return p_exp();
  146. }
  147.  
  148. f64 p_exp(void) {
  149. f64 v = p_primary();
  150. if (curr.type == '^') {
  151. next();
  152. return pow(v, p_exp());
  153. }
  154. return v;
  155. }
  156.  
  157. f64 p_primary(void) {
  158. f64 v;
  159. switch (curr.type) {
  160. case 'n':
  161. v = curr.num;
  162. next();
  163. return v;
  164. case '(':
  165. next();
  166. v = p_add();
  167. if (curr.type != ')')
  168. error("Expected ')', found %s", str_type());
  169. next();
  170. return v;
  171. }
  172. error("Unexpected %s", str_type());
  173. }
  174.  
  175. int main(void) {
  176. next();
  177. printf("%.2f\n", p_add());
  178. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement