calc.c (12545B)
1 #include <assert.h> 2 #include <ctype.h> 3 #include <inttypes.h> 4 #include <stdbool.h> 5 #include <stddef.h> 6 #include <stdint.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #define global_variable static 11 12 struct BufHdr { 13 size_t cap; 14 size_t len; 15 uint8_t buf[]; 16 }; 17 18 void *cmalloc(size_t num_bytes) { 19 void *ptr = malloc(num_bytes); 20 if (!ptr) { 21 fprintf(stderr, "cmalloc failed\n"); 22 exit(1); 23 } 24 return ptr; 25 } 26 27 void *crealloc(void *ptr, size_t num_bytes) { 28 ptr = realloc(ptr, num_bytes); 29 if (!ptr) { 30 fprintf(stderr, "crealloc failed\n"); 31 exit(1); 32 } 33 return ptr; 34 } 35 36 #define buf__hdr(b) ((struct BufHdr *)(void *)((uint8_t *)(b) - offsetof(struct BufHdr, buf))) 37 #define buf_cap(b) ((b) ? buf__hdr(b)->cap : 0) 38 #define buf_len(b) ((b) ? buf__hdr(b)->len : 0) 39 40 #define buf__must_grow(b, n) (buf_len(b) + (n) >= buf_cap(b)) 41 #define buf__maybe_grow(b, n) (buf__must_grow((b), (n)) ? (b) = buf__grow((b), buf_len(b) + (n), sizeof(*(b))) : 0) 42 #define buf_push(b, x) (buf__maybe_grow((b), 1), (b)[buf__hdr(b)->len++] = (x)) 43 44 #define MAX(x, y) ((x) >= (y) ? (x) : (y)) 45 46 void *buf__grow(void *buf, size_t new_length, size_t element_size) { 47 size_t new_cap = MAX(1 + (2 * buf_cap(buf)), new_length); 48 assert(new_cap >= new_length); 49 size_t new_size = offsetof(struct BufHdr, buf) + (new_cap * element_size); 50 struct BufHdr *new_hdr = NULL; 51 if (buf) { 52 new_hdr = crealloc(buf__hdr(buf), new_size); 53 } else { 54 new_hdr = cmalloc(new_size); 55 new_hdr->len = 0; 56 } 57 new_hdr->cap = new_cap; 58 return new_hdr->buf; 59 } 60 61 void buf_test(void) { 62 int *buf = NULL; 63 assert(buf_len(buf) == 0); 64 for (size_t i = 0; i < 1000; ++i) { 65 buf_push(buf, i); 66 } 67 assert(buf_len(buf) == 1000); 68 for (size_t i = 0; i < buf_len(buf); ++i) { 69 //printf("%d, ", buf[i]); 70 } 71 //printf("\n"); 72 } 73 74 #define TOKEN_LIST \ 75 X(TOKEN_NONE, "") \ 76 X(TOKEN_OP_ADD, "+") \ 77 X(TOKEN_OP_SUB, "-") \ 78 X(TOKEN_OP_BIN_OR, "|") \ 79 X(TOKEN_OP_BIN_XOR, "^") \ 80 X(TOKEN_OP_MUL, "*") \ 81 X(TOKEN_OP_DIV, "/") \ 82 X(TOKEN_OP_MOD, "%") \ 83 X(TOKEN_OP_SHIFT_L, "<<") \ 84 X(TOKEN_OP_SHIFT_R, ">>") \ 85 X(TOKEN_OP_BIN_AND, "&") \ 86 X(TOKEN_OP_BIN_NOT, "~") \ 87 X(TOKEN_PAREN_L, "(") \ 88 X(TOKEN_PAREN_R, ")") \ 89 X(TOKEN_INT, "") \ 90 \ 91 X(TOKEN__KIND_COUNT, "") 92 93 enum TokenKind { 94 #define X(kind, glyph) kind, 95 TOKEN_LIST 96 #undef X 97 }; 98 99 char *TokenKindNames[] = { 100 #define X(kind, glyph) [kind] = #kind, 101 TOKEN_LIST 102 #undef X 103 }; 104 105 char *TokenKindGlyphs[] = { 106 #define X(kind, glyph) [kind] = glyph, 107 TOKEN_LIST 108 #undef X 109 }; 110 111 #undef TOKEN_LIST 112 113 char *token_kind_glyph(enum TokenKind k) { 114 assert(k >= TOKEN_NONE && k < TOKEN_INT); 115 assert((size_t)k <= (sizeof TokenKindGlyphs / sizeof TokenKindGlyphs[0])); 116 return TokenKindGlyphs[k]; 117 } 118 119 char *token_kind_name(enum TokenKind k) { 120 assert(k >= TOKEN_NONE && k < TOKEN__KIND_COUNT); 121 assert((size_t)k <= (sizeof TokenKindNames / sizeof TokenKindNames[0])); 122 return TokenKindNames[k]; 123 } 124 125 typedef struct Token { 126 enum TokenKind kind; 127 uint64_t val; 128 } Token; 129 130 global_variable char *g_stream; 131 132 #define ERROR() assert(false && "error") 133 134 void print_token(struct Token token) { 135 bool has_val = token.kind == TOKEN_INT; 136 if (has_val) { 137 printf("T: %s: %" PRIu64 "\n", token_kind_name(token.kind), token.val); 138 } else { 139 printf("T: %s\n", token_kind_name(token.kind)); 140 } 141 } 142 143 char *lex_next_token(Token *out_t) { 144 assert(out_t); 145 146 // TODO: bounds check cursor advances 147 char *cursor = g_stream; 148 149 while (*cursor == ' ') { 150 cursor++; 151 } 152 153 switch(*cursor) { 154 case '0': 155 case '1': 156 case '2': 157 case '3': 158 case '4': 159 case '5': 160 case '6': 161 case '7': 162 case '8': 163 case '9': { 164 uint64_t val = 0; 165 while (isdigit(*cursor)) { 166 val *= 10; 167 val += *cursor++ - '0'; 168 } 169 out_t->kind = TOKEN_INT; 170 out_t->val = val; 171 break; 172 } 173 case '<': 174 cursor++; 175 if (*cursor == '<') { 176 out_t->kind = TOKEN_OP_SHIFT_L; 177 cursor++; 178 } else { 179 ERROR(); 180 } 181 break; 182 case '>': 183 cursor++; 184 if (*cursor == '>') { 185 out_t->kind = TOKEN_OP_SHIFT_R; 186 cursor++; 187 } else { 188 ERROR(); 189 } 190 break; 191 case '+': out_t->kind = TOKEN_OP_ADD; cursor++; break; 192 case '-': out_t->kind = TOKEN_OP_SUB; cursor++; break; 193 case '|': out_t->kind = TOKEN_OP_BIN_OR; cursor++; break; 194 case '^': out_t->kind = TOKEN_OP_BIN_XOR; cursor++; break; 195 case '*': out_t->kind = TOKEN_OP_MUL; cursor++; break; 196 case '/': out_t->kind = TOKEN_OP_DIV; cursor++; break; 197 case '%': out_t->kind = TOKEN_OP_MOD; cursor++; break; 198 case '&': out_t->kind = TOKEN_OP_BIN_AND; cursor++; break; 199 case '~': out_t->kind = TOKEN_OP_BIN_NOT; cursor++; break; 200 case '(': out_t->kind = TOKEN_PAREN_L; cursor++; break; 201 case ')': out_t->kind = TOKEN_PAREN_R; cursor++; break; 202 case '\0': 203 out_t->kind = TOKEN_NONE; 204 break; 205 default: 206 printf("ERROR: '%c' %i\n", *cursor, (int)*cursor); 207 ERROR(); 208 break; 209 } 210 211 return cursor; 212 } 213 214 bool token_is_kind(Token t, enum TokenKind kind) { 215 return t.kind == kind; 216 } 217 218 Token token_peek(void) { 219 Token t = {0}; 220 lex_next_token(&t); 221 return t; 222 } 223 224 Token token_consume(void) { 225 Token t = {0}; 226 g_stream = lex_next_token(&t); 227 return t; 228 } 229 230 bool token_consume_kind(enum TokenKind kind) { 231 Token t = token_peek(); 232 if (token_is_kind(t, kind)) { 233 token_consume(); 234 return true; 235 } else { 236 return false; 237 } 238 } 239 240 Token token_require_kind(enum TokenKind kind) { 241 Token t = token_consume(); 242 if (!token_is_kind(t, kind)) { 243 ERROR(); 244 } 245 return t; 246 } 247 248 void lex_test(void) { 249 char *source = "+123<<>>4+ ~994"; 250 printf("lex_test: '%s'\n", source); 251 g_stream = source; 252 Token t = token_consume(); 253 while (t.kind) { 254 print_token(t); 255 t = token_consume(); 256 } 257 } 258 259 enum ExprKind { 260 EXPR_NONE, 261 EXPR_OPERAND, 262 EXPR_UNARY, 263 EXPR_BINARY, 264 }; 265 266 bool is_unary_op(enum TokenKind o) { 267 return o == TOKEN_OP_SUB || o == TOKEN_OP_BIN_NOT; 268 } 269 270 bool is_mul_op(enum TokenKind o) { 271 return o == TOKEN_OP_MUL || o == TOKEN_OP_DIV || o == TOKEN_OP_MOD || o == TOKEN_OP_SHIFT_L || o == TOKEN_OP_SHIFT_R || o == TOKEN_OP_BIN_AND; 272 } 273 274 bool is_add_op(enum TokenKind o) { 275 return o == TOKEN_OP_ADD || o == TOKEN_OP_SUB || o == TOKEN_OP_BIN_OR || o == TOKEN_OP_BIN_XOR; 276 } 277 278 typedef struct Expr Expr; 279 280 struct Expr { 281 enum ExprKind kind; 282 enum TokenKind op; 283 Expr *left; 284 Expr *right; 285 int32_t operand; 286 }; 287 288 Expr *expr_alloc(void) { 289 Expr *e = malloc(sizeof(Expr)); 290 *e = (Expr) {0}; 291 return e; 292 } 293 294 Expr *expr_unary(enum TokenKind o, Expr *u) { 295 assert(is_unary_op(o)); 296 Expr *e = expr_alloc(); 297 *e = (Expr) { 298 .kind = EXPR_UNARY, 299 .op = o, 300 .left = u, 301 }; 302 return e; 303 } 304 305 Expr *expr_binary(enum TokenKind o, Expr *l, Expr *r) { 306 assert(is_mul_op(o) || is_add_op(o)); 307 Expr *e = expr_alloc(); 308 *e = (Expr) { 309 .kind = EXPR_BINARY, 310 .op = o, 311 .left = l, 312 .right = r, 313 }; 314 return e; 315 } 316 317 void print_expr(Expr *e) { 318 assert(e); 319 320 char *op = token_kind_glyph(e->op); 321 322 if (e->kind != EXPR_OPERAND) { 323 printf("("); 324 } 325 326 switch (e->kind) { 327 case EXPR_OPERAND: 328 printf("%i", e->operand); 329 break; 330 case EXPR_UNARY: 331 printf("%s ", op); 332 print_expr(e->left); 333 break; 334 case EXPR_BINARY: 335 printf("%s ", op); 336 print_expr(e->left); 337 printf(" "); 338 print_expr(e->right); 339 break; 340 case EXPR_NONE: // fallthrough 341 default: 342 ERROR(); 343 break; 344 } 345 346 if (e->kind != EXPR_OPERAND) { 347 printf(")"); 348 } 349 } 350 351 int32_t parse_number(void) { 352 Token t = token_require_kind(TOKEN_INT); 353 return t.val; 354 } 355 356 Expr *parse_expr_operand(void) { 357 Expr *e = expr_alloc(); 358 *e = (Expr) { 359 .operand = parse_number(), 360 .kind = EXPR_OPERAND, 361 }; 362 return e; 363 } 364 365 Expr *parse_expr(void); 366 367 Expr *parse_expr_grouping(void) { 368 if (token_consume_kind(TOKEN_PAREN_L)) { 369 Expr *e = parse_expr(); 370 token_require_kind(TOKEN_PAREN_R); 371 return e; 372 } else { 373 return parse_expr_operand(); 374 } 375 } 376 377 Expr *parse_expr_unary(void) { 378 if (is_unary_op(token_peek().kind)) { 379 enum TokenKind op = token_consume().kind; 380 return expr_unary(op, parse_expr_unary()); 381 } else { 382 return parse_expr_grouping(); 383 } 384 } 385 386 Expr *parse_expr_mul(void) { 387 Expr *e = parse_expr_unary(); 388 while (is_mul_op(token_peek().kind)) { 389 enum TokenKind op = token_consume().kind; 390 e = expr_binary(op, e, parse_expr_unary()); 391 } 392 return e; 393 } 394 395 Expr *parse_expr_add(void) { 396 Expr *e = parse_expr_mul(); 397 while (is_add_op(token_peek().kind)) { 398 enum TokenKind op = token_consume().kind; 399 e = expr_binary(op, e, parse_expr_mul()); 400 } 401 402 return e; 403 } 404 405 Expr *parse_expr(void) { 406 return parse_expr_add(); 407 } 408 409 int32_t eval_expr(Expr *e) { 410 assert(e); 411 412 switch (e->kind) { 413 case EXPR_OPERAND: 414 return e->operand; 415 break; 416 case EXPR_UNARY: { 417 int32_t val = eval_expr(e->left); 418 switch (e->op) { 419 case TOKEN_OP_SUB: 420 return -val; 421 break; 422 case TOKEN_OP_BIN_NOT: 423 return ~val; 424 break; 425 default: 426 ERROR(); 427 break; 428 } 429 } break; 430 case EXPR_BINARY: { 431 int32_t val1 = eval_expr(e->left); 432 int32_t val2 = eval_expr(e->right); 433 434 switch (e->op) { 435 case TOKEN_OP_ADD: 436 return val1 + val2; 437 break; 438 case TOKEN_OP_SUB: 439 return val1 - val2; 440 break; 441 case TOKEN_OP_BIN_OR: 442 return val1 | val2; 443 break; 444 case TOKEN_OP_BIN_XOR: 445 return val1 ^ val2; 446 break; 447 case TOKEN_OP_MUL: 448 return val1 * val2; 449 break; 450 case TOKEN_OP_DIV: 451 if (val2 == 0) { 452 ERROR(); 453 } 454 return val1 / val2; 455 break; 456 case TOKEN_OP_MOD: 457 return val1 % val2; 458 break; 459 case TOKEN_OP_SHIFT_L: 460 return val1 << val2; 461 break; 462 case TOKEN_OP_SHIFT_R: 463 return val1 >> val2; 464 break; 465 case TOKEN_OP_BIN_AND: 466 return val1 & val2; 467 break; 468 default: 469 ERROR(); 470 break; 471 } 472 } break; 473 case EXPR_NONE: // fallthrough 474 default: 475 ERROR(); 476 break; 477 } 478 return 0; 479 } 480 481 // Precedence Climbing 482 // op_unary = "-" | "~". 483 // op_mul = "*" | "/" | "%" | "<<" | ">>" | "&". 484 // op_add = "+" | "-" | "|" | "^". 485 // expr_operand = number. 486 // expr_grouping = "(" expr ") | expr_operand." 487 // expr_unary = ([op_unary] expr_unary) | expr_grouping. 488 // expr_mul = expr_unary {op_mul expr_unary}. 489 // expr_add = expr_mul {op_add expr_mul}. 490 // expr = expr_add. 491 // number = "0" .. "9" {"0" .. "9"}. 492 Expr *parse_test(void) { 493 char *source = "12*34 + 45/56 + ~-25 + ((4+6) / (6+4))"; 494 printf("parse_test: '%s'\n", source); 495 g_stream = source; 496 Expr *e = parse_expr(); 497 print_expr(e); 498 printf("\n"); 499 return e; 500 } 501 502 void eval_test(Expr *e) { 503 printf("Result: %i\n", eval_expr(e)); 504 } 505 506 int main(void) { 507 buf_test(); 508 lex_test(); 509 Expr *e = parse_test(); 510 eval_test(e); 511 return 0; 512 }