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