2 * *****************************************************************************
4 * SPDX-License-Identifier: BSD-2-Clause
6 * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
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.
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.
30 * *****************************************************************************
51 static void bc_parse_else(BcParse *p);
52 static void bc_parse_stmt(BcParse *p);
53 static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
56 static bool bc_parse_inst_isLeaf(BcInst t) {
57 return (t >= BC_INST_NUM && t <= BC_INST_MAXSCALE) ||
58 #if BC_ENABLE_EXTRA_MATH
60 #endif // BC_ENABLE_EXTRA_MATH
64 static bool bc_parse_isDelimiter(const BcParse *p) {
69 if (BC_PARSE_DELIMITER(t)) return true;
71 if (t == BC_LEX_KW_ELSE) {
74 uint16_t *fptr = NULL, flags = BC_PARSE_FLAG_ELSE;
76 for (i = 0; i < p->flags.len && BC_PARSE_BLOCK_STMT(flags); ++i) {
78 fptr = bc_vec_item_rev(&p->flags, i);
81 if ((flags & BC_PARSE_FLAG_BRACE) && p->l.last != BC_LEX_RBRACE)
85 good = ((flags & BC_PARSE_FLAG_IF) != 0);
87 else if (t == BC_LEX_RBRACE) {
91 for (i = 0; !good && i < p->flags.len; ++i) {
92 uint16_t *fptr = bc_vec_item_rev(&p->flags, i);
93 good = (((*fptr) & BC_PARSE_FLAG_BRACE) != 0);
100 static void bc_parse_setLabel(BcParse *p) {
102 BcFunc *func = p->func;
103 BcInstPtr *ip = bc_vec_top(&p->exits);
106 assert(func == bc_vec_item(&p->prog->fns, p->fidx));
108 label = bc_vec_item(&func->labels, ip->idx);
109 *label = func->code.len;
111 bc_vec_pop(&p->exits);
114 static void bc_parse_createLabel(BcParse *p, size_t idx) {
115 bc_vec_push(&p->func->labels, &idx);
118 static void bc_parse_createCondLabel(BcParse *p, size_t idx) {
119 bc_parse_createLabel(p, p->func->code.len);
120 bc_vec_push(&p->conds, &idx);
123 static void bc_parse_createExitLabel(BcParse *p, size_t idx, bool loop) {
127 assert(p->func == bc_vec_item(&p->prog->fns, p->fidx));
133 bc_vec_push(&p->exits, &ip);
134 bc_parse_createLabel(p, SIZE_MAX);
137 static void bc_parse_operator(BcParse *p, BcLexType type,
138 size_t start, size_t *nexprs)
141 uchar l, r = BC_PARSE_OP_PREC(type);
142 uchar left = BC_PARSE_OP_LEFT(type);
144 while (p->ops.len > start) {
146 t = BC_PARSE_TOP_OP(p);
147 if (t == BC_LEX_LPAREN) break;
149 l = BC_PARSE_OP_PREC(t);
150 if (l >= r && (l != r || !left)) break;
152 bc_parse_push(p, BC_PARSE_TOKEN_INST(t));
154 *nexprs -= !BC_PARSE_OP_PREFIX(t);
157 bc_vec_push(&p->ops, &type);
160 static void bc_parse_rightParen(BcParse *p, size_t *nexs) {
164 while ((top = BC_PARSE_TOP_OP(p)) != BC_LEX_LPAREN) {
165 bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
167 *nexs -= !BC_PARSE_OP_PREFIX(top);
175 static void bc_parse_params(BcParse *p, uint8_t flags) {
182 for (nparams = 0; p->l.t != BC_LEX_RPAREN; ++nparams) {
184 flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
185 flags |= (BC_PARSE_ARRAY | BC_PARSE_NEEDVAL);
187 bc_parse_expr_status(p, flags, bc_parse_next_param);
189 comma = (p->l.t == BC_LEX_COMMA);
190 if (comma) bc_lex_next(&p->l);
193 if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
194 bc_parse_push(p, BC_INST_CALL);
195 bc_parse_pushIndex(p, nparams);
198 static void bc_parse_call(BcParse *p, const char *name, uint8_t flags) {
202 bc_parse_params(p, flags);
204 // We just assert this because bc_parse_params() should
205 // ensure that the next token is what it should be.
206 assert(p->l.t == BC_LEX_RPAREN);
208 // We cannot use bc_program_insertFunc() here
209 // because it will overwrite an existing function.
210 idx = bc_map_index(&p->prog->fn_map, name);
212 if (idx == BC_VEC_INVALID_IDX) {
216 idx = bc_program_insertFunc(p->prog, name);
220 assert(idx != BC_VEC_INVALID_IDX);
222 // Make sure that this pointer was not invalidated.
223 p->func = bc_vec_item(&p->prog->fns, p->fidx);
225 else idx = ((BcId*) bc_vec_item(&p->prog->fn_map, idx))->idx;
227 bc_parse_pushIndex(p, idx);
232 static void bc_parse_name(BcParse *p, BcInst *type,
233 bool *can_assign, uint8_t flags)
239 name = bc_vm_strdup(p->l.str.v);
241 BC_SETJMP_LOCKED(err);
247 if (p->l.t == BC_LEX_LBRACKET) {
251 if (p->l.t == BC_LEX_RBRACKET) {
253 if (BC_ERR(!(flags & BC_PARSE_ARRAY)))
254 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
256 *type = BC_INST_ARRAY;
261 uint8_t flags2 = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) |
264 bc_parse_expr_status(p, flags2, bc_parse_next_elem);
266 if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
267 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
269 *type = BC_INST_ARRAY_ELEM;
275 bc_parse_push(p, *type);
276 bc_parse_pushName(p, name, false);
278 else if (p->l.t == BC_LEX_LPAREN) {
280 if (BC_ERR(flags & BC_PARSE_NOCALL))
281 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
283 *type = BC_INST_CALL;
286 bc_parse_call(p, name, flags);
291 bc_parse_push(p, BC_INST_VAR);
292 bc_parse_pushName(p, name, true);
301 static void bc_parse_noArgBuiltin(BcParse *p, BcInst inst) {
304 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
307 if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
309 bc_parse_push(p, inst);
314 static void bc_parse_builtin(BcParse *p, BcLexType type,
315 uint8_t flags, BcInst *prev)
318 if (BC_ERR(p->l.t != BC_LEX_LPAREN))
319 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
323 flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
324 flags |= BC_PARSE_NEEDVAL;
325 if (type == BC_LEX_KW_LENGTH) flags |= BC_PARSE_ARRAY;
327 bc_parse_expr_status(p, flags, bc_parse_next_rel);
329 if (BC_ERR(p->l.t != BC_LEX_RPAREN))
330 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
332 *prev = type - BC_LEX_KW_LENGTH + BC_INST_LENGTH;
333 bc_parse_push(p, *prev);
338 static void bc_parse_scale(BcParse *p, BcInst *type,
339 bool *can_assign, uint8_t flags)
343 if (p->l.t != BC_LEX_LPAREN) {
344 *type = BC_INST_SCALE;
346 bc_parse_push(p, BC_INST_SCALE);
350 *type = BC_INST_SCALE_FUNC;
352 flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
353 flags |= BC_PARSE_NEEDVAL;
357 bc_parse_expr_status(p, flags, bc_parse_next_rel);
358 if (BC_ERR(p->l.t != BC_LEX_RPAREN))
359 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
361 bc_parse_push(p, BC_INST_SCALE_FUNC);
366 static void bc_parse_incdec(BcParse *p, BcInst *prev, bool *can_assign,
367 size_t *nexs, uint8_t flags)
371 BcInst etype = *prev;
372 BcLexType last = p->l.last;
374 assert(prev != NULL && can_assign != NULL);
376 if (BC_ERR(last == BC_LEX_OP_INC || last == BC_LEX_OP_DEC ||
377 last == BC_LEX_RPAREN))
379 bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
382 if (BC_PARSE_INST_VAR(etype)) {
384 if (!*can_assign) bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
386 *prev = inst = BC_INST_INC + (p->l.t != BC_LEX_OP_INC);
387 bc_parse_push(p, inst);
393 *prev = inst = BC_INST_ASSIGN_PLUS + (p->l.t != BC_LEX_OP_INC);
398 // Because we parse the next part of the expression
399 // right here, we need to increment this.
402 if (type == BC_LEX_NAME) {
403 uint8_t flags2 = flags & ~BC_PARSE_ARRAY;
404 bc_parse_name(p, prev, can_assign, flags2 | BC_PARSE_NOCALL);
406 else if (type >= BC_LEX_KW_LAST && type <= BC_LEX_KW_OBASE) {
407 bc_parse_push(p, type - BC_LEX_KW_LAST + BC_INST_LAST);
410 else if (BC_NO_ERR(type == BC_LEX_KW_SCALE)) {
414 if (BC_ERR(p->l.t == BC_LEX_LPAREN))
415 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
416 else bc_parse_push(p, BC_INST_SCALE);
418 else bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
422 bc_parse_push(p, BC_INST_ONE);
423 bc_parse_push(p, inst);
427 static void bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn,
428 bool rparen, bool binlast, size_t *nexprs)
434 type = BC_PARSE_LEAF(*prev, binlast, rparen) ? BC_LEX_OP_MINUS : BC_LEX_NEG;
435 *prev = BC_PARSE_TOKEN_INST(type);
437 // We can just push onto the op stack because this is the largest
438 // precedence operator that gets pushed. Inc/dec does not.
439 if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type);
440 else bc_parse_operator(p, type, ops_bgn, nexprs);
443 static void bc_parse_str(BcParse *p, char inst) {
444 bc_parse_addString(p);
445 bc_parse_push(p, inst);
449 static void bc_parse_print(BcParse *p) {
458 if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERROR_PARSE_PRINT);
461 if (t == BC_LEX_STR) bc_parse_str(p, BC_INST_PRINT_POP);
463 bc_parse_expr_status(p, BC_PARSE_NEEDVAL, bc_parse_next_print);
464 bc_parse_push(p, BC_INST_PRINT_POP);
467 comma = (p->l.t == BC_LEX_COMMA);
469 if (comma) bc_lex_next(&p->l);
471 if (!bc_parse_isDelimiter(p))
472 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
479 if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
482 static void bc_parse_return(BcParse *p) {
486 uchar inst = BC_INST_RET0;
488 if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
490 if (p->func->voidfn) inst = BC_INST_RET_VOID;
495 paren = t == BC_LEX_LPAREN;
497 if (bc_parse_isDelimiter(p)) bc_parse_push(p, inst);
502 s = bc_parse_expr_err(p, BC_PARSE_NEEDVAL, bc_parse_next_expr);
504 if (s == BC_PARSE_STATUS_EMPTY_EXPR) {
505 bc_parse_push(p, inst);
509 if (!paren || p->l.last != BC_LEX_RPAREN) {
510 bc_parse_err(p, BC_ERROR_POSIX_RET);
512 else if (BC_ERR(p->func->voidfn))
513 bc_parse_verr(p, BC_ERROR_PARSE_RET_VOID, p->func->name);
515 bc_parse_push(p, BC_INST_RET);
519 static void bc_parse_endBody(BcParse *p, bool brace) {
521 bool has_brace, new_else = false;
523 if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
527 assert(p->l.t == BC_LEX_RBRACE);
530 if (BC_ERR(!bc_parse_isDelimiter(p)))
531 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
534 has_brace = (BC_PARSE_BRACE(p) != 0);
537 size_t len = p->flags.len;
540 if (has_brace && !brace) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
542 loop = (BC_PARSE_LOOP_INNER(p) != 0);
544 if (loop || BC_PARSE_ELSE(p)) {
548 size_t *label = bc_vec_top(&p->conds);
550 bc_parse_push(p, BC_INST_JUMP);
551 bc_parse_pushIndex(p, *label);
553 bc_vec_pop(&p->conds);
556 bc_parse_setLabel(p);
557 bc_vec_pop(&p->flags);
559 else if (BC_PARSE_FUNC_INNER(p)) {
560 BcInst inst = (p->func->voidfn ? BC_INST_RET_VOID : BC_INST_RET0);
561 bc_parse_push(p, inst);
562 bc_parse_updateFunc(p, BC_PROG_MAIN);
563 bc_vec_pop(&p->flags);
565 else if (BC_PARSE_BRACE(p) && !BC_PARSE_IF(p)) bc_vec_pop(&p->flags);
567 // This needs to be last to parse nested if's properly.
568 if (BC_PARSE_IF(p) && (len == p->flags.len || !BC_PARSE_BRACE(p))) {
570 while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
572 bc_vec_pop(&p->flags);
576 *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_IF_END;
577 new_else = (p->l.t == BC_LEX_KW_ELSE);
579 if (new_else) bc_parse_else(p);
580 else if (!has_brace && (!BC_PARSE_IF_END(p) || brace))
583 else bc_parse_noElse(p);
586 if (brace && has_brace) brace = false;
588 } while (p->flags.len > 1 && !new_else && (!BC_PARSE_IF_END(p) || brace) &&
589 !(has_brace = (BC_PARSE_BRACE(p) != 0)));
591 if (BC_ERR(p->flags.len == 1 && brace))
592 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
593 else if (brace && BC_PARSE_BRACE(p)) {
595 uint16_t flags = BC_PARSE_TOP_FLAG(p);
597 if (!(flags & (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_LOOP_INNER)) &&
598 !(flags & (BC_PARSE_FLAG_IF | BC_PARSE_FLAG_ELSE)) &&
599 !(flags & (BC_PARSE_FLAG_IF_END)))
601 bc_vec_pop(&p->flags);
606 static void bc_parse_startBody(BcParse *p, uint16_t flags) {
608 flags |= (BC_PARSE_TOP_FLAG(p) & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));
609 flags |= BC_PARSE_FLAG_BODY;
610 bc_vec_push(&p->flags, &flags);
613 void bc_parse_noElse(BcParse *p) {
614 uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
615 *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END));
616 bc_parse_setLabel(p);
619 static void bc_parse_if(BcParse *p) {
622 uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
625 if (BC_ERR(p->l.t != BC_LEX_LPAREN))
626 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
629 bc_parse_expr_status(p, flags, bc_parse_next_rel);
630 if (BC_ERR(p->l.t != BC_LEX_RPAREN))
631 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
634 bc_parse_push(p, BC_INST_JUMP_ZERO);
636 idx = p->func->labels.len;
638 bc_parse_pushIndex(p, idx);
639 bc_parse_createExitLabel(p, idx, false);
640 bc_parse_startBody(p, BC_PARSE_FLAG_IF);
643 static void bc_parse_else(BcParse *p) {
645 size_t idx = p->func->labels.len;
647 if (BC_ERR(!BC_PARSE_IF_END(p)))
648 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
650 bc_parse_push(p, BC_INST_JUMP);
651 bc_parse_pushIndex(p, idx);
655 bc_parse_createExitLabel(p, idx, false);
656 bc_parse_startBody(p, BC_PARSE_FLAG_ELSE);
661 static void bc_parse_while(BcParse *p) {
664 uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
667 if (BC_ERR(p->l.t != BC_LEX_LPAREN))
668 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
671 bc_parse_createCondLabel(p, p->func->labels.len);
672 idx = p->func->labels.len;
673 bc_parse_createExitLabel(p, idx, true);
675 bc_parse_expr_status(p, flags, bc_parse_next_rel);
676 if (BC_ERR(p->l.t != BC_LEX_RPAREN))
677 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
680 bc_parse_push(p, BC_INST_JUMP_ZERO);
681 bc_parse_pushIndex(p, idx);
682 bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
685 static void bc_parse_for(BcParse *p) {
687 size_t cond_idx, exit_idx, body_idx, update_idx;
690 if (BC_ERR(p->l.t != BC_LEX_LPAREN))
691 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
694 if (p->l.t != BC_LEX_SCOLON)
695 bc_parse_expr_status(p, 0, bc_parse_next_for);
696 else bc_parse_err(p, BC_ERROR_POSIX_FOR);
698 if (BC_ERR(p->l.t != BC_LEX_SCOLON))
699 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
702 cond_idx = p->func->labels.len;
703 update_idx = cond_idx + 1;
704 body_idx = update_idx + 1;
705 exit_idx = body_idx + 1;
707 bc_parse_createLabel(p, p->func->code.len);
709 if (p->l.t != BC_LEX_SCOLON) {
710 uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
711 bc_parse_expr_status(p, flags, bc_parse_next_for);
715 // Set this for the next call to bc_parse_number.
716 // This is safe to set because the current token
717 // is a semicolon, which has no string requirement.
718 bc_vec_string(&p->l.str, strlen(bc_parse_const1), bc_parse_const1);
721 bc_parse_err(p, BC_ERROR_POSIX_FOR);
724 if (BC_ERR(p->l.t != BC_LEX_SCOLON))
725 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
729 bc_parse_push(p, BC_INST_JUMP_ZERO);
730 bc_parse_pushIndex(p, exit_idx);
731 bc_parse_push(p, BC_INST_JUMP);
732 bc_parse_pushIndex(p, body_idx);
734 bc_parse_createCondLabel(p, update_idx);
736 if (p->l.t != BC_LEX_RPAREN)
737 bc_parse_expr_status(p, 0, bc_parse_next_rel);
738 else bc_parse_err(p, BC_ERROR_POSIX_FOR);
740 if (BC_ERR(p->l.t != BC_LEX_RPAREN))
741 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
742 bc_parse_push(p, BC_INST_JUMP);
743 bc_parse_pushIndex(p, cond_idx);
744 bc_parse_createLabel(p, p->func->code.len);
746 bc_parse_createExitLabel(p, exit_idx, true);
748 bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
751 static void bc_parse_loopExit(BcParse *p, BcLexType type) {
756 if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
758 if (type == BC_LEX_KW_BREAK) {
760 if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
762 i = p->exits.len - 1;
763 ip = bc_vec_item(&p->exits, i);
765 while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--);
766 assert(ip != NULL && (i < p->exits.len || ip->func));
769 else i = *((size_t*) bc_vec_top(&p->conds));
771 bc_parse_push(p, BC_INST_JUMP);
772 bc_parse_pushIndex(p, i);
777 static void bc_parse_func(BcParse *p) {
779 bool comma = false, voidfn;
785 if (BC_ERR(p->l.t != BC_LEX_NAME))
786 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
788 voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME &&
789 !strcmp(p->l.str.v, "void"));
793 voidfn = (voidfn && p->l.t == BC_LEX_NAME);
796 bc_parse_err(p, BC_ERROR_POSIX_VOID);
800 if (BC_ERR(p->l.t != BC_LEX_LPAREN))
801 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
803 assert(p->prog->fns.len == p->prog->fn_map.len);
807 idx = bc_program_insertFunc(p->prog, p->l.str.v);
812 bc_parse_updateFunc(p, idx);
813 p->func->voidfn = voidfn;
817 while (p->l.t != BC_LEX_RPAREN) {
819 BcType t = BC_TYPE_VAR;
821 if (p->l.t == BC_LEX_OP_MULTIPLY) {
824 bc_parse_err(p, BC_ERROR_POSIX_REF);
827 if (BC_ERR(p->l.t != BC_LEX_NAME))
828 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
830 p->func->nparams += 1;
832 bc_vec_string(&p->buf, p->l.str.len, p->l.str.v);
836 if (p->l.t == BC_LEX_LBRACKET) {
838 if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY;
842 if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
843 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
847 else if (BC_ERR(t == BC_TYPE_REF))
848 bc_parse_verr(p, BC_ERROR_PARSE_REF_VAR, p->buf.v);
850 comma = (p->l.t == BC_LEX_COMMA);
855 bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
858 if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_FUNC);
860 flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER;
861 bc_parse_startBody(p, flags);
865 if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERROR_POSIX_BRACE);
868 static void bc_parse_auto(BcParse *p) {
872 if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
875 p->auto_part = comma = false;
876 one = p->l.t == BC_LEX_NAME;
878 while (p->l.t == BC_LEX_NAME) {
882 bc_vec_string(&p->buf, p->l.str.len - 1, p->l.str.v);
886 if (p->l.t == BC_LEX_LBRACKET) {
892 if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
893 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
897 else t = BC_TYPE_VAR;
899 comma = (p->l.t == BC_LEX_COMMA);
900 if (comma) bc_lex_next(&p->l);
902 bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
905 if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_FUNC);
906 if (BC_ERR(!one)) bc_parse_err(p, BC_ERROR_PARSE_NO_AUTO);
907 if (BC_ERR(!bc_parse_isDelimiter(p)))
908 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
911 static void bc_parse_body(BcParse *p, bool brace) {
913 uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
915 assert(flag_ptr != NULL);
916 assert(p->flags.len >= 2);
918 *flag_ptr &= ~(BC_PARSE_FLAG_BODY);
920 if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) {
922 if (BC_ERR(!brace)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
924 p->auto_part = (p->l.t != BC_LEX_KW_AUTO);
928 // Make sure this is true to not get a parse error.
934 if (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
938 size_t len = p->flags.len;
944 if (!brace && !BC_PARSE_BODY(p) && len <= p->flags.len)
945 bc_parse_endBody(p, false);
949 static void bc_parse_stmt(BcParse *p) {
953 BcLexType type = p->l.t;
955 if (type == BC_LEX_NLINE) {
959 if (type == BC_LEX_KW_AUTO) {
964 p->auto_part = false;
966 if (type != BC_LEX_KW_ELSE) {
968 if (BC_PARSE_IF_END(p)) {
970 if (p->flags.len > 1 && !BC_PARSE_BRACE(p))
971 bc_parse_endBody(p, false);
974 else if (type == BC_LEX_LBRACE) {
976 if (!BC_PARSE_BODY(p)) {
977 bc_parse_startBody(p, BC_PARSE_FLAG_BRACE);
981 *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_BRACE;
983 bc_parse_body(p, true);
988 else if (BC_PARSE_BODY(p) && !BC_PARSE_BRACE(p)) {
989 bc_parse_body(p, false);
995 flags = BC_PARSE_TOP_FLAG(p);
1001 case BC_LEX_OP_MINUS:
1002 case BC_LEX_OP_BOOL_NOT:
1006 case BC_LEX_KW_IBASE:
1007 case BC_LEX_KW_LAST:
1008 case BC_LEX_KW_LENGTH:
1009 case BC_LEX_KW_OBASE:
1010 case BC_LEX_KW_SCALE:
1011 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1012 case BC_LEX_KW_SEED:
1013 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1014 case BC_LEX_KW_SQRT:
1016 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1017 case BC_LEX_KW_IRAND:
1018 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1019 case BC_LEX_KW_READ:
1020 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1021 case BC_LEX_KW_RAND:
1022 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1023 case BC_LEX_KW_MAXIBASE:
1024 case BC_LEX_KW_MAXOBASE:
1025 case BC_LEX_KW_MAXSCALE:
1026 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1027 case BC_LEX_KW_MAXRAND:
1028 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1030 bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr);
1034 case BC_LEX_KW_ELSE:
1048 bc_parse_endBody(p, true);
1054 bc_parse_str(p, BC_INST_PRINT_STR);
1058 case BC_LEX_KW_BREAK:
1059 case BC_LEX_KW_CONTINUE:
1061 bc_parse_loopExit(p, p->l.t);
1071 case BC_LEX_KW_HALT:
1073 bc_parse_push(p, BC_INST_HALT);
1084 case BC_LEX_KW_LIMITS:
1086 bc_vm_printf("BC_LONG_BIT = %lu\n", (ulong) BC_LONG_BIT);
1087 bc_vm_printf("BC_BASE_DIGS = %lu\n", (ulong) BC_BASE_DIGS);
1088 bc_vm_printf("BC_BASE_POW = %lu\n", (ulong) BC_BASE_POW);
1089 bc_vm_printf("BC_OVERFLOW_MAX = %lu\n", (ulong) BC_NUM_BIGDIG_MAX);
1091 bc_vm_printf("BC_BASE_MAX = %lu\n", BC_MAX_OBASE);
1092 bc_vm_printf("BC_DIM_MAX = %lu\n", BC_MAX_DIM);
1093 bc_vm_printf("BC_SCALE_MAX = %lu\n", BC_MAX_SCALE);
1094 bc_vm_printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING);
1095 bc_vm_printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME);
1096 bc_vm_printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM);
1097 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1098 bc_vm_printf("BC_RAND_MAX = %lu\n", BC_MAX_RAND);
1099 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1100 bc_vm_printf("MAX Exponent = %lu\n", BC_MAX_EXP);
1101 bc_vm_printf("Number of vars = %lu\n", BC_MAX_VARS);
1108 case BC_LEX_KW_PRINT:
1114 case BC_LEX_KW_QUIT:
1116 // Quit is a compile-time command. We don't exit directly,
1117 // so the vm can clean up. Limits do the same thing.
1118 vm.status = BC_STATUS_QUIT;
1123 case BC_LEX_KW_RETURN:
1129 case BC_LEX_KW_WHILE:
1137 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
1141 if (len == p->flags.len && flags == BC_PARSE_TOP_FLAG(p)) {
1142 if (BC_ERR(!bc_parse_isDelimiter(p)))
1143 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
1146 // Make sure semicolons are eaten.
1147 while (p->l.t == BC_LEX_SCOLON) bc_lex_next(&p->l);
1150 void bc_parse_parse(BcParse *p) {
1156 if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERROR_PARSE_EOF);
1157 else if (p->l.t == BC_LEX_KW_DEFINE) {
1158 if (BC_ERR(BC_PARSE_NO_EXEC(p)))
1159 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
1162 else bc_parse_stmt(p);
1166 if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig)))
1171 static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
1174 BcInst prev = BC_INST_PRINT;
1175 uchar inst = BC_INST_INVALID;
1176 BcLexType top, t = p->l.t;
1177 size_t nexprs = 0, ops_bgn = p->ops.len;
1178 uint32_t i, nparens, nrelops;
1179 bool pfirst, rprn, done, get_token, assign, bin_last, incdec, can_assign;
1181 assert(!(flags & BC_PARSE_PRINT) || !(flags & BC_PARSE_NEEDVAL));
1183 pfirst = (p->l.t == BC_LEX_LPAREN);
1184 nparens = nrelops = 0;
1185 rprn = done = get_token = assign = incdec = can_assign = false;
1188 // We want to eat newlines if newlines are not a valid ending token.
1189 // This is for spacing in things like for loop headers.
1190 if (!(flags & BC_PARSE_NOREAD)) {
1191 while ((t = p->l.t) == BC_LEX_NLINE) bc_lex_next(&p->l);
1194 for (; !done && BC_PARSE_EXPR(t); t = p->l.t)
1201 if (BC_ERR(incdec)) bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
1202 bc_parse_incdec(p, &prev, &can_assign, &nexprs, flags);
1203 rprn = get_token = bin_last = false;
1205 flags &= ~(BC_PARSE_ARRAY);
1209 #if BC_ENABLE_EXTRA_MATH
1210 case BC_LEX_OP_TRUNC:
1212 if (BC_ERR(!BC_PARSE_LEAF(prev, bin_last, rprn)))
1213 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
1215 // I can just add the instruction because
1216 // negative will already be taken care of.
1217 bc_parse_push(p, BC_INST_TRUNC);
1218 rprn = can_assign = incdec = false;
1220 flags &= ~(BC_PARSE_ARRAY);
1223 #endif // BC_ENABLE_EXTRA_MATH
1225 case BC_LEX_OP_MINUS:
1227 bc_parse_minus(p, &prev, ops_bgn, rprn, bin_last, &nexprs);
1228 rprn = get_token = can_assign = false;
1229 bin_last = (prev == BC_INST_MINUS);
1230 if (bin_last) incdec = false;
1231 flags &= ~(BC_PARSE_ARRAY);
1235 case BC_LEX_OP_ASSIGN_POWER:
1236 case BC_LEX_OP_ASSIGN_MULTIPLY:
1237 case BC_LEX_OP_ASSIGN_DIVIDE:
1238 case BC_LEX_OP_ASSIGN_MODULUS:
1239 case BC_LEX_OP_ASSIGN_PLUS:
1240 case BC_LEX_OP_ASSIGN_MINUS:
1241 #if BC_ENABLE_EXTRA_MATH
1242 case BC_LEX_OP_ASSIGN_PLACES:
1243 case BC_LEX_OP_ASSIGN_LSHIFT:
1244 case BC_LEX_OP_ASSIGN_RSHIFT:
1245 #endif // BC_ENABLE_EXTRA_MATH
1246 case BC_LEX_OP_ASSIGN:
1248 if (!BC_PARSE_INST_VAR(prev))
1249 bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
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:
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_ERROR_PARSE_EXPR);
1276 else if (BC_ERR(BC_PARSE_PREV_PREFIX(prev) || bin_last))
1277 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
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;
1284 bin_last = !BC_PARSE_OP_PREFIX(t);
1285 flags &= ~(BC_PARSE_ARRAY);
1292 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1293 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
1296 rprn = incdec = can_assign = false;
1298 bc_vec_push(&p->ops, &t);
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;
1310 if (BC_ERR(bin_last || BC_PARSE_PREV_PREFIX(prev)))
1311 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
1321 get_token = bin_last = incdec = false;
1323 bc_parse_rightParen(p, &nexprs);
1330 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1331 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
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);
1338 flags &= ~(BC_PARSE_ARRAY);
1345 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1346 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
1352 rprn = bin_last = can_assign = false;
1353 flags &= ~(BC_PARSE_ARRAY);
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
1365 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1366 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
1368 prev = t - BC_LEX_KW_LAST + BC_INST_LAST;
1369 bc_parse_push(p, prev);
1371 get_token = can_assign = true;
1372 rprn = bin_last = false;
1374 flags &= ~(BC_PARSE_ARRAY);
1379 case BC_LEX_KW_LENGTH:
1380 case BC_LEX_KW_SQRT:
1382 #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1383 case BC_LEX_KW_IRAND:
1384 #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
1386 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1387 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
1389 bc_parse_builtin(p, t, flags, &prev);
1390 rprn = get_token = bin_last = incdec = can_assign = false;
1392 flags &= ~(BC_PARSE_ARRAY);
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
1408 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1409 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
1410 else if (t == BC_LEX_KW_READ && BC_ERR(flags & BC_PARSE_NOREAD))
1411 bc_parse_err(p, BC_ERROR_EXEC_REC_READ);
1413 prev = t - BC_LEX_KW_READ + BC_INST_READ;
1414 bc_parse_noArgBuiltin(p, prev);
1417 rprn = get_token = bin_last = incdec = can_assign = false;
1419 flags &= ~(BC_PARSE_ARRAY);
1424 case BC_LEX_KW_SCALE:
1426 if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
1427 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
1429 bc_parse_scale(p, &prev, &can_assign, flags);
1430 rprn = get_token = bin_last = false;
1432 flags &= ~(BC_PARSE_ARRAY);
1440 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
1446 if (get_token) bc_lex_next(&p->l);
1449 while (p->ops.len > ops_bgn) {
1451 top = BC_PARSE_TOP_OP(p);
1452 assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;
1454 if (BC_ERR(top == BC_LEX_LPAREN || top == BC_LEX_RPAREN))
1455 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
1457 bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
1459 nexprs -= !BC_PARSE_OP_PREFIX(top);
1460 bc_vec_pop(&p->ops);
1465 if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERROR_PARSE_EXPR);
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_ERROR_PARSE_EXPR);
1471 if (!(flags & BC_PARSE_REL) && nrelops)
1472 bc_parse_err(p, BC_ERROR_POSIX_REL_POS);
1473 else if ((flags & BC_PARSE_REL) && nrelops > 1)
1474 bc_parse_err(p, BC_ERROR_POSIX_MULTIREL);
1476 if (!(flags & BC_PARSE_NEEDVAL) && !pfirst) {
1479 inst = *((uchar*) bc_vec_top(&p->func->code));
1480 inst += (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);
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);
1490 if (inst >= BC_INST_ASSIGN_POWER_NO_VAL &&
1491 inst <= BC_INST_ASSIGN_NO_VAL)
1493 bc_vec_pop(&p->func->code);
1494 if (incdec) bc_parse_push(p, BC_INST_ONE);
1495 bc_parse_push(p, inst);
1499 if ((flags & BC_PARSE_PRINT)) {
1500 if (pfirst || !assign) bc_parse_push(p, BC_INST_PRINT);
1502 else if (!(flags & BC_PARSE_NEEDVAL) &&
1503 (inst < BC_INST_ASSIGN_POWER_NO_VAL ||
1504 inst > BC_INST_ASSIGN_NO_VAL))
1506 bc_parse_push(p, BC_INST_POP);
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);
1514 while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
1517 return BC_PARSE_STATUS_SUCCESS;
1520 void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next) {
1522 BcParseStatus s = bc_parse_expr_err(p, flags, next);
1524 if (BC_ERR(s == BC_PARSE_STATUS_EMPTY_EXPR))
1525 bc_parse_err(p, BC_ERROR_PARSE_EMPTY_EXPR);
1528 void bc_parse_expr(BcParse *p, uint8_t flags) {
1530 bc_parse_expr_status(p, flags, bc_parse_next_read);
1532 #endif // BC_ENABLED