Lines Matching +full:- +full:p
4 * SPDX-License-Identifier: BSD-2-Clause
6 * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
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,
62 static bool bc_parse_isDelimiter(const BcParse *p) { in bc_parse_isDelimiter() argument
64 BcLexType t = p->l.t; in bc_parse_isDelimiter()
74 for (i = 0; i < p->flags.len && BC_PARSE_BLOCK_STMT(flags); ++i) { in bc_parse_isDelimiter()
76 fptr = bc_vec_item_rev(&p->flags, i); in bc_parse_isDelimiter()
79 if ((flags & BC_PARSE_FLAG_BRACE) && p->l.last != BC_LEX_RBRACE) in bc_parse_isDelimiter()
89 for (i = 0; !good && i < p->flags.len; ++i) { in bc_parse_isDelimiter()
90 uint16_t *fptr = bc_vec_item_rev(&p->flags, i); in bc_parse_isDelimiter()
98 static void bc_parse_setLabel(BcParse *p) { in bc_parse_setLabel() argument
100 BcFunc *func = p->func; in bc_parse_setLabel()
101 BcInstPtr *ip = bc_vec_top(&p->exits); in bc_parse_setLabel()
104 assert(func == bc_vec_item(&p->prog->fns, p->fidx)); in bc_parse_setLabel()
106 label = bc_vec_item(&func->labels, ip->idx); in bc_parse_setLabel()
107 *label = func->code.len; in bc_parse_setLabel()
109 bc_vec_pop(&p->exits); in bc_parse_setLabel()
112 static void bc_parse_createLabel(BcParse *p, size_t idx) { in bc_parse_createLabel() argument
113 bc_vec_push(&p->func->labels, &idx); in bc_parse_createLabel()
116 static void bc_parse_createCondLabel(BcParse *p, size_t idx) { in bc_parse_createCondLabel() argument
117 bc_parse_createLabel(p, p->func->code.len); in bc_parse_createCondLabel()
118 bc_vec_push(&p->conds, &idx); in bc_parse_createCondLabel()
121 static void bc_parse_createExitLabel(BcParse *p, size_t idx, bool loop) { in bc_parse_createExitLabel() argument
125 assert(p->func == bc_vec_item(&p->prog->fns, p->fidx)); in bc_parse_createExitLabel()
131 bc_vec_push(&p->exits, &ip); in bc_parse_createExitLabel()
132 bc_parse_createLabel(p, SIZE_MAX); in bc_parse_createExitLabel()
135 static void bc_parse_operator(BcParse *p, BcLexType type, in bc_parse_operator() argument
142 while (p->ops.len > start) { in bc_parse_operator()
144 t = BC_PARSE_TOP_OP(p); in bc_parse_operator()
150 bc_parse_push(p, BC_PARSE_TOKEN_INST(t)); in bc_parse_operator()
151 bc_vec_pop(&p->ops); in bc_parse_operator()
152 *nexprs -= !BC_PARSE_OP_PREFIX(t); in bc_parse_operator()
155 bc_vec_push(&p->ops, &type); in bc_parse_operator()
158 static void bc_parse_rightParen(BcParse *p, size_t *nexs) { in bc_parse_rightParen() argument
162 while ((top = BC_PARSE_TOP_OP(p)) != BC_LEX_LPAREN) { in bc_parse_rightParen()
163 bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); in bc_parse_rightParen()
164 bc_vec_pop(&p->ops); in bc_parse_rightParen()
165 *nexs -= !BC_PARSE_OP_PREFIX(top); in bc_parse_rightParen()
168 bc_vec_pop(&p->ops); in bc_parse_rightParen()
170 bc_lex_next(&p->l); in bc_parse_rightParen()
173 static void bc_parse_params(BcParse *p, uint8_t flags) { in bc_parse_params() argument
178 bc_lex_next(&p->l); in bc_parse_params()
183 for (nparams = 0; p->l.t != BC_LEX_RPAREN; ++nparams) { in bc_parse_params()
185 bc_parse_expr_status(p, flags, bc_parse_next_param); in bc_parse_params()
187 comma = (p->l.t == BC_LEX_COMMA); in bc_parse_params()
188 if (comma) bc_lex_next(&p->l); in bc_parse_params()
191 if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_params()
192 bc_parse_push(p, BC_INST_CALL); in bc_parse_params()
193 bc_parse_pushIndex(p, nparams); in bc_parse_params()
196 static void bc_parse_call(BcParse *p, const char *name, uint8_t flags) { in bc_parse_call() argument
200 bc_parse_params(p, flags); in bc_parse_call()
204 assert(p->l.t == BC_LEX_RPAREN); in bc_parse_call()
208 idx = bc_map_index(&p->prog->fn_map, name); in bc_parse_call()
214 idx = bc_program_insertFunc(p->prog, name); in bc_parse_call()
221 p->func = bc_vec_item(&p->prog->fns, p->fidx); in bc_parse_call()
223 else idx = ((BcId*) bc_vec_item(&p->prog->fn_map, idx))->idx; in bc_parse_call()
225 bc_parse_pushIndex(p, idx); in bc_parse_call()
227 bc_lex_next(&p->l); in bc_parse_call()
230 static void bc_parse_name(BcParse *p, BcInst *type, in bc_parse_name() argument
237 name = bc_vm_strdup(p->l.str.v); in bc_parse_name()
243 bc_lex_next(&p->l); in bc_parse_name()
245 if (p->l.t == BC_LEX_LBRACKET) { in bc_parse_name()
247 bc_lex_next(&p->l); in bc_parse_name()
249 if (p->l.t == BC_LEX_RBRACKET) { in bc_parse_name()
252 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_name()
262 bc_parse_expr_status(p, flags2, bc_parse_next_elem); in bc_parse_name()
264 if (BC_ERR(p->l.t != BC_LEX_RBRACKET)) in bc_parse_name()
265 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_name()
271 bc_lex_next(&p->l); in bc_parse_name()
273 bc_parse_push(p, *type); in bc_parse_name()
274 bc_parse_pushName(p, name, false); in bc_parse_name()
276 else if (p->l.t == BC_LEX_LPAREN) { in bc_parse_name()
279 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_name()
284 bc_parse_call(p, name, flags); in bc_parse_name()
289 bc_parse_push(p, BC_INST_VAR); in bc_parse_name()
290 bc_parse_pushName(p, name, true); in bc_parse_name()
299 static void bc_parse_noArgBuiltin(BcParse *p, BcInst inst) { in bc_parse_noArgBuiltin() argument
301 bc_lex_next(&p->l); in bc_parse_noArgBuiltin()
302 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_noArgBuiltin()
304 bc_lex_next(&p->l); in bc_parse_noArgBuiltin()
305 if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_noArgBuiltin()
307 bc_parse_push(p, inst); in bc_parse_noArgBuiltin()
309 bc_lex_next(&p->l); in bc_parse_noArgBuiltin()
312 static void bc_parse_builtin(BcParse *p, BcLexType type, in bc_parse_builtin() argument
315 bc_lex_next(&p->l); in bc_parse_builtin()
316 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) in bc_parse_builtin()
317 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_builtin()
319 bc_lex_next(&p->l); in bc_parse_builtin()
325 bc_parse_expr_status(p, flags, bc_parse_next_rel); in bc_parse_builtin()
327 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) in bc_parse_builtin()
328 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_builtin()
330 *prev = type - BC_LEX_KW_LENGTH + BC_INST_LENGTH; in bc_parse_builtin()
331 bc_parse_push(p, *prev); in bc_parse_builtin()
333 bc_lex_next(&p->l); in bc_parse_builtin()
336 static void bc_parse_scale(BcParse *p, BcInst *type, in bc_parse_scale() argument
339 bc_lex_next(&p->l); in bc_parse_scale()
341 if (p->l.t != BC_LEX_LPAREN) { in bc_parse_scale()
344 bc_parse_push(p, BC_INST_SCALE); in bc_parse_scale()
353 bc_lex_next(&p->l); in bc_parse_scale()
355 bc_parse_expr_status(p, flags, bc_parse_next_rel); in bc_parse_scale()
356 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) in bc_parse_scale()
357 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_scale()
359 bc_parse_push(p, BC_INST_SCALE_FUNC); in bc_parse_scale()
361 bc_lex_next(&p->l); in bc_parse_scale()
364 static void bc_parse_incdec(BcParse *p, BcInst *prev, bool *can_assign, in bc_parse_incdec() argument
370 BcLexType last = p->l.last; in bc_parse_incdec()
377 bc_parse_err(p, BC_ERR_PARSE_ASSIGN); in bc_parse_incdec()
382 if (!*can_assign) bc_parse_err(p, BC_ERR_PARSE_ASSIGN); in bc_parse_incdec()
384 *prev = inst = BC_INST_INC + (p->l.t != BC_LEX_OP_INC); in bc_parse_incdec()
385 bc_parse_push(p, inst); in bc_parse_incdec()
386 bc_lex_next(&p->l); in bc_parse_incdec()
391 *prev = inst = BC_INST_ASSIGN_PLUS + (p->l.t != BC_LEX_OP_INC); in bc_parse_incdec()
393 bc_lex_next(&p->l); in bc_parse_incdec()
394 type = p->l.t; in bc_parse_incdec()
402 bc_parse_name(p, prev, can_assign, flags2 | BC_PARSE_NOCALL); in bc_parse_incdec()
405 bc_parse_push(p, type - BC_LEX_KW_LAST + BC_INST_LAST); in bc_parse_incdec()
406 bc_lex_next(&p->l); in bc_parse_incdec()
410 bc_lex_next(&p->l); in bc_parse_incdec()
412 if (BC_ERR(p->l.t == BC_LEX_LPAREN)) in bc_parse_incdec()
413 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_incdec()
414 else bc_parse_push(p, BC_INST_SCALE); in bc_parse_incdec()
416 else bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_incdec()
420 bc_parse_push(p, BC_INST_ONE); in bc_parse_incdec()
421 bc_parse_push(p, inst); in bc_parse_incdec()
425 static void bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, in bc_parse_minus() argument
430 bc_lex_next(&p->l); in bc_parse_minus()
437 if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type); in bc_parse_minus()
438 else bc_parse_operator(p, type, ops_bgn, nexprs); in bc_parse_minus()
441 static void bc_parse_str(BcParse *p, char inst) { in bc_parse_str() argument
442 bc_parse_addString(p); in bc_parse_str()
443 bc_parse_push(p, inst); in bc_parse_str()
444 bc_lex_next(&p->l); in bc_parse_str()
447 static void bc_parse_print(BcParse *p) { in bc_parse_print() argument
452 bc_lex_next(&p->l); in bc_parse_print()
454 t = p->l.t; in bc_parse_print()
456 if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERR_PARSE_PRINT); in bc_parse_print()
459 if (t == BC_LEX_STR) bc_parse_str(p, BC_INST_PRINT_POP); in bc_parse_print()
461 bc_parse_expr_status(p, BC_PARSE_NEEDVAL, bc_parse_next_print); in bc_parse_print()
462 bc_parse_push(p, BC_INST_PRINT_POP); in bc_parse_print()
465 comma = (p->l.t == BC_LEX_COMMA); in bc_parse_print()
467 if (comma) bc_lex_next(&p->l); in bc_parse_print()
469 if (!bc_parse_isDelimiter(p)) in bc_parse_print()
470 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_print()
474 t = p->l.t; in bc_parse_print()
477 if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_print()
480 static void bc_parse_return(BcParse *p) { in bc_parse_return() argument
486 if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_return()
488 if (p->func->voidfn) inst = BC_INST_RET_VOID; in bc_parse_return()
490 bc_lex_next(&p->l); in bc_parse_return()
492 t = p->l.t; in bc_parse_return()
495 if (bc_parse_isDelimiter(p)) bc_parse_push(p, inst); in bc_parse_return()
500 s = bc_parse_expr_err(p, BC_PARSE_NEEDVAL, bc_parse_next_expr); in bc_parse_return()
503 bc_parse_push(p, inst); in bc_parse_return()
504 bc_lex_next(&p->l); in bc_parse_return()
507 if (!paren || p->l.last != BC_LEX_RPAREN) { in bc_parse_return()
508 bc_parse_err(p, BC_ERR_POSIX_RET); in bc_parse_return()
510 else if (BC_ERR(p->func->voidfn)) in bc_parse_return()
511 bc_parse_verr(p, BC_ERR_PARSE_RET_VOID, p->func->name); in bc_parse_return()
513 bc_parse_push(p, BC_INST_RET); in bc_parse_return()
517 static void bc_parse_noElse(BcParse *p) { in bc_parse_noElse() argument
518 uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); in bc_parse_noElse()
520 bc_parse_setLabel(p); in bc_parse_noElse()
523 static void bc_parse_endBody(BcParse *p, bool brace) { in bc_parse_endBody() argument
527 if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_endBody()
531 assert(p->l.t == BC_LEX_RBRACE); in bc_parse_endBody()
533 bc_lex_next(&p->l); in bc_parse_endBody()
534 if (BC_ERR(!bc_parse_isDelimiter(p))) in bc_parse_endBody()
535 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_endBody()
538 has_brace = (BC_PARSE_BRACE(p) != 0); in bc_parse_endBody()
541 size_t len = p->flags.len; in bc_parse_endBody()
544 if (has_brace && !brace) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_endBody()
546 loop = (BC_PARSE_LOOP_INNER(p) != 0); in bc_parse_endBody()
548 if (loop || BC_PARSE_ELSE(p)) { in bc_parse_endBody()
552 size_t *label = bc_vec_top(&p->conds); in bc_parse_endBody()
554 bc_parse_push(p, BC_INST_JUMP); in bc_parse_endBody()
555 bc_parse_pushIndex(p, *label); in bc_parse_endBody()
557 bc_vec_pop(&p->conds); in bc_parse_endBody()
560 bc_parse_setLabel(p); in bc_parse_endBody()
561 bc_vec_pop(&p->flags); in bc_parse_endBody()
563 else if (BC_PARSE_FUNC_INNER(p)) { in bc_parse_endBody()
564 BcInst inst = (p->func->voidfn ? BC_INST_RET_VOID : BC_INST_RET0); in bc_parse_endBody()
565 bc_parse_push(p, inst); in bc_parse_endBody()
566 bc_parse_updateFunc(p, BC_PROG_MAIN); in bc_parse_endBody()
567 bc_vec_pop(&p->flags); in bc_parse_endBody()
569 else if (BC_PARSE_BRACE(p) && !BC_PARSE_IF(p)) bc_vec_pop(&p->flags); in bc_parse_endBody()
572 if (BC_PARSE_IF(p) && (len == p->flags.len || !BC_PARSE_BRACE(p))) { in bc_parse_endBody()
574 while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l); in bc_parse_endBody()
576 bc_vec_pop(&p->flags); in bc_parse_endBody()
580 *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_IF_END; in bc_parse_endBody()
581 new_else = (p->l.t == BC_LEX_KW_ELSE); in bc_parse_endBody()
583 if (new_else) bc_parse_else(p); in bc_parse_endBody()
584 else if (!has_brace && (!BC_PARSE_IF_END(p) || brace)) in bc_parse_endBody()
585 bc_parse_noElse(p); in bc_parse_endBody()
587 else bc_parse_noElse(p); in bc_parse_endBody()
592 } while (p->flags.len > 1 && !new_else && (!BC_PARSE_IF_END(p) || brace) && in bc_parse_endBody()
593 !(has_brace = (BC_PARSE_BRACE(p) != 0))); in bc_parse_endBody()
595 if (BC_ERR(p->flags.len == 1 && brace)) in bc_parse_endBody()
596 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_endBody()
597 else if (brace && BC_PARSE_BRACE(p)) { in bc_parse_endBody()
599 uint16_t flags = BC_PARSE_TOP_FLAG(p); in bc_parse_endBody()
605 bc_vec_pop(&p->flags); in bc_parse_endBody()
610 static void bc_parse_startBody(BcParse *p, uint16_t flags) { in bc_parse_startBody() argument
612 flags |= (BC_PARSE_TOP_FLAG(p) & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP)); in bc_parse_startBody()
614 bc_vec_push(&p->flags, &flags); in bc_parse_startBody()
617 static void bc_parse_if(BcParse *p) { in bc_parse_if() argument
622 bc_lex_next(&p->l); in bc_parse_if()
623 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) in bc_parse_if()
624 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_if()
626 bc_lex_next(&p->l); in bc_parse_if()
627 bc_parse_expr_status(p, flags, bc_parse_next_rel); in bc_parse_if()
628 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) in bc_parse_if()
629 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_if()
631 bc_lex_next(&p->l); in bc_parse_if()
632 bc_parse_push(p, BC_INST_JUMP_ZERO); in bc_parse_if()
634 idx = p->func->labels.len; in bc_parse_if()
636 bc_parse_pushIndex(p, idx); in bc_parse_if()
637 bc_parse_createExitLabel(p, idx, false); in bc_parse_if()
638 bc_parse_startBody(p, BC_PARSE_FLAG_IF); in bc_parse_if()
641 static void bc_parse_else(BcParse *p) { in bc_parse_else() argument
643 size_t idx = p->func->labels.len; in bc_parse_else()
645 if (BC_ERR(!BC_PARSE_IF_END(p))) in bc_parse_else()
646 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_else()
648 bc_parse_push(p, BC_INST_JUMP); in bc_parse_else()
649 bc_parse_pushIndex(p, idx); in bc_parse_else()
651 bc_parse_noElse(p); in bc_parse_else()
653 bc_parse_createExitLabel(p, idx, false); in bc_parse_else()
654 bc_parse_startBody(p, BC_PARSE_FLAG_ELSE); in bc_parse_else()
656 bc_lex_next(&p->l); in bc_parse_else()
659 static void bc_parse_while(BcParse *p) { in bc_parse_while() argument
664 bc_lex_next(&p->l); in bc_parse_while()
665 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) in bc_parse_while()
666 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_while()
667 bc_lex_next(&p->l); in bc_parse_while()
669 bc_parse_createCondLabel(p, p->func->labels.len); in bc_parse_while()
670 idx = p->func->labels.len; in bc_parse_while()
671 bc_parse_createExitLabel(p, idx, true); in bc_parse_while()
673 bc_parse_expr_status(p, flags, bc_parse_next_rel); in bc_parse_while()
674 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) in bc_parse_while()
675 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_while()
676 bc_lex_next(&p->l); in bc_parse_while()
678 bc_parse_push(p, BC_INST_JUMP_ZERO); in bc_parse_while()
679 bc_parse_pushIndex(p, idx); in bc_parse_while()
680 bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); in bc_parse_while()
683 static void bc_parse_for(BcParse *p) { in bc_parse_for() argument
687 bc_lex_next(&p->l); in bc_parse_for()
688 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) in bc_parse_for()
689 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_for()
690 bc_lex_next(&p->l); in bc_parse_for()
692 if (p->l.t != BC_LEX_SCOLON) in bc_parse_for()
693 bc_parse_expr_status(p, 0, bc_parse_next_for); in bc_parse_for()
694 else bc_parse_err(p, BC_ERR_POSIX_FOR); in bc_parse_for()
696 if (BC_ERR(p->l.t != BC_LEX_SCOLON)) in bc_parse_for()
697 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_for()
698 bc_lex_next(&p->l); in bc_parse_for()
700 cond_idx = p->func->labels.len; in bc_parse_for()
705 bc_parse_createLabel(p, p->func->code.len); in bc_parse_for()
707 if (p->l.t != BC_LEX_SCOLON) { in bc_parse_for()
709 bc_parse_expr_status(p, flags, bc_parse_next_for); in bc_parse_for()
716 bc_vec_string(&p->l.str, sizeof(bc_parse_one) - 1, bc_parse_one); in bc_parse_for()
717 bc_parse_number(p); in bc_parse_for()
719 bc_parse_err(p, BC_ERR_POSIX_FOR); in bc_parse_for()
722 if (BC_ERR(p->l.t != BC_LEX_SCOLON)) in bc_parse_for()
723 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_for()
725 bc_lex_next(&p->l); in bc_parse_for()
727 bc_parse_push(p, BC_INST_JUMP_ZERO); in bc_parse_for()
728 bc_parse_pushIndex(p, exit_idx); in bc_parse_for()
729 bc_parse_push(p, BC_INST_JUMP); in bc_parse_for()
730 bc_parse_pushIndex(p, body_idx); in bc_parse_for()
732 bc_parse_createCondLabel(p, update_idx); in bc_parse_for()
734 if (p->l.t != BC_LEX_RPAREN) in bc_parse_for()
735 bc_parse_expr_status(p, 0, bc_parse_next_rel); in bc_parse_for()
736 else bc_parse_err(p, BC_ERR_POSIX_FOR); in bc_parse_for()
738 if (BC_ERR(p->l.t != BC_LEX_RPAREN)) in bc_parse_for()
739 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_for()
740 bc_parse_push(p, BC_INST_JUMP); in bc_parse_for()
741 bc_parse_pushIndex(p, cond_idx); in bc_parse_for()
742 bc_parse_createLabel(p, p->func->code.len); in bc_parse_for()
744 bc_parse_createExitLabel(p, exit_idx, true); in bc_parse_for()
745 bc_lex_next(&p->l); in bc_parse_for()
746 bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); in bc_parse_for()
749 static void bc_parse_loopExit(BcParse *p, BcLexType type) { in bc_parse_loopExit() argument
754 if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_loopExit()
758 if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_loopExit()
760 i = p->exits.len - 1; in bc_parse_loopExit()
761 ip = bc_vec_item(&p->exits, i); in bc_parse_loopExit()
763 while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); in bc_parse_loopExit()
764 assert(ip != NULL && (i < p->exits.len || ip->func)); in bc_parse_loopExit()
765 i = ip->idx; in bc_parse_loopExit()
767 else i = *((size_t*) bc_vec_top(&p->conds)); in bc_parse_loopExit()
769 bc_parse_push(p, BC_INST_JUMP); in bc_parse_loopExit()
770 bc_parse_pushIndex(p, i); in bc_parse_loopExit()
772 bc_lex_next(&p->l); in bc_parse_loopExit()
775 static void bc_parse_func(BcParse *p) { in bc_parse_func() argument
781 bc_lex_next(&p->l); in bc_parse_func()
783 if (BC_ERR(p->l.t != BC_LEX_NAME)) in bc_parse_func()
784 bc_parse_err(p, BC_ERR_PARSE_FUNC); in bc_parse_func()
786 voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME && in bc_parse_func()
787 !strcmp(p->l.str.v, "void")); in bc_parse_func()
789 bc_lex_next(&p->l); in bc_parse_func()
791 voidfn = (voidfn && p->l.t == BC_LEX_NAME); in bc_parse_func()
794 bc_parse_err(p, BC_ERR_POSIX_VOID); in bc_parse_func()
795 bc_lex_next(&p->l); in bc_parse_func()
798 if (BC_ERR(p->l.t != BC_LEX_LPAREN)) in bc_parse_func()
799 bc_parse_err(p, BC_ERR_PARSE_FUNC); in bc_parse_func()
801 assert(p->prog->fns.len == p->prog->fn_map.len); in bc_parse_func()
805 idx = bc_program_insertFunc(p->prog, p->l.str.v); in bc_parse_func()
810 bc_parse_updateFunc(p, idx); in bc_parse_func()
811 p->func->voidfn = voidfn; in bc_parse_func()
813 bc_lex_next(&p->l); in bc_parse_func()
815 while (p->l.t != BC_LEX_RPAREN) { in bc_parse_func()
819 if (p->l.t == BC_LEX_OP_MULTIPLY) { in bc_parse_func()
821 bc_lex_next(&p->l); in bc_parse_func()
822 bc_parse_err(p, BC_ERR_POSIX_REF); in bc_parse_func()
825 if (BC_ERR(p->l.t != BC_LEX_NAME)) in bc_parse_func()
826 bc_parse_err(p, BC_ERR_PARSE_FUNC); in bc_parse_func()
828 p->func->nparams += 1; in bc_parse_func()
830 bc_vec_string(&p->buf, p->l.str.len, p->l.str.v); in bc_parse_func()
832 bc_lex_next(&p->l); in bc_parse_func()
834 if (p->l.t == BC_LEX_LBRACKET) { in bc_parse_func()
838 bc_lex_next(&p->l); in bc_parse_func()
840 if (BC_ERR(p->l.t != BC_LEX_RBRACKET)) in bc_parse_func()
841 bc_parse_err(p, BC_ERR_PARSE_FUNC); in bc_parse_func()
843 bc_lex_next(&p->l); in bc_parse_func()
846 bc_parse_verr(p, BC_ERR_PARSE_REF_VAR, p->buf.v); in bc_parse_func()
848 comma = (p->l.t == BC_LEX_COMMA); in bc_parse_func()
850 bc_lex_next(&p->l); in bc_parse_func()
853 bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line); in bc_parse_func()
856 if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC); in bc_parse_func()
859 bc_parse_startBody(p, flags); in bc_parse_func()
861 bc_lex_next(&p->l); in bc_parse_func()
863 if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERR_POSIX_BRACE); in bc_parse_func()
866 static void bc_parse_auto(BcParse *p) { in bc_parse_auto() argument
870 if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_auto()
871 bc_lex_next(&p->l); in bc_parse_auto()
873 p->auto_part = comma = false; in bc_parse_auto()
874 one = p->l.t == BC_LEX_NAME; in bc_parse_auto()
876 while (p->l.t == BC_LEX_NAME) { in bc_parse_auto()
880 bc_vec_string(&p->buf, p->l.str.len - 1, p->l.str.v); in bc_parse_auto()
882 bc_lex_next(&p->l); in bc_parse_auto()
884 if (p->l.t == BC_LEX_LBRACKET) { in bc_parse_auto()
888 bc_lex_next(&p->l); in bc_parse_auto()
890 if (BC_ERR(p->l.t != BC_LEX_RBRACKET)) in bc_parse_auto()
891 bc_parse_err(p, BC_ERR_PARSE_FUNC); in bc_parse_auto()
893 bc_lex_next(&p->l); in bc_parse_auto()
897 comma = (p->l.t == BC_LEX_COMMA); in bc_parse_auto()
898 if (comma) bc_lex_next(&p->l); in bc_parse_auto()
900 bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line); in bc_parse_auto()
903 if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC); in bc_parse_auto()
904 if (BC_ERR(!one)) bc_parse_err(p, BC_ERR_PARSE_NO_AUTO); in bc_parse_auto()
905 if (BC_ERR(!bc_parse_isDelimiter(p))) in bc_parse_auto()
906 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_auto()
909 static void bc_parse_body(BcParse *p, bool brace) { in bc_parse_body() argument
911 uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); in bc_parse_body()
914 assert(p->flags.len >= 2); in bc_parse_body()
920 if (BC_ERR(!brace)) bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_body()
922 p->auto_part = (p->l.t != BC_LEX_KW_AUTO); in bc_parse_body()
924 if (!p->auto_part) { in bc_parse_body()
927 p->auto_part = true; in bc_parse_body()
929 bc_parse_auto(p); in bc_parse_body()
932 if (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l); in bc_parse_body()
936 size_t len = p->flags.len; in bc_parse_body()
940 bc_parse_stmt(p); in bc_parse_body()
942 if (!brace && !BC_PARSE_BODY(p) && len <= p->flags.len) in bc_parse_body()
943 bc_parse_endBody(p, false); in bc_parse_body()
947 static void bc_parse_stmt(BcParse *p) { in bc_parse_stmt() argument
951 BcLexType type = p->l.t; in bc_parse_stmt()
954 bc_lex_next(&p->l); in bc_parse_stmt()
958 bc_parse_auto(p); in bc_parse_stmt()
962 p->auto_part = false; in bc_parse_stmt()
966 if (BC_PARSE_IF_END(p)) { in bc_parse_stmt()
967 bc_parse_noElse(p); in bc_parse_stmt()
968 if (p->flags.len > 1 && !BC_PARSE_BRACE(p)) in bc_parse_stmt()
969 bc_parse_endBody(p, false); in bc_parse_stmt()
974 if (!BC_PARSE_BODY(p)) { in bc_parse_stmt()
975 bc_parse_startBody(p, BC_PARSE_FLAG_BRACE); in bc_parse_stmt()
976 bc_lex_next(&p->l); in bc_parse_stmt()
979 *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_BRACE; in bc_parse_stmt()
980 bc_lex_next(&p->l); in bc_parse_stmt()
981 bc_parse_body(p, true); in bc_parse_stmt()
986 else if (BC_PARSE_BODY(p) && !BC_PARSE_BRACE(p)) { in bc_parse_stmt()
987 bc_parse_body(p, false); in bc_parse_stmt()
992 len = p->flags.len; in bc_parse_stmt()
993 flags = BC_PARSE_TOP_FLAG(p); in bc_parse_stmt()
1028 bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr); in bc_parse_stmt()
1034 bc_parse_else(p); in bc_parse_stmt()
1046 bc_parse_endBody(p, true); in bc_parse_stmt()
1052 bc_parse_str(p, BC_INST_PRINT_STR); in bc_parse_stmt()
1059 bc_parse_loopExit(p, p->l.t); in bc_parse_stmt()
1065 bc_parse_for(p); in bc_parse_stmt()
1071 bc_parse_push(p, BC_INST_HALT); in bc_parse_stmt()
1072 bc_lex_next(&p->l); in bc_parse_stmt()
1078 bc_parse_if(p); in bc_parse_stmt()
1101 bc_lex_next(&p->l); in bc_parse_stmt()
1108 bc_parse_print(p); in bc_parse_stmt()
1114 // Quit is a compile-time command. We don't exit directly, in bc_parse_stmt()
1123 bc_parse_return(p); in bc_parse_stmt()
1129 bc_parse_while(p); in bc_parse_stmt()
1135 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_stmt()
1139 if (len == p->flags.len && flags == BC_PARSE_TOP_FLAG(p)) { in bc_parse_stmt()
1140 if (BC_ERR(!bc_parse_isDelimiter(p))) in bc_parse_stmt()
1141 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_stmt()
1145 while (p->l.t == BC_LEX_SCOLON) bc_lex_next(&p->l); in bc_parse_stmt()
1148 void bc_parse_parse(BcParse *p) { in bc_parse_parse() argument
1150 assert(p); in bc_parse_parse()
1154 if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERR_PARSE_EOF); in bc_parse_parse()
1155 else if (p->l.t == BC_LEX_KW_DEFINE) { in bc_parse_parse()
1156 if (BC_ERR(BC_PARSE_NO_EXEC(p))) in bc_parse_parse()
1157 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_parse()
1158 bc_parse_func(p); in bc_parse_parse()
1160 else bc_parse_stmt(p); in bc_parse_parse()
1165 bc_parse_reset(p); in bc_parse_parse()
1169 static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags, in bc_parse_expr_err() argument
1174 BcLexType top, t = p->l.t; in bc_parse_expr_err()
1175 size_t nexprs = 0, ops_bgn = p->ops.len; in bc_parse_expr_err()
1181 pfirst = (p->l.t == BC_LEX_LPAREN); in bc_parse_expr_err()
1189 while ((t = p->l.t) == BC_LEX_NLINE) bc_lex_next(&p->l); in bc_parse_expr_err()
1192 for (; !done && BC_PARSE_EXPR(t); t = p->l.t) in bc_parse_expr_err()
1199 if (BC_ERR(incdec)) bc_parse_err(p, BC_ERR_PARSE_ASSIGN); in bc_parse_expr_err()
1200 bc_parse_incdec(p, &prev, &can_assign, &nexprs, flags); in bc_parse_expr_err()
1211 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_expr_err()
1215 bc_parse_push(p, BC_INST_TRUNC); in bc_parse_expr_err()
1225 bc_parse_minus(p, &prev, ops_bgn, rprn, bin_last, &nexprs); in bc_parse_expr_err()
1247 bc_parse_err(p, BC_ERR_PARSE_ASSIGN); in bc_parse_expr_err()
1273 if (BC_ERR(!bin_last && !BC_PARSE_OP_PREFIX(p->l.last))) in bc_parse_expr_err()
1274 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1277 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1281 bc_parse_operator(p, t, ops_bgn, &nexprs); in bc_parse_expr_err()
1293 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1298 bc_vec_push(&p->ops, &t); in bc_parse_expr_err()
1307 if (BC_ERR(p->l.last == BC_LEX_LPAREN)) in bc_parse_expr_err()
1311 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1319 nparens -= 1; in bc_parse_expr_err()
1323 bc_parse_rightParen(p, &nexprs); in bc_parse_expr_err()
1331 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1334 bc_parse_name(p, &prev, &can_assign, in bc_parse_expr_err()
1346 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1348 bc_parse_number(p); in bc_parse_expr_err()
1366 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1368 prev = t - BC_LEX_KW_LAST + BC_INST_LAST; in bc_parse_expr_err()
1369 bc_parse_push(p, prev); in bc_parse_expr_err()
1387 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1389 bc_parse_builtin(p, t, flags, &prev); in bc_parse_expr_err()
1409 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1411 bc_parse_err(p, BC_ERR_EXEC_REC_READ); in bc_parse_expr_err()
1413 prev = t - BC_LEX_KW_READ + BC_INST_READ; in bc_parse_expr_err()
1414 bc_parse_noArgBuiltin(p, prev); in bc_parse_expr_err()
1427 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1429 bc_parse_scale(p, &prev, &can_assign, flags); in bc_parse_expr_err()
1440 bc_parse_err(p, BC_ERR_PARSE_TOKEN); in bc_parse_expr_err()
1446 if (get_token) bc_lex_next(&p->l); in bc_parse_expr_err()
1449 while (p->ops.len > ops_bgn) { in bc_parse_expr_err()
1451 top = BC_PARSE_TOP_OP(p); in bc_parse_expr_err()
1455 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1457 bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); in bc_parse_expr_err()
1459 nexprs -= !BC_PARSE_OP_PREFIX(top); in bc_parse_expr_err()
1460 bc_vec_pop(&p->ops); in bc_parse_expr_err()
1465 if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1468 if (BC_ERR(i == next.len && !bc_parse_isDelimiter(p))) in bc_parse_expr_err()
1469 bc_parse_err(p, BC_ERR_PARSE_EXPR); in bc_parse_expr_err()
1472 bc_parse_err(p, BC_ERR_POSIX_REL_POS); in bc_parse_expr_err()
1474 bc_parse_err(p, BC_ERR_POSIX_MULTIREL); in bc_parse_expr_err()
1479 inst = *((uchar*) bc_vec_top(&p->func->code)); in bc_parse_expr_err()
1480 inst += (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER); in bc_parse_expr_err()
1484 inst = *((uchar*) bc_vec_top(&p->func->code)); in bc_parse_expr_err()
1493 bc_vec_pop(&p->func->code); in bc_parse_expr_err()
1494 if (incdec) bc_parse_push(p, BC_INST_ONE); in bc_parse_expr_err()
1495 bc_parse_push(p, inst); in bc_parse_expr_err()
1500 if (pfirst || !assign) bc_parse_push(p, BC_INST_PRINT); in bc_parse_expr_err()
1506 bc_parse_push(p, BC_INST_POP); in bc_parse_expr_err()
1514 while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l); in bc_parse_expr_err()
1520 void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next) { in bc_parse_expr_status() argument
1522 BcParseStatus s = bc_parse_expr_err(p, flags, next); in bc_parse_expr_status()
1525 bc_parse_err(p, BC_ERR_PARSE_EMPTY_EXPR); in bc_parse_expr_status()
1528 void bc_parse_expr(BcParse *p, uint8_t flags) { in bc_parse_expr() argument
1529 assert(p); in bc_parse_expr()
1530 bc_parse_expr_status(p, flags, bc_parse_next_read); in bc_parse_expr()