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
bc_parse_inst_isLeaf(BcInst t)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
bc_parse_isDelimiter(const BcParse * p)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
bc_parse_setLabel(BcParse * p)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
bc_parse_createLabel(BcParse * p,size_t idx)112 static void bc_parse_createLabel(BcParse *p, size_t idx) {
113 bc_vec_push(&p->func->labels, &idx);
114 }
115
bc_parse_createCondLabel(BcParse * p,size_t idx)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
bc_parse_createExitLabel(BcParse * p,size_t idx,bool loop)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
bc_parse_operator(BcParse * p,BcLexType type,size_t start,size_t * nexprs)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
bc_parse_rightParen(BcParse * p,size_t * nexs)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
bc_parse_params(BcParse * p,uint8_t flags)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
bc_parse_call(BcParse * p,const char * name,uint8_t flags)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
bc_parse_name(BcParse * p,BcInst * type,bool * can_assign,uint8_t flags)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
bc_parse_noArgBuiltin(BcParse * p,BcInst inst)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
bc_parse_builtin(BcParse * p,BcLexType type,uint8_t flags,BcInst * prev)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
bc_parse_scale(BcParse * p,BcInst * type,bool * can_assign,uint8_t flags)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
bc_parse_incdec(BcParse * p,BcInst * prev,bool * can_assign,size_t * nexs,uint8_t flags)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
bc_parse_minus(BcParse * p,BcInst * prev,size_t ops_bgn,bool rparen,bool binlast,size_t * nexprs)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
bc_parse_str(BcParse * p,char inst)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
bc_parse_print(BcParse * p)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
bc_parse_return(BcParse * p)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
bc_parse_noElse(BcParse * p)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
bc_parse_endBody(BcParse * p,bool brace)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
bc_parse_startBody(BcParse * p,uint16_t flags)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
bc_parse_if(BcParse * p)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
bc_parse_else(BcParse * p)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
bc_parse_while(BcParse * p)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
bc_parse_for(BcParse * p)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
bc_parse_loopExit(BcParse * p,BcLexType type)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
bc_parse_func(BcParse * p)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
bc_parse_auto(BcParse * p)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
bc_parse_body(BcParse * p,bool brace)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
bc_parse_stmt(BcParse * p)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
bc_parse_parse(BcParse * p)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
bc_parse_expr_err(BcParse * p,uint8_t flags,BcParseNext next)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
bc_parse_expr_status(BcParse * p,uint8_t flags,BcParseNext next)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
bc_parse_expr(BcParse * p,uint8_t flags)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