1 /* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2018-2021 Gavin D. Howard and contributors. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * * Redistributions of source code must retain the above copyright notice, this 12 * list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * ***************************************************************************** 31 * 32 * The parser for bc. 33 * 34 */ 35 36 #if BC_ENABLED 37 38 #include <assert.h> 39 #include <stdbool.h> 40 #include <stdlib.h> 41 #include <string.h> 42 43 #include <setjmp.h> 44 45 #include <bc.h> 46 #include <num.h> 47 #include <vm.h> 48 49 static void bc_parse_else(BcParse *p); 50 static void bc_parse_stmt(BcParse *p); 51 static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags, 52 BcParseNext next); 53 54 static bool bc_parse_inst_isLeaf(BcInst t) { 55 return (t >= BC_INST_NUM && t <= BC_INST_MAXSCALE) || 56 #if BC_ENABLE_EXTRA_MATH 57 t == BC_INST_TRUNC || 58 #endif // BC_ENABLE_EXTRA_MATH 59 t <= BC_INST_DEC; 60 } 61 62 static bool bc_parse_isDelimiter(const BcParse *p) { 63 64 BcLexType t = p->l.t; 65 bool good = false; 66 67 if (BC_PARSE_DELIMITER(t)) return true; 68 69 if (t == BC_LEX_KW_ELSE) { 70 71 size_t i; 72 uint16_t *fptr = NULL, flags = BC_PARSE_FLAG_ELSE; 73 74 for (i = 0; i < p->flags.len && BC_PARSE_BLOCK_STMT(flags); ++i) { 75 76 fptr = bc_vec_item_rev(&p->flags, i); 77 flags = *fptr; 78 79 if ((flags & BC_PARSE_FLAG_BRACE) && p->l.last != BC_LEX_RBRACE) 80 return false; 81 } 82 83 good = ((flags & BC_PARSE_FLAG_IF) != 0); 84 } 85 else if (t == BC_LEX_RBRACE) { 86 87 size_t i; 88 89 for (i = 0; !good && i < p->flags.len; ++i) { 90 uint16_t *fptr = bc_vec_item_rev(&p->flags, i); 91 good = (((*fptr) & BC_PARSE_FLAG_BRACE) != 0); 92 } 93 } 94 95 return good; 96 } 97 98 static void bc_parse_setLabel(BcParse *p) { 99 100 BcFunc *func = p->func; 101 BcInstPtr *ip = bc_vec_top(&p->exits); 102 size_t *label; 103 104 assert(func == bc_vec_item(&p->prog->fns, p->fidx)); 105 106 label = bc_vec_item(&func->labels, ip->idx); 107 *label = func->code.len; 108 109 bc_vec_pop(&p->exits); 110 } 111 112 static void bc_parse_createLabel(BcParse *p, size_t idx) { 113 bc_vec_push(&p->func->labels, &idx); 114 } 115 116 static void bc_parse_createCondLabel(BcParse *p, size_t idx) { 117 bc_parse_createLabel(p, p->func->code.len); 118 bc_vec_push(&p->conds, &idx); 119 } 120 121 static void bc_parse_createExitLabel(BcParse *p, size_t idx, bool loop) { 122 123 BcInstPtr ip; 124 125 assert(p->func == bc_vec_item(&p->prog->fns, p->fidx)); 126 127 ip.func = loop; 128 ip.idx = idx; 129 ip.len = 0; 130 131 bc_vec_push(&p->exits, &ip); 132 bc_parse_createLabel(p, SIZE_MAX); 133 } 134 135 static void bc_parse_operator(BcParse *p, BcLexType type, 136 size_t start, size_t *nexprs) 137 { 138 BcLexType t; 139 uchar l, r = BC_PARSE_OP_PREC(type); 140 uchar left = BC_PARSE_OP_LEFT(type); 141 142 while (p->ops.len > start) { 143 144 t = BC_PARSE_TOP_OP(p); 145 if (t == BC_LEX_LPAREN) break; 146 147 l = BC_PARSE_OP_PREC(t); 148 if (l >= r && (l != r || !left)) break; 149 150 bc_parse_push(p, BC_PARSE_TOKEN_INST(t)); 151 bc_vec_pop(&p->ops); 152 *nexprs -= !BC_PARSE_OP_PREFIX(t); 153 } 154 155 bc_vec_push(&p->ops, &type); 156 } 157 158 static void bc_parse_rightParen(BcParse *p, size_t *nexs) { 159 160 BcLexType top; 161 162 while ((top = BC_PARSE_TOP_OP(p)) != BC_LEX_LPAREN) { 163 bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); 164 bc_vec_pop(&p->ops); 165 *nexs -= !BC_PARSE_OP_PREFIX(top); 166 } 167 168 bc_vec_pop(&p->ops); 169 170 bc_lex_next(&p->l); 171 } 172 173 static void bc_parse_params(BcParse *p, uint8_t flags) { 174 175 bool comma = false; 176 size_t nparams; 177 178 bc_lex_next(&p->l); 179 180 flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); 181 flags |= (BC_PARSE_ARRAY | BC_PARSE_NEEDVAL); 182 183 for (nparams = 0; p->l.t != BC_LEX_RPAREN; ++nparams) { 184 185 bc_parse_expr_status(p, flags, bc_parse_next_param); 186 187 comma = (p->l.t == BC_LEX_COMMA); 188 if (comma) bc_lex_next(&p->l); 189 } 190 191 if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 192 bc_parse_push(p, BC_INST_CALL); 193 bc_parse_pushIndex(p, nparams); 194 } 195 196 static void bc_parse_call(BcParse *p, const char *name, uint8_t flags) { 197 198 size_t idx; 199 200 bc_parse_params(p, flags); 201 202 // We just assert this because bc_parse_params() should 203 // ensure that the next token is what it should be. 204 assert(p->l.t == BC_LEX_RPAREN); 205 206 // We cannot use bc_program_insertFunc() here 207 // because it will overwrite an existing function. 208 idx = bc_map_index(&p->prog->fn_map, name); 209 210 if (idx == BC_VEC_INVALID_IDX) { 211 212 BC_SIG_LOCK; 213 214 idx = bc_program_insertFunc(p->prog, name); 215 216 BC_SIG_UNLOCK; 217 218 assert(idx != BC_VEC_INVALID_IDX); 219 220 // Make sure that this pointer was not invalidated. 221 p->func = bc_vec_item(&p->prog->fns, p->fidx); 222 } 223 else idx = ((BcId*) bc_vec_item(&p->prog->fn_map, idx))->idx; 224 225 bc_parse_pushIndex(p, idx); 226 227 bc_lex_next(&p->l); 228 } 229 230 static void bc_parse_name(BcParse *p, BcInst *type, 231 bool *can_assign, uint8_t flags) 232 { 233 char *name; 234 235 BC_SIG_LOCK; 236 237 name = bc_vm_strdup(p->l.str.v); 238 239 BC_SETJMP_LOCKED(err); 240 241 BC_SIG_UNLOCK; 242 243 bc_lex_next(&p->l); 244 245 if (p->l.t == BC_LEX_LBRACKET) { 246 247 bc_lex_next(&p->l); 248 249 if (p->l.t == BC_LEX_RBRACKET) { 250 251 if (BC_ERR(!(flags & BC_PARSE_ARRAY))) 252 bc_parse_err(p, BC_ERR_PARSE_EXPR); 253 254 *type = BC_INST_ARRAY; 255 *can_assign = false; 256 } 257 else { 258 259 uint8_t flags2 = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | 260 BC_PARSE_NEEDVAL; 261 262 bc_parse_expr_status(p, flags2, bc_parse_next_elem); 263 264 if (BC_ERR(p->l.t != BC_LEX_RBRACKET)) 265 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 266 267 *type = BC_INST_ARRAY_ELEM; 268 *can_assign = true; 269 } 270 271 bc_lex_next(&p->l); 272 273 bc_parse_push(p, *type); 274 bc_parse_pushName(p, name, false); 275 } 276 else if (p->l.t == BC_LEX_LPAREN) { 277 278 if (BC_ERR(flags & BC_PARSE_NOCALL)) 279 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 280 281 *type = BC_INST_CALL; 282 *can_assign = false; 283 284 bc_parse_call(p, name, flags); 285 } 286 else { 287 *type = BC_INST_VAR; 288 *can_assign = true; 289 bc_parse_push(p, BC_INST_VAR); 290 bc_parse_pushName(p, name, true); 291 } 292 293 err: 294 BC_SIG_MAYLOCK; 295 free(name); 296 BC_LONGJMP_CONT; 297 } 298 299 static void bc_parse_noArgBuiltin(BcParse *p, BcInst inst) { 300 301 bc_lex_next(&p->l); 302 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 303 304 bc_lex_next(&p->l); 305 if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 306 307 bc_parse_push(p, inst); 308 309 bc_lex_next(&p->l); 310 } 311 312 static void bc_parse_builtin(BcParse *p, BcLexType type, 313 uint8_t flags, BcInst *prev) 314 { 315 bc_lex_next(&p->l); 316 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) 317 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 318 319 bc_lex_next(&p->l); 320 321 flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); 322 flags |= BC_PARSE_NEEDVAL; 323 if (type == BC_LEX_KW_LENGTH) flags |= BC_PARSE_ARRAY; 324 325 bc_parse_expr_status(p, flags, bc_parse_next_rel); 326 327 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) 328 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 329 330 *prev = type - BC_LEX_KW_LENGTH + BC_INST_LENGTH; 331 bc_parse_push(p, *prev); 332 333 bc_lex_next(&p->l); 334 } 335 336 static void bc_parse_scale(BcParse *p, BcInst *type, 337 bool *can_assign, uint8_t flags) 338 { 339 bc_lex_next(&p->l); 340 341 if (p->l.t != BC_LEX_LPAREN) { 342 *type = BC_INST_SCALE; 343 *can_assign = true; 344 bc_parse_push(p, BC_INST_SCALE); 345 return; 346 } 347 348 *type = BC_INST_SCALE_FUNC; 349 *can_assign = false; 350 flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); 351 flags |= BC_PARSE_NEEDVAL; 352 353 bc_lex_next(&p->l); 354 355 bc_parse_expr_status(p, flags, bc_parse_next_rel); 356 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) 357 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 358 359 bc_parse_push(p, BC_INST_SCALE_FUNC); 360 361 bc_lex_next(&p->l); 362 } 363 364 static void bc_parse_incdec(BcParse *p, BcInst *prev, bool *can_assign, 365 size_t *nexs, uint8_t flags) 366 { 367 BcLexType type; 368 uchar inst; 369 BcInst etype = *prev; 370 BcLexType last = p->l.last; 371 372 assert(prev != NULL && can_assign != NULL); 373 374 if (BC_ERR(last == BC_LEX_OP_INC || last == BC_LEX_OP_DEC || 375 last == BC_LEX_RPAREN)) 376 { 377 bc_parse_err(p, BC_ERR_PARSE_ASSIGN); 378 } 379 380 if (BC_PARSE_INST_VAR(etype)) { 381 382 if (!*can_assign) bc_parse_err(p, BC_ERR_PARSE_ASSIGN); 383 384 *prev = inst = BC_INST_INC + (p->l.t != BC_LEX_OP_INC); 385 bc_parse_push(p, inst); 386 bc_lex_next(&p->l); 387 *can_assign = false; 388 } 389 else { 390 391 *prev = inst = BC_INST_ASSIGN_PLUS + (p->l.t != BC_LEX_OP_INC); 392 393 bc_lex_next(&p->l); 394 type = p->l.t; 395 396 // Because we parse the next part of the expression 397 // right here, we need to increment this. 398 *nexs = *nexs + 1; 399 400 if (type == BC_LEX_NAME) { 401 uint8_t flags2 = flags & ~BC_PARSE_ARRAY; 402 bc_parse_name(p, prev, can_assign, flags2 | BC_PARSE_NOCALL); 403 } 404 else if (type >= BC_LEX_KW_LAST && type <= BC_LEX_KW_OBASE) { 405 bc_parse_push(p, type - BC_LEX_KW_LAST + BC_INST_LAST); 406 bc_lex_next(&p->l); 407 } 408 else if (BC_NO_ERR(type == BC_LEX_KW_SCALE)) { 409 410 bc_lex_next(&p->l); 411 412 if (BC_ERR(p->l.t == BC_LEX_LPAREN)) 413 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 414 else bc_parse_push(p, BC_INST_SCALE); 415 } 416 else bc_parse_err(p, BC_ERR_PARSE_TOKEN); 417 418 *can_assign = false; 419 420 bc_parse_push(p, BC_INST_ONE); 421 bc_parse_push(p, inst); 422 } 423 } 424 425 static void bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, 426 bool rparen, bool binlast, size_t *nexprs) 427 { 428 BcLexType type; 429 430 bc_lex_next(&p->l); 431 432 type = BC_PARSE_LEAF(*prev, binlast, rparen) ? BC_LEX_OP_MINUS : BC_LEX_NEG; 433 *prev = BC_PARSE_TOKEN_INST(type); 434 435 // We can just push onto the op stack because this is the largest 436 // precedence operator that gets pushed. Inc/dec does not. 437 if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type); 438 else bc_parse_operator(p, type, ops_bgn, nexprs); 439 } 440 441 static void bc_parse_str(BcParse *p, char inst) { 442 bc_parse_addString(p); 443 bc_parse_push(p, inst); 444 bc_lex_next(&p->l); 445 } 446 447 static void bc_parse_print(BcParse *p) { 448 449 BcLexType t; 450 bool comma = false; 451 452 bc_lex_next(&p->l); 453 454 t = p->l.t; 455 456 if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERR_PARSE_PRINT); 457 458 do { 459 if (t == BC_LEX_STR) bc_parse_str(p, BC_INST_PRINT_POP); 460 else { 461 bc_parse_expr_status(p, BC_PARSE_NEEDVAL, bc_parse_next_print); 462 bc_parse_push(p, BC_INST_PRINT_POP); 463 } 464 465 comma = (p->l.t == BC_LEX_COMMA); 466 467 if (comma) bc_lex_next(&p->l); 468 else { 469 if (!bc_parse_isDelimiter(p)) 470 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 471 else break; 472 } 473 474 t = p->l.t; 475 } while (true); 476 477 if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 478 } 479 480 static void bc_parse_return(BcParse *p) { 481 482 BcLexType t; 483 bool paren; 484 uchar inst = BC_INST_RET0; 485 486 if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 487 488 if (p->func->voidfn) inst = BC_INST_RET_VOID; 489 490 bc_lex_next(&p->l); 491 492 t = p->l.t; 493 paren = t == BC_LEX_LPAREN; 494 495 if (bc_parse_isDelimiter(p)) bc_parse_push(p, inst); 496 else { 497 498 BcParseStatus s; 499 500 s = bc_parse_expr_err(p, BC_PARSE_NEEDVAL, bc_parse_next_expr); 501 502 if (s == BC_PARSE_STATUS_EMPTY_EXPR) { 503 bc_parse_push(p, inst); 504 bc_lex_next(&p->l); 505 } 506 507 if (!paren || p->l.last != BC_LEX_RPAREN) { 508 bc_parse_err(p, BC_ERR_POSIX_RET); 509 } 510 else if (BC_ERR(p->func->voidfn)) 511 bc_parse_verr(p, BC_ERR_PARSE_RET_VOID, p->func->name); 512 513 bc_parse_push(p, BC_INST_RET); 514 } 515 } 516 517 static void bc_parse_noElse(BcParse *p) { 518 uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); 519 *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END)); 520 bc_parse_setLabel(p); 521 } 522 523 static void bc_parse_endBody(BcParse *p, bool brace) { 524 525 bool has_brace, new_else = false; 526 527 if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 528 529 if (brace) { 530 531 assert(p->l.t == BC_LEX_RBRACE); 532 533 bc_lex_next(&p->l); 534 if (BC_ERR(!bc_parse_isDelimiter(p))) 535 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 536 } 537 538 has_brace = (BC_PARSE_BRACE(p) != 0); 539 540 do { 541 size_t len = p->flags.len; 542 bool loop; 543 544 if (has_brace && !brace) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 545 546 loop = (BC_PARSE_LOOP_INNER(p) != 0); 547 548 if (loop || BC_PARSE_ELSE(p)) { 549 550 if (loop) { 551 552 size_t *label = bc_vec_top(&p->conds); 553 554 bc_parse_push(p, BC_INST_JUMP); 555 bc_parse_pushIndex(p, *label); 556 557 bc_vec_pop(&p->conds); 558 } 559 560 bc_parse_setLabel(p); 561 bc_vec_pop(&p->flags); 562 } 563 else if (BC_PARSE_FUNC_INNER(p)) { 564 BcInst inst = (p->func->voidfn ? BC_INST_RET_VOID : BC_INST_RET0); 565 bc_parse_push(p, inst); 566 bc_parse_updateFunc(p, BC_PROG_MAIN); 567 bc_vec_pop(&p->flags); 568 } 569 else if (BC_PARSE_BRACE(p) && !BC_PARSE_IF(p)) bc_vec_pop(&p->flags); 570 571 // This needs to be last to parse nested if's properly. 572 if (BC_PARSE_IF(p) && (len == p->flags.len || !BC_PARSE_BRACE(p))) { 573 574 while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l); 575 576 bc_vec_pop(&p->flags); 577 578 if (!BC_S) { 579 580 *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_IF_END; 581 new_else = (p->l.t == BC_LEX_KW_ELSE); 582 583 if (new_else) bc_parse_else(p); 584 else if (!has_brace && (!BC_PARSE_IF_END(p) || brace)) 585 bc_parse_noElse(p); 586 } 587 else bc_parse_noElse(p); 588 } 589 590 if (brace && has_brace) brace = false; 591 592 } while (p->flags.len > 1 && !new_else && (!BC_PARSE_IF_END(p) || brace) && 593 !(has_brace = (BC_PARSE_BRACE(p) != 0))); 594 595 if (BC_ERR(p->flags.len == 1 && brace)) 596 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 597 else if (brace && BC_PARSE_BRACE(p)) { 598 599 uint16_t flags = BC_PARSE_TOP_FLAG(p); 600 601 if (!(flags & (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_LOOP_INNER)) && 602 !(flags & (BC_PARSE_FLAG_IF | BC_PARSE_FLAG_ELSE)) && 603 !(flags & (BC_PARSE_FLAG_IF_END))) 604 { 605 bc_vec_pop(&p->flags); 606 } 607 } 608 } 609 610 static void bc_parse_startBody(BcParse *p, uint16_t flags) { 611 assert(flags); 612 flags |= (BC_PARSE_TOP_FLAG(p) & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP)); 613 flags |= BC_PARSE_FLAG_BODY; 614 bc_vec_push(&p->flags, &flags); 615 } 616 617 static void bc_parse_if(BcParse *p) { 618 619 size_t idx; 620 uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL); 621 622 bc_lex_next(&p->l); 623 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) 624 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 625 626 bc_lex_next(&p->l); 627 bc_parse_expr_status(p, flags, bc_parse_next_rel); 628 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) 629 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 630 631 bc_lex_next(&p->l); 632 bc_parse_push(p, BC_INST_JUMP_ZERO); 633 634 idx = p->func->labels.len; 635 636 bc_parse_pushIndex(p, idx); 637 bc_parse_createExitLabel(p, idx, false); 638 bc_parse_startBody(p, BC_PARSE_FLAG_IF); 639 } 640 641 static void bc_parse_else(BcParse *p) { 642 643 size_t idx = p->func->labels.len; 644 645 if (BC_ERR(!BC_PARSE_IF_END(p))) 646 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 647 648 bc_parse_push(p, BC_INST_JUMP); 649 bc_parse_pushIndex(p, idx); 650 651 bc_parse_noElse(p); 652 653 bc_parse_createExitLabel(p, idx, false); 654 bc_parse_startBody(p, BC_PARSE_FLAG_ELSE); 655 656 bc_lex_next(&p->l); 657 } 658 659 static void bc_parse_while(BcParse *p) { 660 661 size_t idx; 662 uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL); 663 664 bc_lex_next(&p->l); 665 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) 666 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 667 bc_lex_next(&p->l); 668 669 bc_parse_createCondLabel(p, p->func->labels.len); 670 idx = p->func->labels.len; 671 bc_parse_createExitLabel(p, idx, true); 672 673 bc_parse_expr_status(p, flags, bc_parse_next_rel); 674 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) 675 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 676 bc_lex_next(&p->l); 677 678 bc_parse_push(p, BC_INST_JUMP_ZERO); 679 bc_parse_pushIndex(p, idx); 680 bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); 681 } 682 683 static void bc_parse_for(BcParse *p) { 684 685 size_t cond_idx, exit_idx, body_idx, update_idx; 686 687 bc_lex_next(&p->l); 688 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) 689 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 690 bc_lex_next(&p->l); 691 692 if (p->l.t != BC_LEX_SCOLON) 693 bc_parse_expr_status(p, 0, bc_parse_next_for); 694 else bc_parse_err(p, BC_ERR_POSIX_FOR); 695 696 if (BC_ERR(p->l.t != BC_LEX_SCOLON)) 697 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 698 bc_lex_next(&p->l); 699 700 cond_idx = p->func->labels.len; 701 update_idx = cond_idx + 1; 702 body_idx = update_idx + 1; 703 exit_idx = body_idx + 1; 704 705 bc_parse_createLabel(p, p->func->code.len); 706 707 if (p->l.t != BC_LEX_SCOLON) { 708 uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL); 709 bc_parse_expr_status(p, flags, bc_parse_next_for); 710 } 711 else { 712 713 // Set this for the next call to bc_parse_number. 714 // This is safe to set because the current token 715 // is a semicolon, which has no string requirement. 716 bc_vec_string(&p->l.str, sizeof(bc_parse_one) - 1, bc_parse_one); 717 bc_parse_number(p); 718 719 bc_parse_err(p, BC_ERR_POSIX_FOR); 720 } 721 722 if (BC_ERR(p->l.t != BC_LEX_SCOLON)) 723 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 724 725 bc_lex_next(&p->l); 726 727 bc_parse_push(p, BC_INST_JUMP_ZERO); 728 bc_parse_pushIndex(p, exit_idx); 729 bc_parse_push(p, BC_INST_JUMP); 730 bc_parse_pushIndex(p, body_idx); 731 732 bc_parse_createCondLabel(p, update_idx); 733 734 if (p->l.t != BC_LEX_RPAREN) 735 bc_parse_expr_status(p, 0, bc_parse_next_rel); 736 else bc_parse_err(p, BC_ERR_POSIX_FOR); 737 738 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) 739 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 740 bc_parse_push(p, BC_INST_JUMP); 741 bc_parse_pushIndex(p, cond_idx); 742 bc_parse_createLabel(p, p->func->code.len); 743 744 bc_parse_createExitLabel(p, exit_idx, true); 745 bc_lex_next(&p->l); 746 bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); 747 } 748 749 static void bc_parse_loopExit(BcParse *p, BcLexType type) { 750 751 size_t i; 752 BcInstPtr *ip; 753 754 if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 755 756 if (type == BC_LEX_KW_BREAK) { 757 758 if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 759 760 i = p->exits.len - 1; 761 ip = bc_vec_item(&p->exits, i); 762 763 while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); 764 assert(ip != NULL && (i < p->exits.len || ip->func)); 765 i = ip->idx; 766 } 767 else i = *((size_t*) bc_vec_top(&p->conds)); 768 769 bc_parse_push(p, BC_INST_JUMP); 770 bc_parse_pushIndex(p, i); 771 772 bc_lex_next(&p->l); 773 } 774 775 static void bc_parse_func(BcParse *p) { 776 777 bool comma = false, voidfn; 778 uint16_t flags; 779 size_t idx; 780 781 bc_lex_next(&p->l); 782 783 if (BC_ERR(p->l.t != BC_LEX_NAME)) 784 bc_parse_err(p, BC_ERR_PARSE_FUNC); 785 786 voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME && 787 !strcmp(p->l.str.v, "void")); 788 789 bc_lex_next(&p->l); 790 791 voidfn = (voidfn && p->l.t == BC_LEX_NAME); 792 793 if (voidfn) { 794 bc_parse_err(p, BC_ERR_POSIX_VOID); 795 bc_lex_next(&p->l); 796 } 797 798 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) 799 bc_parse_err(p, BC_ERR_PARSE_FUNC); 800 801 assert(p->prog->fns.len == p->prog->fn_map.len); 802 803 BC_SIG_LOCK; 804 805 idx = bc_program_insertFunc(p->prog, p->l.str.v); 806 807 BC_SIG_UNLOCK; 808 809 assert(idx); 810 bc_parse_updateFunc(p, idx); 811 p->func->voidfn = voidfn; 812 813 bc_lex_next(&p->l); 814 815 while (p->l.t != BC_LEX_RPAREN) { 816 817 BcType t = BC_TYPE_VAR; 818 819 if (p->l.t == BC_LEX_OP_MULTIPLY) { 820 t = BC_TYPE_REF; 821 bc_lex_next(&p->l); 822 bc_parse_err(p, BC_ERR_POSIX_REF); 823 } 824 825 if (BC_ERR(p->l.t != BC_LEX_NAME)) 826 bc_parse_err(p, BC_ERR_PARSE_FUNC); 827 828 p->func->nparams += 1; 829 830 bc_vec_string(&p->buf, p->l.str.len, p->l.str.v); 831 832 bc_lex_next(&p->l); 833 834 if (p->l.t == BC_LEX_LBRACKET) { 835 836 if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY; 837 838 bc_lex_next(&p->l); 839 840 if (BC_ERR(p->l.t != BC_LEX_RBRACKET)) 841 bc_parse_err(p, BC_ERR_PARSE_FUNC); 842 843 bc_lex_next(&p->l); 844 } 845 else if (BC_ERR(t == BC_TYPE_REF)) 846 bc_parse_verr(p, BC_ERR_PARSE_REF_VAR, p->buf.v); 847 848 comma = (p->l.t == BC_LEX_COMMA); 849 if (comma) { 850 bc_lex_next(&p->l); 851 } 852 853 bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line); 854 } 855 856 if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC); 857 858 flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER; 859 bc_parse_startBody(p, flags); 860 861 bc_lex_next(&p->l); 862 863 if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERR_POSIX_BRACE); 864 } 865 866 static void bc_parse_auto(BcParse *p) { 867 868 bool comma, one; 869 870 if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 871 bc_lex_next(&p->l); 872 873 p->auto_part = comma = false; 874 one = p->l.t == BC_LEX_NAME; 875 876 while (p->l.t == BC_LEX_NAME) { 877 878 BcType t; 879 880 bc_vec_string(&p->buf, p->l.str.len - 1, p->l.str.v); 881 882 bc_lex_next(&p->l); 883 884 if (p->l.t == BC_LEX_LBRACKET) { 885 886 t = BC_TYPE_ARRAY; 887 888 bc_lex_next(&p->l); 889 890 if (BC_ERR(p->l.t != BC_LEX_RBRACKET)) 891 bc_parse_err(p, BC_ERR_PARSE_FUNC); 892 893 bc_lex_next(&p->l); 894 } 895 else t = BC_TYPE_VAR; 896 897 comma = (p->l.t == BC_LEX_COMMA); 898 if (comma) bc_lex_next(&p->l); 899 900 bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line); 901 } 902 903 if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC); 904 if (BC_ERR(!one)) bc_parse_err(p, BC_ERR_PARSE_NO_AUTO); 905 if (BC_ERR(!bc_parse_isDelimiter(p))) 906 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 907 } 908 909 static void bc_parse_body(BcParse *p, bool brace) { 910 911 uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); 912 913 assert(flag_ptr != NULL); 914 assert(p->flags.len >= 2); 915 916 *flag_ptr &= ~(BC_PARSE_FLAG_BODY); 917 918 if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { 919 920 if (BC_ERR(!brace)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); 921 922 p->auto_part = (p->l.t != BC_LEX_KW_AUTO); 923 924 if (!p->auto_part) { 925 926 // Make sure this is true to not get a parse error. 927 p->auto_part = true; 928 929 bc_parse_auto(p); 930 } 931 932 if (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l); 933 } 934 else { 935 936 size_t len = p->flags.len; 937 938 assert(*flag_ptr); 939 940 bc_parse_stmt(p); 941 942 if (!brace && !BC_PARSE_BODY(p) && len <= p->flags.len) 943 bc_parse_endBody(p, false); 944 } 945 } 946 947 static void bc_parse_stmt(BcParse *p) { 948 949 size_t len; 950 uint16_t flags; 951 BcLexType type = p->l.t; 952 953 if (type == BC_LEX_NLINE) { 954 bc_lex_next(&p->l); 955 return; 956 } 957 if (type == BC_LEX_KW_AUTO) { 958 bc_parse_auto(p); 959 return; 960 } 961 962 p->auto_part = false; 963 964 if (type != BC_LEX_KW_ELSE) { 965 966 if (BC_PARSE_IF_END(p)) { 967 bc_parse_noElse(p); 968 if (p->flags.len > 1 && !BC_PARSE_BRACE(p)) 969 bc_parse_endBody(p, false); 970 return; 971 } 972 else if (type == BC_LEX_LBRACE) { 973 974 if (!BC_PARSE_BODY(p)) { 975 bc_parse_startBody(p, BC_PARSE_FLAG_BRACE); 976 bc_lex_next(&p->l); 977 } 978 else { 979 *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_BRACE; 980 bc_lex_next(&p->l); 981 bc_parse_body(p, true); 982 } 983 984 return; 985 } 986 else if (BC_PARSE_BODY(p) && !BC_PARSE_BRACE(p)) { 987 bc_parse_body(p, false); 988 return; 989 } 990 } 991 992 len = p->flags.len; 993 flags = BC_PARSE_TOP_FLAG(p); 994 995 switch (type) { 996 997 case BC_LEX_OP_INC: 998 case BC_LEX_OP_DEC: 999 case BC_LEX_OP_MINUS: 1000 case BC_LEX_OP_BOOL_NOT: 1001 case BC_LEX_LPAREN: 1002 case BC_LEX_NAME: 1003 case BC_LEX_NUMBER: 1004 case BC_LEX_KW_IBASE: 1005 case BC_LEX_KW_LAST: 1006 case BC_LEX_KW_LENGTH: 1007 case BC_LEX_KW_OBASE: 1008 case BC_LEX_KW_SCALE: 1009 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1010 case BC_LEX_KW_SEED: 1011 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1012 case BC_LEX_KW_SQRT: 1013 case BC_LEX_KW_ABS: 1014 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1015 case BC_LEX_KW_IRAND: 1016 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1017 case BC_LEX_KW_READ: 1018 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1019 case BC_LEX_KW_RAND: 1020 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1021 case BC_LEX_KW_MAXIBASE: 1022 case BC_LEX_KW_MAXOBASE: 1023 case BC_LEX_KW_MAXSCALE: 1024 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1025 case BC_LEX_KW_MAXRAND: 1026 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1027 { 1028 bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr); 1029 break; 1030 } 1031 1032 case BC_LEX_KW_ELSE: 1033 { 1034 bc_parse_else(p); 1035 break; 1036 } 1037 1038 case BC_LEX_SCOLON: 1039 { 1040 // Do nothing. 1041 break; 1042 } 1043 1044 case BC_LEX_RBRACE: 1045 { 1046 bc_parse_endBody(p, true); 1047 break; 1048 } 1049 1050 case BC_LEX_STR: 1051 { 1052 bc_parse_str(p, BC_INST_PRINT_STR); 1053 break; 1054 } 1055 1056 case BC_LEX_KW_BREAK: 1057 case BC_LEX_KW_CONTINUE: 1058 { 1059 bc_parse_loopExit(p, p->l.t); 1060 break; 1061 } 1062 1063 case BC_LEX_KW_FOR: 1064 { 1065 bc_parse_for(p); 1066 break; 1067 } 1068 1069 case BC_LEX_KW_HALT: 1070 { 1071 bc_parse_push(p, BC_INST_HALT); 1072 bc_lex_next(&p->l); 1073 break; 1074 } 1075 1076 case BC_LEX_KW_IF: 1077 { 1078 bc_parse_if(p); 1079 break; 1080 } 1081 1082 case BC_LEX_KW_LIMITS: 1083 { 1084 bc_vm_printf("BC_LONG_BIT = %lu\n", (ulong) BC_LONG_BIT); 1085 bc_vm_printf("BC_BASE_DIGS = %lu\n", (ulong) BC_BASE_DIGS); 1086 bc_vm_printf("BC_BASE_POW = %lu\n", (ulong) BC_BASE_POW); 1087 bc_vm_printf("BC_OVERFLOW_MAX = %lu\n", (ulong) BC_NUM_BIGDIG_MAX); 1088 bc_vm_printf("\n"); 1089 bc_vm_printf("BC_BASE_MAX = %lu\n", BC_MAX_OBASE); 1090 bc_vm_printf("BC_DIM_MAX = %lu\n", BC_MAX_DIM); 1091 bc_vm_printf("BC_SCALE_MAX = %lu\n", BC_MAX_SCALE); 1092 bc_vm_printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING); 1093 bc_vm_printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME); 1094 bc_vm_printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM); 1095 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1096 bc_vm_printf("BC_RAND_MAX = %lu\n", BC_MAX_RAND); 1097 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1098 bc_vm_printf("MAX Exponent = %lu\n", BC_MAX_EXP); 1099 bc_vm_printf("Number of vars = %lu\n", BC_MAX_VARS); 1100 1101 bc_lex_next(&p->l); 1102 1103 break; 1104 } 1105 1106 case BC_LEX_KW_PRINT: 1107 { 1108 bc_parse_print(p); 1109 break; 1110 } 1111 1112 case BC_LEX_KW_QUIT: 1113 { 1114 // Quit is a compile-time command. We don't exit directly, 1115 // so the vm can clean up. Limits do the same thing. 1116 vm.status = BC_STATUS_QUIT; 1117 BC_VM_JMP; 1118 break; 1119 } 1120 1121 case BC_LEX_KW_RETURN: 1122 { 1123 bc_parse_return(p); 1124 break; 1125 } 1126 1127 case BC_LEX_KW_WHILE: 1128 { 1129 bc_parse_while(p); 1130 break; 1131 } 1132 1133 default: 1134 { 1135 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 1136 } 1137 } 1138 1139 if (len == p->flags.len && flags == BC_PARSE_TOP_FLAG(p)) { 1140 if (BC_ERR(!bc_parse_isDelimiter(p))) 1141 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 1142 } 1143 1144 // Make sure semicolons are eaten. 1145 while (p->l.t == BC_LEX_SCOLON) bc_lex_next(&p->l); 1146 } 1147 1148 void bc_parse_parse(BcParse *p) { 1149 1150 assert(p); 1151 1152 BC_SETJMP(exit); 1153 1154 if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERR_PARSE_EOF); 1155 else if (p->l.t == BC_LEX_KW_DEFINE) { 1156 if (BC_ERR(BC_PARSE_NO_EXEC(p))) 1157 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 1158 bc_parse_func(p); 1159 } 1160 else bc_parse_stmt(p); 1161 1162 exit: 1163 BC_SIG_MAYLOCK; 1164 if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig))) 1165 bc_parse_reset(p); 1166 BC_LONGJMP_CONT; 1167 } 1168 1169 static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags, 1170 BcParseNext next) 1171 { 1172 BcInst prev = BC_INST_PRINT; 1173 uchar inst = BC_INST_INVALID; 1174 BcLexType top, t = p->l.t; 1175 size_t nexprs = 0, ops_bgn = p->ops.len; 1176 uint32_t i, nparens, nrelops; 1177 bool pfirst, rprn, done, get_token, assign, bin_last, incdec, can_assign; 1178 1179 assert(!(flags & BC_PARSE_PRINT) || !(flags & BC_PARSE_NEEDVAL)); 1180 1181 pfirst = (p->l.t == BC_LEX_LPAREN); 1182 nparens = nrelops = 0; 1183 rprn = done = get_token = assign = incdec = can_assign = false; 1184 bin_last = true; 1185 1186 // We want to eat newlines if newlines are not a valid ending token. 1187 // This is for spacing in things like for loop headers. 1188 if (!(flags & BC_PARSE_NOREAD)) { 1189 while ((t = p->l.t) == BC_LEX_NLINE) bc_lex_next(&p->l); 1190 } 1191 1192 for (; !done && BC_PARSE_EXPR(t); t = p->l.t) 1193 { 1194 switch (t) { 1195 1196 case BC_LEX_OP_INC: 1197 case BC_LEX_OP_DEC: 1198 { 1199 if (BC_ERR(incdec)) bc_parse_err(p, BC_ERR_PARSE_ASSIGN); 1200 bc_parse_incdec(p, &prev, &can_assign, &nexprs, flags); 1201 rprn = get_token = bin_last = false; 1202 incdec = true; 1203 flags &= ~(BC_PARSE_ARRAY); 1204 break; 1205 } 1206 1207 #if BC_ENABLE_EXTRA_MATH 1208 case BC_LEX_OP_TRUNC: 1209 { 1210 if (BC_ERR(!BC_PARSE_LEAF(prev, bin_last, rprn))) 1211 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 1212 1213 // I can just add the instruction because 1214 // negative will already be taken care of. 1215 bc_parse_push(p, BC_INST_TRUNC); 1216 rprn = can_assign = incdec = false; 1217 get_token = true; 1218 flags &= ~(BC_PARSE_ARRAY); 1219 break; 1220 } 1221 #endif // BC_ENABLE_EXTRA_MATH 1222 1223 case BC_LEX_OP_MINUS: 1224 { 1225 bc_parse_minus(p, &prev, ops_bgn, rprn, bin_last, &nexprs); 1226 rprn = get_token = can_assign = false; 1227 bin_last = (prev == BC_INST_MINUS); 1228 if (bin_last) incdec = false; 1229 flags &= ~(BC_PARSE_ARRAY); 1230 break; 1231 } 1232 1233 case BC_LEX_OP_ASSIGN_POWER: 1234 case BC_LEX_OP_ASSIGN_MULTIPLY: 1235 case BC_LEX_OP_ASSIGN_DIVIDE: 1236 case BC_LEX_OP_ASSIGN_MODULUS: 1237 case BC_LEX_OP_ASSIGN_PLUS: 1238 case BC_LEX_OP_ASSIGN_MINUS: 1239 #if BC_ENABLE_EXTRA_MATH 1240 case BC_LEX_OP_ASSIGN_PLACES: 1241 case BC_LEX_OP_ASSIGN_LSHIFT: 1242 case BC_LEX_OP_ASSIGN_RSHIFT: 1243 #endif // BC_ENABLE_EXTRA_MATH 1244 case BC_LEX_OP_ASSIGN: 1245 { 1246 if (!BC_PARSE_INST_VAR(prev)) 1247 bc_parse_err(p, BC_ERR_PARSE_ASSIGN); 1248 } 1249 // Fallthrough. 1250 BC_FALLTHROUGH 1251 1252 case BC_LEX_OP_POWER: 1253 case BC_LEX_OP_MULTIPLY: 1254 case BC_LEX_OP_DIVIDE: 1255 case BC_LEX_OP_MODULUS: 1256 case BC_LEX_OP_PLUS: 1257 #if BC_ENABLE_EXTRA_MATH 1258 case BC_LEX_OP_PLACES: 1259 case BC_LEX_OP_LSHIFT: 1260 case BC_LEX_OP_RSHIFT: 1261 #endif // BC_ENABLE_EXTRA_MATH 1262 case BC_LEX_OP_REL_EQ: 1263 case BC_LEX_OP_REL_LE: 1264 case BC_LEX_OP_REL_GE: 1265 case BC_LEX_OP_REL_NE: 1266 case BC_LEX_OP_REL_LT: 1267 case BC_LEX_OP_REL_GT: 1268 case BC_LEX_OP_BOOL_NOT: 1269 case BC_LEX_OP_BOOL_OR: 1270 case BC_LEX_OP_BOOL_AND: 1271 { 1272 if (BC_PARSE_OP_PREFIX(t)) { 1273 if (BC_ERR(!bin_last && !BC_PARSE_OP_PREFIX(p->l.last))) 1274 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1275 } 1276 else if (BC_ERR(BC_PARSE_PREV_PREFIX(prev) || bin_last)) 1277 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1278 1279 nrelops += (t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT); 1280 prev = BC_PARSE_TOKEN_INST(t); 1281 bc_parse_operator(p, t, ops_bgn, &nexprs); 1282 rprn = incdec = can_assign = false; 1283 get_token = true; 1284 bin_last = !BC_PARSE_OP_PREFIX(t); 1285 flags &= ~(BC_PARSE_ARRAY); 1286 1287 break; 1288 } 1289 1290 case BC_LEX_LPAREN: 1291 { 1292 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn))) 1293 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1294 1295 nparens += 1; 1296 rprn = incdec = can_assign = false; 1297 get_token = true; 1298 bc_vec_push(&p->ops, &t); 1299 1300 break; 1301 } 1302 1303 case BC_LEX_RPAREN: 1304 { 1305 // This needs to be a status. The error 1306 // is handled in bc_parse_expr_status(). 1307 if (BC_ERR(p->l.last == BC_LEX_LPAREN)) 1308 return BC_PARSE_STATUS_EMPTY_EXPR; 1309 1310 if (BC_ERR(bin_last || BC_PARSE_PREV_PREFIX(prev))) 1311 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1312 1313 if (!nparens) { 1314 done = true; 1315 get_token = false; 1316 break; 1317 } 1318 1319 nparens -= 1; 1320 rprn = true; 1321 get_token = bin_last = incdec = false; 1322 1323 bc_parse_rightParen(p, &nexprs); 1324 1325 break; 1326 } 1327 1328 case BC_LEX_NAME: 1329 { 1330 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn))) 1331 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1332 1333 get_token = bin_last = false; 1334 bc_parse_name(p, &prev, &can_assign, 1335 flags & ~BC_PARSE_NOCALL); 1336 rprn = (prev == BC_INST_CALL); 1337 nexprs += 1; 1338 flags &= ~(BC_PARSE_ARRAY); 1339 1340 break; 1341 } 1342 1343 case BC_LEX_NUMBER: 1344 { 1345 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn))) 1346 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1347 1348 bc_parse_number(p); 1349 nexprs += 1; 1350 prev = BC_INST_NUM; 1351 get_token = true; 1352 rprn = bin_last = can_assign = false; 1353 flags &= ~(BC_PARSE_ARRAY); 1354 1355 break; 1356 } 1357 1358 case BC_LEX_KW_IBASE: 1359 case BC_LEX_KW_LAST: 1360 case BC_LEX_KW_OBASE: 1361 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1362 case BC_LEX_KW_SEED: 1363 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1364 { 1365 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn))) 1366 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1367 1368 prev = t - BC_LEX_KW_LAST + BC_INST_LAST; 1369 bc_parse_push(p, prev); 1370 1371 get_token = can_assign = true; 1372 rprn = bin_last = false; 1373 nexprs += 1; 1374 flags &= ~(BC_PARSE_ARRAY); 1375 1376 break; 1377 } 1378 1379 case BC_LEX_KW_LENGTH: 1380 case BC_LEX_KW_SQRT: 1381 case BC_LEX_KW_ABS: 1382 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1383 case BC_LEX_KW_IRAND: 1384 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1385 { 1386 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn))) 1387 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1388 1389 bc_parse_builtin(p, t, flags, &prev); 1390 rprn = get_token = bin_last = incdec = can_assign = false; 1391 nexprs += 1; 1392 flags &= ~(BC_PARSE_ARRAY); 1393 1394 break; 1395 } 1396 1397 case BC_LEX_KW_READ: 1398 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1399 case BC_LEX_KW_RAND: 1400 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1401 case BC_LEX_KW_MAXIBASE: 1402 case BC_LEX_KW_MAXOBASE: 1403 case BC_LEX_KW_MAXSCALE: 1404 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1405 case BC_LEX_KW_MAXRAND: 1406 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND 1407 { 1408 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn))) 1409 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1410 else if (t == BC_LEX_KW_READ && BC_ERR(flags & BC_PARSE_NOREAD)) 1411 bc_parse_err(p, BC_ERR_EXEC_REC_READ); 1412 else { 1413 prev = t - BC_LEX_KW_READ + BC_INST_READ; 1414 bc_parse_noArgBuiltin(p, prev); 1415 } 1416 1417 rprn = get_token = bin_last = incdec = can_assign = false; 1418 nexprs += 1; 1419 flags &= ~(BC_PARSE_ARRAY); 1420 1421 break; 1422 } 1423 1424 case BC_LEX_KW_SCALE: 1425 { 1426 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn))) 1427 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1428 1429 bc_parse_scale(p, &prev, &can_assign, flags); 1430 rprn = get_token = bin_last = false; 1431 nexprs += 1; 1432 flags &= ~(BC_PARSE_ARRAY); 1433 1434 break; 1435 } 1436 1437 default: 1438 { 1439 #ifndef NDEBUG 1440 bc_parse_err(p, BC_ERR_PARSE_TOKEN); 1441 break; 1442 #endif // NDEBUG 1443 } 1444 } 1445 1446 if (get_token) bc_lex_next(&p->l); 1447 } 1448 1449 while (p->ops.len > ops_bgn) { 1450 1451 top = BC_PARSE_TOP_OP(p); 1452 assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; 1453 1454 if (BC_ERR(top == BC_LEX_LPAREN || top == BC_LEX_RPAREN)) 1455 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1456 1457 bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); 1458 1459 nexprs -= !BC_PARSE_OP_PREFIX(top); 1460 bc_vec_pop(&p->ops); 1461 1462 incdec = false; 1463 } 1464 1465 if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERR_PARSE_EXPR); 1466 1467 for (i = 0; i < next.len && t != next.tokens[i]; ++i); 1468 if (BC_ERR(i == next.len && !bc_parse_isDelimiter(p))) 1469 bc_parse_err(p, BC_ERR_PARSE_EXPR); 1470 1471 if (!(flags & BC_PARSE_REL) && nrelops) 1472 bc_parse_err(p, BC_ERR_POSIX_REL_POS); 1473 else if ((flags & BC_PARSE_REL) && nrelops > 1) 1474 bc_parse_err(p, BC_ERR_POSIX_MULTIREL); 1475 1476 if (!(flags & BC_PARSE_NEEDVAL) && !pfirst) { 1477 1478 if (assign) { 1479 inst = *((uchar*) bc_vec_top(&p->func->code)); 1480 inst += (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER); 1481 incdec = false; 1482 } 1483 else if (incdec && !(flags & BC_PARSE_PRINT)) { 1484 inst = *((uchar*) bc_vec_top(&p->func->code)); 1485 incdec = (inst <= BC_INST_DEC); 1486 inst = BC_INST_ASSIGN_PLUS_NO_VAL + (inst != BC_INST_INC && 1487 inst != BC_INST_ASSIGN_PLUS); 1488 } 1489 1490 if (inst >= BC_INST_ASSIGN_POWER_NO_VAL && 1491 inst <= BC_INST_ASSIGN_NO_VAL) 1492 { 1493 bc_vec_pop(&p->func->code); 1494 if (incdec) bc_parse_push(p, BC_INST_ONE); 1495 bc_parse_push(p, inst); 1496 } 1497 } 1498 1499 if ((flags & BC_PARSE_PRINT)) { 1500 if (pfirst || !assign) bc_parse_push(p, BC_INST_PRINT); 1501 } 1502 else if (!(flags & BC_PARSE_NEEDVAL) && 1503 (inst < BC_INST_ASSIGN_POWER_NO_VAL || 1504 inst > BC_INST_ASSIGN_NO_VAL)) 1505 { 1506 bc_parse_push(p, BC_INST_POP); 1507 } 1508 1509 // We want to eat newlines if newlines are not a valid ending token. 1510 // This is for spacing in things like for loop headers. 1511 for (incdec = true, i = 0; i < next.len && incdec; ++i) 1512 incdec = (next.tokens[i] != BC_LEX_NLINE); 1513 if (incdec) { 1514 while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l); 1515 } 1516 1517 return BC_PARSE_STATUS_SUCCESS; 1518 } 1519 1520 void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next) { 1521 1522 BcParseStatus s = bc_parse_expr_err(p, flags, next); 1523 1524 if (BC_ERR(s == BC_PARSE_STATUS_EMPTY_EXPR)) 1525 bc_parse_err(p, BC_ERR_PARSE_EMPTY_EXPR); 1526 } 1527 1528 void bc_parse_expr(BcParse *p, uint8_t flags) { 1529 assert(p); 1530 bc_parse_expr_status(p, flags, bc_parse_next_read); 1531 } 1532 #endif // BC_ENABLED 1533