Brian Callahan | 1c76196 | 2019-04-02 18:37:44 -0400 | [diff] [blame] | 1 | /* |
Gavin Howard | b5904bf | 2018-02-20 13:28:18 -0700 | [diff] [blame] | 2 | * ***************************************************************************** |
Gavin Howard | 5715b04 | 2018-02-12 16:11:42 -0700 | [diff] [blame] | 3 | * |
Gavin Howard | 29e00ba | 2020-06-30 09:25:21 -0600 | [diff] [blame] | 4 | * SPDX-License-Identifier: BSD-2-Clause |
| 5 | * |
Zach van Rijn | 6d2cf3f | 2020-01-14 22:05:02 +0000 | [diff] [blame] | 6 | * Copyright (c) 2018-2020 Gavin D. Howard and contributors. |
Gavin Howard | 5715b04 | 2018-02-12 16:11:42 -0700 | [diff] [blame] | 7 | * |
Gavin Howard | 7345cb9 | 2019-04-08 14:13:43 -0600 | [diff] [blame] | 8 | * All rights reserved. |
Gavin Howard | 5715b04 | 2018-02-12 16:11:42 -0700 | [diff] [blame] | 9 | * |
Gavin Howard | 7345cb9 | 2019-04-08 14:13:43 -0600 | [diff] [blame] | 10 | * Redistribution and use in source and binary forms, with or without |
| 11 | * modification, are permitted provided that the following conditions are met: |
| 12 | * |
| 13 | * * Redistributions of source code must retain the above copyright notice, this |
| 14 | * list of conditions and the following disclaimer. |
| 15 | * |
| 16 | * * Redistributions in binary form must reproduce the above copyright notice, |
| 17 | * this list of conditions and the following disclaimer in the documentation |
| 18 | * and/or other materials provided with the distribution. |
| 19 | * |
| 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 30 | * POSSIBILITY OF SUCH DAMAGE. |
Gavin Howard | 5715b04 | 2018-02-12 16:11:42 -0700 | [diff] [blame] | 31 | * |
Gavin Howard | b5904bf | 2018-02-20 13:28:18 -0700 | [diff] [blame] | 32 | * ***************************************************************************** |
Gavin Howard | 5715b04 | 2018-02-12 16:11:42 -0700 | [diff] [blame] | 33 | * |
Gavin Howard | 4ffe5a9 | 2018-09-26 20:58:31 -0600 | [diff] [blame] | 34 | * Definitions for bc. |
Gavin Howard | 5715b04 | 2018-02-12 16:11:42 -0700 | [diff] [blame] | 35 | * |
| 36 | */ |
| 37 | |
Gavin Howard | 4ffe5a9 | 2018-09-26 20:58:31 -0600 | [diff] [blame] | 38 | #ifndef BC_BC_H |
| 39 | #define BC_BC_H |
Gavin Howard | 8a596d4 | 2018-01-15 15:46:01 -0700 | [diff] [blame] | 40 | |
Gavin Howard | 1545ffe | 2018-12-24 11:26:46 -0700 | [diff] [blame] | 41 | #if BC_ENABLED |
| 42 | |
Gavin Howard | c1902aa | 2018-12-20 15:54:28 -0700 | [diff] [blame] | 43 | #include <limits.h> |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 44 | #include <stdbool.h> |
| 45 | |
Gavin Howard | 2949306 | 2018-03-20 19:57:37 -0600 | [diff] [blame] | 46 | #include <status.h> |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 47 | #include <lex.h> |
| 48 | #include <parse.h> |
Gavin Howard | 6839e4d | 2018-03-20 21:24:52 -0600 | [diff] [blame] | 49 | |
Gavin Howard | 5a32189 | 2020-05-16 17:27:55 -0600 | [diff] [blame] | 50 | void bc_main(int argc, char **argv); |
Gavin Howard | a84ad99 | 2018-12-03 19:11:06 -0700 | [diff] [blame] | 51 | |
Gavin Howard | a046ce9 | 2019-06-14 19:43:13 -0600 | [diff] [blame] | 52 | extern const char bc_help[]; |
Gavin Howard | 1ddff51 | 2019-06-14 19:59:57 -0600 | [diff] [blame] | 53 | extern const char bc_lib[]; |
| 54 | extern const char* bc_lib_name; |
Gavin Howard | 9866767 | 2020-04-28 17:17:39 -0600 | [diff] [blame] | 55 | |
Gavin Howard | 1ddff51 | 2019-06-14 19:59:57 -0600 | [diff] [blame] | 56 | #if BC_ENABLE_EXTRA_MATH |
| 57 | extern const char bc_lib2[]; |
| 58 | extern const char* bc_lib2_name; |
| 59 | #endif // BC_ENABLE_EXTRA_MATH |
Gavin Howard | a046ce9 | 2019-06-14 19:43:13 -0600 | [diff] [blame] | 60 | |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 61 | typedef struct BcLexKeyword { |
Gavin Howard | c1902aa | 2018-12-20 15:54:28 -0700 | [diff] [blame] | 62 | uchar data; |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 63 | const char name[9]; |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 64 | } BcLexKeyword; |
| 65 | |
Gavin Howard | 4662d6c | 2018-12-20 16:31:31 -0700 | [diff] [blame] | 66 | #define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1)) |
| 67 | |
Gavin Howard | fbd2b4a | 2018-12-27 12:11:41 -0700 | [diff] [blame] | 68 | #define BC_LEX_KW_POSIX(kw) ((kw)->data & (BC_LEX_CHAR_MSB(1))) |
| 69 | #define BC_LEX_KW_LEN(kw) ((size_t) ((kw)->data & ~(BC_LEX_CHAR_MSB(1)))) |
Gavin Howard | 4662d6c | 2018-12-20 16:31:31 -0700 | [diff] [blame] | 70 | |
Gavin Howard | c1902aa | 2018-12-20 15:54:28 -0700 | [diff] [blame] | 71 | #define BC_LEX_KW_ENTRY(a, b, c) \ |
Gavin Howard | 5151c87 | 2019-10-04 18:06:25 -0600 | [diff] [blame] | 72 | { .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c), .name = a } |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 73 | |
Gavin Howard | c70bd50 | 2018-12-31 17:28:32 -0700 | [diff] [blame] | 74 | extern const BcLexKeyword bc_lex_kws[]; |
| 75 | extern const size_t bc_lex_kws_len; |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 76 | |
Gavin Howard | 5a32189 | 2020-05-16 17:27:55 -0600 | [diff] [blame] | 77 | void bc_lex_token(BcLex *l); |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 78 | |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 79 | #define BC_PARSE_TOP_FLAG_PTR(p) ((uint16_t*) bc_vec_top(&(p)->flags)) |
| 80 | #define BC_PARSE_TOP_FLAG(p) (*(BC_PARSE_TOP_FLAG_PTR(p))) |
| 81 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 82 | #define BC_PARSE_FLAG_BRACE (UINTMAX_C(1)<<0) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 83 | #define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE) |
| 84 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 85 | #define BC_PARSE_FLAG_FUNC_INNER (UINTMAX_C(1)<<1) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 86 | #define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER) |
| 87 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 88 | #define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 89 | #define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC) |
| 90 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 91 | #define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 92 | #define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY) |
| 93 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 94 | #define BC_PARSE_FLAG_LOOP (UINTMAX_C(1)<<4) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 95 | #define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP) |
| 96 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 97 | #define BC_PARSE_FLAG_LOOP_INNER (UINTMAX_C(1)<<5) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 98 | #define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER) |
| 99 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 100 | #define BC_PARSE_FLAG_IF (UINTMAX_C(1)<<6) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 101 | #define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF) |
| 102 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 103 | #define BC_PARSE_FLAG_ELSE (UINTMAX_C(1)<<7) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 104 | #define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE) |
| 105 | |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 106 | #define BC_PARSE_FLAG_IF_END (UINTMAX_C(1)<<8) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 107 | #define BC_PARSE_IF_END(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF_END) |
| 108 | |
| 109 | #define BC_PARSE_NO_EXEC(p) ((p)->flags.len != 1 || BC_PARSE_TOP_FLAG(p) != 0) |
| 110 | |
Gavin Howard | 7ed50c7 | 2019-01-14 11:20:12 -0700 | [diff] [blame] | 111 | #define BC_PARSE_DELIMITER(t) \ |
| 112 | ((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF) |
Gavin Howard | b15fa03 | 2019-01-02 14:42:36 -0700 | [diff] [blame] | 113 | |
Gavin Howard | 63fdbfa | 2019-01-16 09:47:04 -0700 | [diff] [blame] | 114 | #define BC_PARSE_BLOCK_STMT(f) \ |
| 115 | ((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER)) |
| 116 | |
Gavin Howard | 2b4fde9 | 2018-12-24 16:02:24 -0700 | [diff] [blame] | 117 | #define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l))) |
Gavin Howard | 4662d6c | 2018-12-20 16:31:31 -0700 | [diff] [blame] | 118 | |
Gavin Howard | 1c6cfb8 | 2019-01-21 11:42:34 -0700 | [diff] [blame] | 119 | #define BC_PARSE_OP_DATA(t) bc_parse_ops[((t) - BC_LEX_OP_INC)] |
| 120 | #define BC_PARSE_OP_LEFT(op) (BC_PARSE_OP_DATA(op) & BC_LEX_CHAR_MSB(1)) |
| 121 | #define BC_PARSE_OP_PREC(op) (BC_PARSE_OP_DATA(op) & ~(BC_LEX_CHAR_MSB(1))) |
Gavin Howard | 4662d6c | 2018-12-20 16:31:31 -0700 | [diff] [blame] | 122 | |
Gavin Howard | 675b5cc | 2018-12-20 16:55:36 -0700 | [diff] [blame] | 123 | #define BC_PARSE_EXPR_ENTRY(e1, e2, e3, e4, e5, e6, e7, e8) \ |
Gavin Howard | f2d9a65 | 2019-05-11 07:38:32 -0600 | [diff] [blame] | 124 | ((UINTMAX_C(e1) << 7) | (UINTMAX_C(e2) << 6) | (UINTMAX_C(e3) << 5) | \ |
| 125 | (UINTMAX_C(e4) << 4) | (UINTMAX_C(e5) << 3) | (UINTMAX_C(e6) << 2) | \ |
| 126 | (UINTMAX_C(e7) << 1) | (UINTMAX_C(e8) << 0)) |
Gavin Howard | 675b5cc | 2018-12-20 16:55:36 -0700 | [diff] [blame] | 127 | |
| 128 | #define BC_PARSE_EXPR(i) \ |
Gavin Howard | 1cbfe24 | 2019-01-09 17:13:11 -0700 | [diff] [blame] | 129 | (bc_parse_exprs[(((i) & (uchar) ~(0x07)) >> 3)] & (1 << (7 - ((i) & 0x07)))) |
Gavin Howard | 675b5cc | 2018-12-20 16:55:36 -0700 | [diff] [blame] | 130 | |
Gavin Howard | 890d0c0 | 2018-10-30 16:34:50 -0600 | [diff] [blame] | 131 | #define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops))) |
Gavin Howard | b6e5a17 | 2018-12-28 17:41:15 -0700 | [diff] [blame] | 132 | #define BC_PARSE_LEAF(prev, bin_last, rparen) \ |
| 133 | (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev))) |
Gavin Howard | 60068bc | 2020-04-25 21:32:53 -0600 | [diff] [blame] | 134 | |
Gavin Howard | cb06773 | 2020-07-01 13:30:08 -0600 | [diff] [blame^] | 135 | #if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND |
Gavin Howard | 4713793 | 2019-10-10 21:16:43 -0600 | [diff] [blame] | 136 | #define BC_PARSE_INST_VAR(t) \ |
| 137 | ((t) >= BC_INST_VAR && (t) <= BC_INST_SEED && (t) != BC_INST_ARRAY) |
Gavin Howard | cb06773 | 2020-07-01 13:30:08 -0600 | [diff] [blame^] | 138 | #else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND |
Gavin Howard | f81f904 | 2018-12-27 14:19:53 -0700 | [diff] [blame] | 139 | #define BC_PARSE_INST_VAR(t) \ |
Gavin Howard | d975dc7 | 2019-01-24 15:13:17 -0700 | [diff] [blame] | 140 | ((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY) |
Gavin Howard | cb06773 | 2020-07-01 13:30:08 -0600 | [diff] [blame^] | 141 | #endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 142 | |
Gavin Howard | e522888 | 2019-01-10 16:08:04 -0700 | [diff] [blame] | 143 | #define BC_PARSE_PREV_PREFIX(p) \ |
Gavin Howard | 4684d71 | 2020-06-18 16:37:45 -0600 | [diff] [blame] | 144 | ((p) >= BC_INST_NEG && (p) <= BC_INST_BOOL_NOT) |
Gavin Howard | e522888 | 2019-01-10 16:08:04 -0700 | [diff] [blame] | 145 | #define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG) |
Gavin Howard | ac7a3c9 | 2019-01-10 13:26:29 -0700 | [diff] [blame] | 146 | |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 147 | // We can calculate the conversion between tokens and exprs by subtracting the |
Gavin Howard | 954f9b6 | 2018-12-19 15:22:20 -0700 | [diff] [blame] | 148 | // position of the first operator in the lex enum and adding the position of |
| 149 | // the first in the expr enum. Note: This only works for binary operators. |
| 150 | #define BC_PARSE_TOKEN_INST(t) ((uchar) ((t) - BC_LEX_NEG + BC_INST_NEG)) |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 151 | |
Gavin Howard | 5a32189 | 2020-05-16 17:27:55 -0600 | [diff] [blame] | 152 | typedef enum BcParseStatus { |
Gavin Howard | 707a4e3 | 2018-10-03 16:36:41 -0600 | [diff] [blame] | 153 | |
Gavin Howard | 5a32189 | 2020-05-16 17:27:55 -0600 | [diff] [blame] | 154 | BC_PARSE_STATUS_SUCCESS, |
| 155 | BC_PARSE_STATUS_EMPTY_EXPR, |
| 156 | |
| 157 | } BcParseStatus; |
| 158 | |
| 159 | void bc_parse_expr(BcParse *p, uint8_t flags); |
| 160 | |
| 161 | void bc_parse_parse(BcParse *p); |
| 162 | void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next); |
Gavin Howard | ff66e29 | 2018-03-28 12:47:58 -0600 | [diff] [blame] | 163 | |
Gavin Howard | c529578 | 2019-05-12 17:26:29 -0600 | [diff] [blame] | 164 | // This is necessary to clear up for if statements at the end of files. |
| 165 | void bc_parse_noElse(BcParse *p); |
| 166 | |
Gavin Howard | 1066709 | 2018-12-20 11:52:55 -0700 | [diff] [blame] | 167 | extern const char bc_sig_msg[]; |
Gavin Howard | 452841b | 2020-05-15 13:12:55 -0600 | [diff] [blame] | 168 | extern const uchar bc_sig_msg_len; |
Gavin Howard | 1066709 | 2018-12-20 11:52:55 -0700 | [diff] [blame] | 169 | |
Gavin Howard | a73c11b | 2018-12-17 11:30:39 -0700 | [diff] [blame] | 170 | extern const char* const bc_parse_const1; |
Gavin Howard | 675b5cc | 2018-12-20 16:55:36 -0700 | [diff] [blame] | 171 | extern const uint8_t bc_parse_exprs[]; |
Gavin Howard | c1902aa | 2018-12-20 15:54:28 -0700 | [diff] [blame] | 172 | extern const uchar bc_parse_ops[]; |
Gavin Howard | f89006a | 2018-10-29 13:01:51 -0600 | [diff] [blame] | 173 | extern const BcParseNext bc_parse_next_expr; |
| 174 | extern const BcParseNext bc_parse_next_param; |
| 175 | extern const BcParseNext bc_parse_next_print; |
| 176 | extern const BcParseNext bc_parse_next_rel; |
| 177 | extern const BcParseNext bc_parse_next_elem; |
| 178 | extern const BcParseNext bc_parse_next_for; |
| 179 | extern const BcParseNext bc_parse_next_read; |
| 180 | |
Gavin Howard | df4fe79 | 2018-10-03 16:48:30 -0600 | [diff] [blame] | 181 | #endif // BC_ENABLED |
| 182 | |
Gavin Howard | 4ffe5a9 | 2018-09-26 20:58:31 -0600 | [diff] [blame] | 183 | #endif // BC_BC_H |