]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bc/src/bc/parse.c
Upgrade to version 3.1.4
[FreeBSD/FreeBSD.git] / contrib / bc / src / bc / parse.c
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2020 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 <lex.h>
46 #include <parse.h>
47 #include <bc.h>
48 #include <num.h>
49 #include <vm.h>
50
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,
54                                        BcParseNext next);
55
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
59                 t == BC_INST_TRUNC ||
60 #endif // BC_ENABLE_EXTRA_MATH
61                 t <= BC_INST_DEC;
62 }
63
64 static bool bc_parse_isDelimiter(const BcParse *p) {
65
66         BcLexType t = p->l.t;
67         bool good = false;
68
69         if (BC_PARSE_DELIMITER(t)) return true;
70
71         if (t == BC_LEX_KW_ELSE) {
72
73                 size_t i;
74                 uint16_t *fptr = NULL, flags = BC_PARSE_FLAG_ELSE;
75
76                 for (i = 0; i < p->flags.len && BC_PARSE_BLOCK_STMT(flags); ++i) {
77
78                         fptr = bc_vec_item_rev(&p->flags, i);
79                         flags = *fptr;
80
81                         if ((flags & BC_PARSE_FLAG_BRACE) && p->l.last != BC_LEX_RBRACE)
82                                 return false;
83                 }
84
85                 good = ((flags & BC_PARSE_FLAG_IF) != 0);
86         }
87         else if (t == BC_LEX_RBRACE) {
88
89                 size_t i;
90
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);
94                 }
95         }
96
97         return good;
98 }
99
100 static void bc_parse_setLabel(BcParse *p) {
101
102         BcFunc *func = p->func;
103         BcInstPtr *ip = bc_vec_top(&p->exits);
104         size_t *label;
105
106         assert(func == bc_vec_item(&p->prog->fns, p->fidx));
107
108         label = bc_vec_item(&func->labels, ip->idx);
109         *label = func->code.len;
110
111         bc_vec_pop(&p->exits);
112 }
113
114 static void bc_parse_createLabel(BcParse *p, size_t idx) {
115         bc_vec_push(&p->func->labels, &idx);
116 }
117
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);
121 }
122
123 static void bc_parse_createExitLabel(BcParse *p, size_t idx, bool loop) {
124
125         BcInstPtr ip;
126
127         assert(p->func == bc_vec_item(&p->prog->fns, p->fidx));
128
129         ip.func = loop;
130         ip.idx = idx;
131         ip.len = 0;
132
133         bc_vec_push(&p->exits, &ip);
134         bc_parse_createLabel(p, SIZE_MAX);
135 }
136
137 static void bc_parse_operator(BcParse *p, BcLexType type,
138                               size_t start, size_t *nexprs)
139 {
140         BcLexType t;
141         uchar l, r = BC_PARSE_OP_PREC(type);
142         uchar left = BC_PARSE_OP_LEFT(type);
143
144         while (p->ops.len > start) {
145
146                 t = BC_PARSE_TOP_OP(p);
147                 if (t == BC_LEX_LPAREN) break;
148
149                 l = BC_PARSE_OP_PREC(t);
150                 if (l >= r && (l != r || !left)) break;
151
152                 bc_parse_push(p, BC_PARSE_TOKEN_INST(t));
153                 bc_vec_pop(&p->ops);
154                 *nexprs -= !BC_PARSE_OP_PREFIX(t);
155         }
156
157         bc_vec_push(&p->ops, &type);
158 }
159
160 static void bc_parse_rightParen(BcParse *p, size_t *nexs) {
161
162         BcLexType top;
163
164         while ((top = BC_PARSE_TOP_OP(p)) != BC_LEX_LPAREN) {
165                 bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
166                 bc_vec_pop(&p->ops);
167                 *nexs -= !BC_PARSE_OP_PREFIX(top);
168         }
169
170         bc_vec_pop(&p->ops);
171
172         bc_lex_next(&p->l);
173 }
174
175 static void bc_parse_params(BcParse *p, uint8_t flags) {
176
177         bool comma = false;
178         size_t nparams;
179
180         bc_lex_next(&p->l);
181
182         flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
183         flags |= (BC_PARSE_ARRAY | BC_PARSE_NEEDVAL);
184
185         for (nparams = 0; p->l.t != BC_LEX_RPAREN; ++nparams) {
186
187                 bc_parse_expr_status(p, flags, bc_parse_next_param);
188
189                 comma = (p->l.t == BC_LEX_COMMA);
190                 if (comma) bc_lex_next(&p->l);
191         }
192
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);
196 }
197
198 static void bc_parse_call(BcParse *p, const char *name, uint8_t flags) {
199
200         size_t idx;
201
202         bc_parse_params(p, flags);
203
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);
207
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);
211
212         if (idx == BC_VEC_INVALID_IDX) {
213
214                 BC_SIG_LOCK;
215
216                 idx = bc_program_insertFunc(p->prog, name);
217
218                 BC_SIG_UNLOCK;
219
220                 assert(idx != BC_VEC_INVALID_IDX);
221
222                 // Make sure that this pointer was not invalidated.
223                 p->func = bc_vec_item(&p->prog->fns, p->fidx);
224         }
225         else idx = ((BcId*) bc_vec_item(&p->prog->fn_map, idx))->idx;
226
227         bc_parse_pushIndex(p, idx);
228
229         bc_lex_next(&p->l);
230 }
231
232 static void bc_parse_name(BcParse *p, BcInst *type,
233                           bool *can_assign, uint8_t flags)
234 {
235         char *name;
236
237         BC_SIG_LOCK;
238
239         name = bc_vm_strdup(p->l.str.v);
240
241         BC_SETJMP_LOCKED(err);
242
243         BC_SIG_UNLOCK;
244
245         bc_lex_next(&p->l);
246
247         if (p->l.t == BC_LEX_LBRACKET) {
248
249                 bc_lex_next(&p->l);
250
251                 if (p->l.t == BC_LEX_RBRACKET) {
252
253                         if (BC_ERR(!(flags & BC_PARSE_ARRAY)))
254                                 bc_parse_err(p, BC_ERROR_PARSE_EXPR);
255
256                         *type = BC_INST_ARRAY;
257                         *can_assign = false;
258                 }
259                 else {
260
261                         uint8_t flags2 = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) |
262                             BC_PARSE_NEEDVAL;
263
264                         bc_parse_expr_status(p, flags2, bc_parse_next_elem);
265
266                         if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
267                                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
268
269                         *type = BC_INST_ARRAY_ELEM;
270                         *can_assign = true;
271                 }
272
273                 bc_lex_next(&p->l);
274
275                 bc_parse_push(p, *type);
276                 bc_parse_pushName(p, name, false);
277         }
278         else if (p->l.t == BC_LEX_LPAREN) {
279
280                 if (BC_ERR(flags & BC_PARSE_NOCALL))
281                         bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
282
283                 *type = BC_INST_CALL;
284                 *can_assign = false;
285
286                 bc_parse_call(p, name, flags);
287         }
288         else {
289                 *type = BC_INST_VAR;
290                 *can_assign = true;
291                 bc_parse_push(p, BC_INST_VAR);
292                 bc_parse_pushName(p, name, true);
293         }
294
295 err:
296         BC_SIG_MAYLOCK;
297         free(name);
298         BC_LONGJMP_CONT;
299 }
300
301 static void bc_parse_noArgBuiltin(BcParse *p, BcInst inst) {
302
303         bc_lex_next(&p->l);
304         if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
305
306         bc_lex_next(&p->l);
307         if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
308
309         bc_parse_push(p, inst);
310
311         bc_lex_next(&p->l);
312 }
313
314 static void bc_parse_builtin(BcParse *p, BcLexType type,
315                              uint8_t flags, BcInst *prev)
316 {
317         bc_lex_next(&p->l);
318         if (BC_ERR(p->l.t != BC_LEX_LPAREN))
319                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
320
321         bc_lex_next(&p->l);
322
323         flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
324         flags |= BC_PARSE_NEEDVAL;
325         if (type == BC_LEX_KW_LENGTH) flags |= BC_PARSE_ARRAY;
326
327         bc_parse_expr_status(p, flags, bc_parse_next_rel);
328
329         if (BC_ERR(p->l.t != BC_LEX_RPAREN))
330                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
331
332         *prev = type - BC_LEX_KW_LENGTH + BC_INST_LENGTH;
333         bc_parse_push(p, *prev);
334
335         bc_lex_next(&p->l);
336 }
337
338 static void bc_parse_scale(BcParse *p, BcInst *type,
339                                bool *can_assign, uint8_t flags)
340 {
341         bc_lex_next(&p->l);
342
343         if (p->l.t != BC_LEX_LPAREN) {
344                 *type = BC_INST_SCALE;
345                 *can_assign = true;
346                 bc_parse_push(p, BC_INST_SCALE);
347                 return;
348         }
349
350         *type = BC_INST_SCALE_FUNC;
351         *can_assign = false;
352         flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
353         flags |= BC_PARSE_NEEDVAL;
354
355         bc_lex_next(&p->l);
356
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);
360
361         bc_parse_push(p, BC_INST_SCALE_FUNC);
362
363         bc_lex_next(&p->l);
364 }
365
366 static void bc_parse_incdec(BcParse *p, BcInst *prev, bool *can_assign,
367                             size_t *nexs, uint8_t flags)
368 {
369         BcLexType type;
370         uchar inst;
371         BcInst etype = *prev;
372         BcLexType last = p->l.last;
373
374         assert(prev != NULL && can_assign != NULL);
375
376         if (BC_ERR(last == BC_LEX_OP_INC || last == BC_LEX_OP_DEC ||
377                    last == BC_LEX_RPAREN))
378         {
379                 bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
380         }
381
382         if (BC_PARSE_INST_VAR(etype)) {
383
384                 if (!*can_assign) bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
385
386                 *prev = inst = BC_INST_INC + (p->l.t != BC_LEX_OP_INC);
387                 bc_parse_push(p, inst);
388                 bc_lex_next(&p->l);
389                 *can_assign = false;
390         }
391         else {
392
393                 *prev = inst = BC_INST_ASSIGN_PLUS + (p->l.t != BC_LEX_OP_INC);
394
395                 bc_lex_next(&p->l);
396                 type = p->l.t;
397
398                 // Because we parse the next part of the expression
399                 // right here, we need to increment this.
400                 *nexs = *nexs + 1;
401
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);
405                 }
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);
408                         bc_lex_next(&p->l);
409                 }
410                 else if (BC_NO_ERR(type == BC_LEX_KW_SCALE)) {
411
412                         bc_lex_next(&p->l);
413
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);
417                 }
418                 else bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
419
420                 *can_assign = false;
421
422                 bc_parse_push(p, BC_INST_ONE);
423                 bc_parse_push(p, inst);
424         }
425 }
426
427 static void bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn,
428                            bool rparen, bool binlast, size_t *nexprs)
429 {
430         BcLexType type;
431
432         bc_lex_next(&p->l);
433
434         type = BC_PARSE_LEAF(*prev, binlast, rparen) ? BC_LEX_OP_MINUS : BC_LEX_NEG;
435         *prev = BC_PARSE_TOKEN_INST(type);
436
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);
441 }
442
443 static void bc_parse_str(BcParse *p, char inst) {
444         bc_parse_addString(p);
445         bc_parse_push(p, inst);
446         bc_lex_next(&p->l);
447 }
448
449 static void bc_parse_print(BcParse *p) {
450
451         BcLexType t;
452         bool comma = false;
453
454         bc_lex_next(&p->l);
455
456         t = p->l.t;
457
458         if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERROR_PARSE_PRINT);
459
460         do {
461                 if (t == BC_LEX_STR) bc_parse_str(p, BC_INST_PRINT_POP);
462                 else {
463                         bc_parse_expr_status(p, BC_PARSE_NEEDVAL, bc_parse_next_print);
464                         bc_parse_push(p, BC_INST_PRINT_POP);
465                 }
466
467                 comma = (p->l.t == BC_LEX_COMMA);
468
469                 if (comma) bc_lex_next(&p->l);
470                 else {
471                         if (!bc_parse_isDelimiter(p))
472                                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
473                         else break;
474                 }
475
476                 t = p->l.t;
477         } while (true);
478
479         if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
480 }
481
482 static void bc_parse_return(BcParse *p) {
483
484         BcLexType t;
485         bool paren;
486         uchar inst = BC_INST_RET0;
487
488         if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
489
490         if (p->func->voidfn) inst = BC_INST_RET_VOID;
491
492         bc_lex_next(&p->l);
493
494         t = p->l.t;
495         paren = t == BC_LEX_LPAREN;
496
497         if (bc_parse_isDelimiter(p)) bc_parse_push(p, inst);
498         else {
499
500                 BcParseStatus s;
501
502                 s = bc_parse_expr_err(p, BC_PARSE_NEEDVAL, bc_parse_next_expr);
503
504                 if (s == BC_PARSE_STATUS_EMPTY_EXPR) {
505                         bc_parse_push(p, inst);
506                         bc_lex_next(&p->l);
507                 }
508
509                 if (!paren || p->l.last != BC_LEX_RPAREN) {
510                         bc_parse_err(p, BC_ERROR_POSIX_RET);
511                 }
512                 else if (BC_ERR(p->func->voidfn))
513                         bc_parse_verr(p, BC_ERROR_PARSE_RET_VOID, p->func->name);
514
515                 bc_parse_push(p, BC_INST_RET);
516         }
517 }
518
519 static void bc_parse_noElse(BcParse *p) {
520         uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
521         *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END));
522         bc_parse_setLabel(p);
523 }
524
525 static void bc_parse_endBody(BcParse *p, bool brace) {
526
527         bool has_brace, new_else = false;
528
529         if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
530
531         if (brace) {
532
533                 assert(p->l.t == BC_LEX_RBRACE);
534
535                 bc_lex_next(&p->l);
536                 if (BC_ERR(!bc_parse_isDelimiter(p)))
537                         bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
538         }
539
540         has_brace = (BC_PARSE_BRACE(p) != 0);
541
542         do {
543                 size_t len = p->flags.len;
544                 bool loop;
545
546                 if (has_brace && !brace) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
547
548                 loop = (BC_PARSE_LOOP_INNER(p) != 0);
549
550                 if (loop || BC_PARSE_ELSE(p)) {
551
552                         if (loop) {
553
554                                 size_t *label = bc_vec_top(&p->conds);
555
556                                 bc_parse_push(p, BC_INST_JUMP);
557                                 bc_parse_pushIndex(p, *label);
558
559                                 bc_vec_pop(&p->conds);
560                         }
561
562                         bc_parse_setLabel(p);
563                         bc_vec_pop(&p->flags);
564                 }
565                 else if (BC_PARSE_FUNC_INNER(p)) {
566                         BcInst inst = (p->func->voidfn ? BC_INST_RET_VOID : BC_INST_RET0);
567                         bc_parse_push(p, inst);
568                         bc_parse_updateFunc(p, BC_PROG_MAIN);
569                         bc_vec_pop(&p->flags);
570                 }
571                 else if (BC_PARSE_BRACE(p) && !BC_PARSE_IF(p)) bc_vec_pop(&p->flags);
572
573                 // This needs to be last to parse nested if's properly.
574                 if (BC_PARSE_IF(p) && (len == p->flags.len || !BC_PARSE_BRACE(p))) {
575
576                         while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
577
578                         bc_vec_pop(&p->flags);
579
580                         if (!BC_S) {
581
582                                 *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_IF_END;
583                                 new_else = (p->l.t == BC_LEX_KW_ELSE);
584
585                                 if (new_else) bc_parse_else(p);
586                                 else if (!has_brace && (!BC_PARSE_IF_END(p) || brace))
587                                         bc_parse_noElse(p);
588                         }
589                         else bc_parse_noElse(p);
590                 }
591
592                 if (brace && has_brace) brace = false;
593
594         } while (p->flags.len > 1 && !new_else && (!BC_PARSE_IF_END(p) || brace) &&
595                  !(has_brace = (BC_PARSE_BRACE(p) != 0)));
596
597         if (BC_ERR(p->flags.len == 1 && brace))
598                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
599         else if (brace && BC_PARSE_BRACE(p)) {
600
601                 uint16_t flags = BC_PARSE_TOP_FLAG(p);
602
603                 if (!(flags & (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_LOOP_INNER)) &&
604                     !(flags & (BC_PARSE_FLAG_IF | BC_PARSE_FLAG_ELSE)) &&
605                     !(flags & (BC_PARSE_FLAG_IF_END)))
606                 {
607                         bc_vec_pop(&p->flags);
608                 }
609         }
610 }
611
612 static void bc_parse_startBody(BcParse *p, uint16_t flags) {
613         assert(flags);
614         flags |= (BC_PARSE_TOP_FLAG(p) & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));
615         flags |= BC_PARSE_FLAG_BODY;
616         bc_vec_push(&p->flags, &flags);
617 }
618
619 static void bc_parse_if(BcParse *p) {
620
621         size_t idx;
622         uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
623
624         bc_lex_next(&p->l);
625         if (BC_ERR(p->l.t != BC_LEX_LPAREN))
626                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
627
628         bc_lex_next(&p->l);
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);
632
633         bc_lex_next(&p->l);
634         bc_parse_push(p, BC_INST_JUMP_ZERO);
635
636         idx = p->func->labels.len;
637
638         bc_parse_pushIndex(p, idx);
639         bc_parse_createExitLabel(p, idx, false);
640         bc_parse_startBody(p, BC_PARSE_FLAG_IF);
641 }
642
643 static void bc_parse_else(BcParse *p) {
644
645         size_t idx = p->func->labels.len;
646
647         if (BC_ERR(!BC_PARSE_IF_END(p)))
648                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
649
650         bc_parse_push(p, BC_INST_JUMP);
651         bc_parse_pushIndex(p, idx);
652
653         bc_parse_noElse(p);
654
655         bc_parse_createExitLabel(p, idx, false);
656         bc_parse_startBody(p, BC_PARSE_FLAG_ELSE);
657
658         bc_lex_next(&p->l);
659 }
660
661 static void bc_parse_while(BcParse *p) {
662
663         size_t idx;
664         uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
665
666         bc_lex_next(&p->l);
667         if (BC_ERR(p->l.t != BC_LEX_LPAREN))
668                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
669         bc_lex_next(&p->l);
670
671         bc_parse_createCondLabel(p, p->func->labels.len);
672         idx = p->func->labels.len;
673         bc_parse_createExitLabel(p, idx, true);
674
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);
678         bc_lex_next(&p->l);
679
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);
683 }
684
685 static void bc_parse_for(BcParse *p) {
686
687         size_t cond_idx, exit_idx, body_idx, update_idx;
688
689         bc_lex_next(&p->l);
690         if (BC_ERR(p->l.t != BC_LEX_LPAREN))
691                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
692         bc_lex_next(&p->l);
693
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);
697
698         if (BC_ERR(p->l.t != BC_LEX_SCOLON))
699                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
700         bc_lex_next(&p->l);
701
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;
706
707         bc_parse_createLabel(p, p->func->code.len);
708
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);
712         }
713         else {
714
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);
719                 bc_parse_number(p);
720
721                 bc_parse_err(p, BC_ERROR_POSIX_FOR);
722         }
723
724         if (BC_ERR(p->l.t != BC_LEX_SCOLON))
725                 bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
726
727         bc_lex_next(&p->l);
728
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);
733
734         bc_parse_createCondLabel(p, update_idx);
735
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);
739
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);
745
746         bc_parse_createExitLabel(p, exit_idx, true);
747         bc_lex_next(&p->l);
748         bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
749 }
750
751 static void bc_parse_loopExit(BcParse *p, BcLexType type) {
752
753         size_t i;
754         BcInstPtr *ip;
755
756         if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
757
758         if (type == BC_LEX_KW_BREAK) {
759
760                 if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
761
762                 i = p->exits.len - 1;
763                 ip = bc_vec_item(&p->exits, i);
764
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));
767                 i = ip->idx;
768         }
769         else i = *((size_t*) bc_vec_top(&p->conds));
770
771         bc_parse_push(p, BC_INST_JUMP);
772         bc_parse_pushIndex(p, i);
773
774         bc_lex_next(&p->l);
775 }
776
777 static void bc_parse_func(BcParse *p) {
778
779         bool comma = false, voidfn;
780         uint16_t flags;
781         size_t idx;
782
783         bc_lex_next(&p->l);
784
785         if (BC_ERR(p->l.t != BC_LEX_NAME))
786                 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
787
788         voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME &&
789                   !strcmp(p->l.str.v, "void"));
790
791         bc_lex_next(&p->l);
792
793         voidfn = (voidfn && p->l.t == BC_LEX_NAME);
794
795         if (voidfn) {
796                 bc_parse_err(p, BC_ERROR_POSIX_VOID);
797                 bc_lex_next(&p->l);
798         }
799
800         if (BC_ERR(p->l.t != BC_LEX_LPAREN))
801                 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
802
803         assert(p->prog->fns.len == p->prog->fn_map.len);
804
805         BC_SIG_LOCK;
806
807         idx = bc_program_insertFunc(p->prog, p->l.str.v);
808
809         BC_SIG_UNLOCK;
810
811         assert(idx);
812         bc_parse_updateFunc(p, idx);
813         p->func->voidfn = voidfn;
814
815         bc_lex_next(&p->l);
816
817         while (p->l.t != BC_LEX_RPAREN) {
818
819                 BcType t = BC_TYPE_VAR;
820
821                 if (p->l.t == BC_LEX_OP_MULTIPLY) {
822                         t = BC_TYPE_REF;
823                         bc_lex_next(&p->l);
824                         bc_parse_err(p, BC_ERROR_POSIX_REF);
825                 }
826
827                 if (BC_ERR(p->l.t != BC_LEX_NAME))
828                         bc_parse_err(p, BC_ERROR_PARSE_FUNC);
829
830                 p->func->nparams += 1;
831
832                 bc_vec_string(&p->buf, p->l.str.len, p->l.str.v);
833
834                 bc_lex_next(&p->l);
835
836                 if (p->l.t == BC_LEX_LBRACKET) {
837
838                         if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY;
839
840                         bc_lex_next(&p->l);
841
842                         if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
843                                 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
844
845                         bc_lex_next(&p->l);
846                 }
847                 else if (BC_ERR(t == BC_TYPE_REF))
848                         bc_parse_verr(p, BC_ERROR_PARSE_REF_VAR, p->buf.v);
849
850                 comma = (p->l.t == BC_LEX_COMMA);
851                 if (comma) {
852                         bc_lex_next(&p->l);
853                 }
854
855                 bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
856         }
857
858         if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_FUNC);
859
860         flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER;
861         bc_parse_startBody(p, flags);
862
863         bc_lex_next(&p->l);
864
865         if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERROR_POSIX_BRACE);
866 }
867
868 static void bc_parse_auto(BcParse *p) {
869
870         bool comma, one;
871
872         if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
873         bc_lex_next(&p->l);
874
875         p->auto_part = comma = false;
876         one = p->l.t == BC_LEX_NAME;
877
878         while (p->l.t == BC_LEX_NAME) {
879
880                 BcType t;
881
882                 bc_vec_string(&p->buf, p->l.str.len - 1, p->l.str.v);
883
884                 bc_lex_next(&p->l);
885
886                 if (p->l.t == BC_LEX_LBRACKET) {
887
888                         t = BC_TYPE_ARRAY;
889
890                         bc_lex_next(&p->l);
891
892                         if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
893                                 bc_parse_err(p, BC_ERROR_PARSE_FUNC);
894
895                         bc_lex_next(&p->l);
896                 }
897                 else t = BC_TYPE_VAR;
898
899                 comma = (p->l.t == BC_LEX_COMMA);
900                 if (comma) bc_lex_next(&p->l);
901
902                 bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
903         }
904
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);
909 }
910
911 static void bc_parse_body(BcParse *p, bool brace) {
912
913         uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
914
915         assert(flag_ptr != NULL);
916         assert(p->flags.len >= 2);
917
918         *flag_ptr &= ~(BC_PARSE_FLAG_BODY);
919
920         if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) {
921
922                 if (BC_ERR(!brace)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
923
924                 p->auto_part = (p->l.t != BC_LEX_KW_AUTO);
925
926                 if (!p->auto_part) {
927
928                         // Make sure this is true to not get a parse error.
929                         p->auto_part = true;
930
931                         bc_parse_auto(p);
932                 }
933
934                 if (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
935         }
936         else {
937
938                 size_t len = p->flags.len;
939
940                 assert(*flag_ptr);
941
942                 bc_parse_stmt(p);
943
944                 if (!brace && !BC_PARSE_BODY(p) && len <= p->flags.len)
945                         bc_parse_endBody(p, false);
946         }
947 }
948
949 static void bc_parse_stmt(BcParse *p) {
950
951         size_t len;
952         uint16_t flags;
953         BcLexType type = p->l.t;
954
955         if (type == BC_LEX_NLINE) {
956                 bc_lex_next(&p->l);
957                 return;
958         }
959         if (type == BC_LEX_KW_AUTO) {
960                 bc_parse_auto(p);
961                 return;
962         }
963
964         p->auto_part = false;
965
966         if (type != BC_LEX_KW_ELSE) {
967
968                 if (BC_PARSE_IF_END(p)) {
969                         bc_parse_noElse(p);
970                         if (p->flags.len > 1 && !BC_PARSE_BRACE(p))
971                                 bc_parse_endBody(p, false);
972                         return;
973                 }
974                 else if (type == BC_LEX_LBRACE) {
975
976                         if (!BC_PARSE_BODY(p)) {
977                                 bc_parse_startBody(p, BC_PARSE_FLAG_BRACE);
978                                 bc_lex_next(&p->l);
979                         }
980                         else {
981                                 *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_BRACE;
982                                 bc_lex_next(&p->l);
983                                 bc_parse_body(p, true);
984                         }
985
986                         return;
987                 }
988                 else if (BC_PARSE_BODY(p) && !BC_PARSE_BRACE(p)) {
989                         bc_parse_body(p, false);
990                         return;
991                 }
992         }
993
994         len = p->flags.len;
995         flags = BC_PARSE_TOP_FLAG(p);
996
997         switch (type) {
998
999                 case BC_LEX_OP_INC:
1000                 case BC_LEX_OP_DEC:
1001                 case BC_LEX_OP_MINUS:
1002                 case BC_LEX_OP_BOOL_NOT:
1003                 case BC_LEX_LPAREN:
1004                 case BC_LEX_NAME:
1005                 case BC_LEX_NUMBER:
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:
1015                 case BC_LEX_KW_ABS:
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
1029                 {
1030                         bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr);
1031                         break;
1032                 }
1033
1034                 case BC_LEX_KW_ELSE:
1035                 {
1036                         bc_parse_else(p);
1037                         break;
1038                 }
1039
1040                 case BC_LEX_SCOLON:
1041                 {
1042                         // Do nothing.
1043                         break;
1044                 }
1045
1046                 case BC_LEX_RBRACE:
1047                 {
1048                         bc_parse_endBody(p, true);
1049                         break;
1050                 }
1051
1052                 case BC_LEX_STR:
1053                 {
1054                         bc_parse_str(p, BC_INST_PRINT_STR);
1055                         break;
1056                 }
1057
1058                 case BC_LEX_KW_BREAK:
1059                 case BC_LEX_KW_CONTINUE:
1060                 {
1061                         bc_parse_loopExit(p, p->l.t);
1062                         break;
1063                 }
1064
1065                 case BC_LEX_KW_FOR:
1066                 {
1067                         bc_parse_for(p);
1068                         break;
1069                 }
1070
1071                 case BC_LEX_KW_HALT:
1072                 {
1073                         bc_parse_push(p, BC_INST_HALT);
1074                         bc_lex_next(&p->l);
1075                         break;
1076                 }
1077
1078                 case BC_LEX_KW_IF:
1079                 {
1080                         bc_parse_if(p);
1081                         break;
1082                 }
1083
1084                 case BC_LEX_KW_LIMITS:
1085                 {
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);
1090                         bc_vm_printf("\n");
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);
1102
1103                         bc_lex_next(&p->l);
1104
1105                         break;
1106                 }
1107
1108                 case BC_LEX_KW_PRINT:
1109                 {
1110                         bc_parse_print(p);
1111                         break;
1112                 }
1113
1114                 case BC_LEX_KW_QUIT:
1115                 {
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;
1119                         BC_VM_JMP;
1120                         break;
1121                 }
1122
1123                 case BC_LEX_KW_RETURN:
1124                 {
1125                         bc_parse_return(p);
1126                         break;
1127                 }
1128
1129                 case BC_LEX_KW_WHILE:
1130                 {
1131                         bc_parse_while(p);
1132                         break;
1133                 }
1134
1135                 default:
1136                 {
1137                         bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
1138                 }
1139         }
1140
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);
1144         }
1145
1146         // Make sure semicolons are eaten.
1147         while (p->l.t == BC_LEX_SCOLON) bc_lex_next(&p->l);
1148 }
1149
1150 void bc_parse_parse(BcParse *p) {
1151
1152         assert(p);
1153
1154         BC_SETJMP(exit);
1155
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);
1160                 bc_parse_func(p);
1161         }
1162         else bc_parse_stmt(p);
1163
1164 exit:
1165         BC_SIG_MAYLOCK;
1166         if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig)))
1167                 bc_parse_reset(p);
1168         BC_LONGJMP_CONT;
1169 }
1170
1171 static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
1172                                        BcParseNext next)
1173 {
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;
1180
1181         assert(!(flags & BC_PARSE_PRINT) || !(flags & BC_PARSE_NEEDVAL));
1182
1183         pfirst = (p->l.t == BC_LEX_LPAREN);
1184         nparens = nrelops = 0;
1185         rprn = done = get_token = assign = incdec = can_assign = false;
1186         bin_last = true;
1187
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);
1192         }
1193
1194         for (; !done && BC_PARSE_EXPR(t); t = p->l.t)
1195         {
1196                 switch (t) {
1197
1198                         case BC_LEX_OP_INC:
1199                         case BC_LEX_OP_DEC:
1200                         {
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;
1204                                 incdec = true;
1205                                 flags &= ~(BC_PARSE_ARRAY);
1206                                 break;
1207                         }
1208
1209 #if BC_ENABLE_EXTRA_MATH
1210                         case BC_LEX_OP_TRUNC:
1211                         {
1212                                 if (BC_ERR(!BC_PARSE_LEAF(prev, bin_last, rprn)))
1213                                         bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
1214
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;
1219                                 get_token = true;
1220                                 flags &= ~(BC_PARSE_ARRAY);
1221                                 break;
1222                         }
1223 #endif // BC_ENABLE_EXTRA_MATH
1224
1225                         case BC_LEX_OP_MINUS:
1226                         {
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);
1232                                 break;
1233                         }
1234
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:
1247                         {
1248                                 if (!BC_PARSE_INST_VAR(prev))
1249                                         bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
1250                         }
1251                         // Fallthrough.
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_ERROR_PARSE_EXPR);
1275                                 }
1276                                 else if (BC_ERR(BC_PARSE_PREV_PREFIX(prev) || bin_last))
1277                                         bc_parse_err(p, BC_ERROR_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_ERROR_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_ERROR_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_ERROR_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_ERROR_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_ERROR_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_ERROR_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_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);
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_ERROR_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_ERROR_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_ERROR_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_ERROR_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_ERROR_PARSE_EXPR);
1470
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);
1475
1476         if (!(flags & BC_PARSE_NEEDVAL) && !pfirst) {
1477
1478                 if (assign) {
1479                         inst = *((uchar*) bc_vec_top(&p->func->code));
1480                         inst += (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);
1481                         incdec = false;
1482                 }
1483                 else if (incdec && !(flags & BC_PARSE_PRINT)) {
1484                         inst = *((uchar*) bc_vec_top(&p->func->code));
1485                         incdec = (inst <= BC_INST_DEC);
1486                         inst = BC_INST_ASSIGN_PLUS_NO_VAL + (inst != BC_INST_INC &&
1487                                                              inst != BC_INST_ASSIGN_PLUS);
1488                 }
1489
1490                 if (inst >= BC_INST_ASSIGN_POWER_NO_VAL &&
1491                     inst <= BC_INST_ASSIGN_NO_VAL)
1492                 {
1493                         bc_vec_pop(&p->func->code);
1494                         if (incdec) bc_parse_push(p, BC_INST_ONE);
1495                         bc_parse_push(p, inst);
1496                 }
1497         }
1498
1499         if ((flags & BC_PARSE_PRINT)) {
1500                 if (pfirst || !assign) bc_parse_push(p, BC_INST_PRINT);
1501         }
1502         else if (!(flags & BC_PARSE_NEEDVAL) &&
1503                  (inst < BC_INST_ASSIGN_POWER_NO_VAL ||
1504                   inst > BC_INST_ASSIGN_NO_VAL))
1505         {
1506                 bc_parse_push(p, BC_INST_POP);
1507         }
1508
1509         // We want to eat newlines if newlines are not a valid ending token.
1510         // This is for spacing in things like for loop headers.
1511         for (incdec = true, i = 0; i < next.len && incdec; ++i)
1512                 incdec = (next.tokens[i] != BC_LEX_NLINE);
1513         if (incdec) {
1514                 while (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
1515         }
1516
1517         return BC_PARSE_STATUS_SUCCESS;
1518 }
1519
1520 void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next) {
1521
1522         BcParseStatus s = bc_parse_expr_err(p, flags, next);
1523
1524         if (BC_ERR(s == BC_PARSE_STATUS_EMPTY_EXPR))
1525                 bc_parse_err(p, BC_ERROR_PARSE_EMPTY_EXPR);
1526 }
1527
1528 void bc_parse_expr(BcParse *p, uint8_t flags) {
1529         assert(p);
1530         bc_parse_expr_status(p, flags, bc_parse_next_read);
1531 }
1532 #endif // BC_ENABLED