blob: be1f09db04a3a835f5425d75fbaa1125f9561b1d [file] [log] [blame]
Brian Callahan1c761962019-04-02 18:37:44 -04001/*
Gavin Howardb5904bf2018-02-20 13:28:18 -07002 * *****************************************************************************
Gavin Howard5715b042018-02-12 16:11:42 -07003 *
Gavin Howard7345cb92019-04-08 14:13:43 -06004 * Copyright (c) 2018-2019 Gavin D. Howard and contributors.
Gavin Howard5715b042018-02-12 16:11:42 -07005 *
Gavin Howard7345cb92019-04-08 14:13:43 -06006 * All rights reserved.
Gavin Howard5715b042018-02-12 16:11:42 -07007 *
Gavin Howard7345cb92019-04-08 14:13:43 -06008 * 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.
Gavin Howard5715b042018-02-12 16:11:42 -070029 *
Gavin Howardb5904bf2018-02-20 13:28:18 -070030 * *****************************************************************************
Gavin Howard5715b042018-02-12 16:11:42 -070031 *
Gavin Howard4ffe5a92018-09-26 20:58:31 -060032 * Definitions for bc.
Gavin Howard5715b042018-02-12 16:11:42 -070033 *
34 */
35
Gavin Howard4ffe5a92018-09-26 20:58:31 -060036#ifndef BC_BC_H
37#define BC_BC_H
Gavin Howard8a596d42018-01-15 15:46:01 -070038
Gavin Howard1545ffe2018-12-24 11:26:46 -070039#if BC_ENABLED
40
Gavin Howardc1902aa2018-12-20 15:54:28 -070041#include <limits.h>
Gavin Howard707a4e32018-10-03 16:36:41 -060042#include <stdbool.h>
43
Gavin Howard29493062018-03-20 19:57:37 -060044#include <status.h>
Gavin Howard707a4e32018-10-03 16:36:41 -060045#include <lex.h>
46#include <parse.h>
Gavin Howard6839e4d2018-03-20 21:24:52 -060047
Gavin Howarda84ad992018-12-03 19:11:06 -070048int bc_main(int argc, char **argv);
49
Gavin Howard707a4e32018-10-03 16:36:41 -060050typedef struct BcLexKeyword {
Gavin Howardc1902aa2018-12-20 15:54:28 -070051 uchar data;
Gavin Howard707a4e32018-10-03 16:36:41 -060052 const char name[9];
Gavin Howard707a4e32018-10-03 16:36:41 -060053} BcLexKeyword;
54
Gavin Howard4662d6c2018-12-20 16:31:31 -070055#define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1))
56
Gavin Howardfbd2b4a2018-12-27 12:11:41 -070057#define BC_LEX_KW_POSIX(kw) ((kw)->data & (BC_LEX_CHAR_MSB(1)))
58#define BC_LEX_KW_LEN(kw) ((size_t) ((kw)->data & ~(BC_LEX_CHAR_MSB(1))))
Gavin Howard4662d6c2018-12-20 16:31:31 -070059
Gavin Howardc1902aa2018-12-20 15:54:28 -070060#define BC_LEX_KW_ENTRY(a, b, c) \
Gavin Howarded38e942018-12-21 15:09:13 -070061 { .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c),.name = a }
Gavin Howard707a4e32018-10-03 16:36:41 -060062
Gavin Howardc70bd502018-12-31 17:28:32 -070063extern const BcLexKeyword bc_lex_kws[];
64extern const size_t bc_lex_kws_len;
Gavin Howard707a4e32018-10-03 16:36:41 -060065
66BcStatus bc_lex_token(BcLex *l);
67
Gavin Howardb15fa032019-01-02 14:42:36 -070068#define BC_PARSE_TOP_FLAG_PTR(p) ((uint16_t*) bc_vec_top(&(p)->flags))
69#define BC_PARSE_TOP_FLAG(p) (*(BC_PARSE_TOP_FLAG_PTR(p)))
70
Gavin Howardf2d9a652019-05-11 07:38:32 -060071#define BC_PARSE_FLAG_BRACE (UINTMAX_C(1)<<0)
Gavin Howardb15fa032019-01-02 14:42:36 -070072#define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE)
73
Gavin Howardf2d9a652019-05-11 07:38:32 -060074#define BC_PARSE_FLAG_FUNC_INNER (UINTMAX_C(1)<<1)
Gavin Howardb15fa032019-01-02 14:42:36 -070075#define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER)
76
Gavin Howardf2d9a652019-05-11 07:38:32 -060077#define BC_PARSE_FLAG_FUNC (UINTMAX_C(1)<<2)
Gavin Howardb15fa032019-01-02 14:42:36 -070078#define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC)
79
Gavin Howardf2d9a652019-05-11 07:38:32 -060080#define BC_PARSE_FLAG_BODY (UINTMAX_C(1)<<3)
Gavin Howardb15fa032019-01-02 14:42:36 -070081#define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY)
82
Gavin Howardf2d9a652019-05-11 07:38:32 -060083#define BC_PARSE_FLAG_LOOP (UINTMAX_C(1)<<4)
Gavin Howardb15fa032019-01-02 14:42:36 -070084#define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP)
85
Gavin Howardf2d9a652019-05-11 07:38:32 -060086#define BC_PARSE_FLAG_LOOP_INNER (UINTMAX_C(1)<<5)
Gavin Howardb15fa032019-01-02 14:42:36 -070087#define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER)
88
Gavin Howardf2d9a652019-05-11 07:38:32 -060089#define BC_PARSE_FLAG_IF (UINTMAX_C(1)<<6)
Gavin Howardb15fa032019-01-02 14:42:36 -070090#define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF)
91
Gavin Howardf2d9a652019-05-11 07:38:32 -060092#define BC_PARSE_FLAG_ELSE (UINTMAX_C(1)<<7)
Gavin Howardb15fa032019-01-02 14:42:36 -070093#define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE)
94
Gavin Howardf2d9a652019-05-11 07:38:32 -060095#define BC_PARSE_FLAG_IF_END (UINTMAX_C(1)<<8)
Gavin Howardb15fa032019-01-02 14:42:36 -070096#define BC_PARSE_IF_END(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF_END)
97
98#define BC_PARSE_NO_EXEC(p) ((p)->flags.len != 1 || BC_PARSE_TOP_FLAG(p) != 0)
99
Gavin Howard7ed50c72019-01-14 11:20:12 -0700100#define BC_PARSE_DELIMITER(t) \
101 ((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF)
Gavin Howardb15fa032019-01-02 14:42:36 -0700102
Gavin Howard63fdbfa2019-01-16 09:47:04 -0700103#define BC_PARSE_BLOCK_STMT(f) \
104 ((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER))
105
Gavin Howard2b4fde92018-12-24 16:02:24 -0700106#define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l)))
Gavin Howard4662d6c2018-12-20 16:31:31 -0700107
Gavin Howard1c6cfb82019-01-21 11:42:34 -0700108#define BC_PARSE_OP_DATA(t) bc_parse_ops[((t) - BC_LEX_OP_INC)]
109#define BC_PARSE_OP_LEFT(op) (BC_PARSE_OP_DATA(op) & BC_LEX_CHAR_MSB(1))
110#define BC_PARSE_OP_PREC(op) (BC_PARSE_OP_DATA(op) & ~(BC_LEX_CHAR_MSB(1)))
Gavin Howard4662d6c2018-12-20 16:31:31 -0700111
Gavin Howard675b5cc2018-12-20 16:55:36 -0700112#define BC_PARSE_EXPR_ENTRY(e1, e2, e3, e4, e5, e6, e7, e8) \
Gavin Howardf2d9a652019-05-11 07:38:32 -0600113 ((UINTMAX_C(e1) << 7) | (UINTMAX_C(e2) << 6) | (UINTMAX_C(e3) << 5) | \
114 (UINTMAX_C(e4) << 4) | (UINTMAX_C(e5) << 3) | (UINTMAX_C(e6) << 2) | \
115 (UINTMAX_C(e7) << 1) | (UINTMAX_C(e8) << 0))
Gavin Howard675b5cc2018-12-20 16:55:36 -0700116
117#define BC_PARSE_EXPR(i) \
Gavin Howard1cbfe242019-01-09 17:13:11 -0700118 (bc_parse_exprs[(((i) & (uchar) ~(0x07)) >> 3)] & (1 << (7 - ((i) & 0x07))))
Gavin Howard675b5cc2018-12-20 16:55:36 -0700119
Gavin Howard890d0c02018-10-30 16:34:50 -0600120#define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops)))
Gavin Howardb6e5a172018-12-28 17:41:15 -0700121#define BC_PARSE_LEAF(prev, bin_last, rparen) \
122 (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
Gavin Howardf81f9042018-12-27 14:19:53 -0700123#define BC_PARSE_INST_VAR(t) \
Gavin Howardd975dc72019-01-24 15:13:17 -0700124 ((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY)
Gavin Howard707a4e32018-10-03 16:36:41 -0600125
Gavin Howarde5228882019-01-10 16:08:04 -0700126#define BC_PARSE_PREV_PREFIX(p) \
127 ((p) >= BC_INST_INC_PRE && (p) <= BC_INST_BOOL_NOT)
128#define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG)
Gavin Howardac7a3c92019-01-10 13:26:29 -0700129
Gavin Howard707a4e32018-10-03 16:36:41 -0600130// We can calculate the conversion between tokens and exprs by subtracting the
Gavin Howard954f9b62018-12-19 15:22:20 -0700131// position of the first operator in the lex enum and adding the position of
132// the first in the expr enum. Note: This only works for binary operators.
133#define BC_PARSE_TOKEN_INST(t) ((uchar) ((t) - BC_LEX_NEG + BC_INST_NEG))
Gavin Howard707a4e32018-10-03 16:36:41 -0600134
Gavin Howard7536dcf2018-12-15 19:27:09 -0700135BcStatus bc_parse_expr(BcParse *p, uint8_t flags);
Gavin Howard707a4e32018-10-03 16:36:41 -0600136
Gavin Howard9d2497d2018-10-29 16:10:21 -0600137BcStatus bc_parse_parse(BcParse *p);
Gavin Howard7536dcf2018-12-15 19:27:09 -0700138BcStatus bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next);
Gavin Howardff66e292018-03-28 12:47:58 -0600139
Gavin Howardc5295782019-05-12 17:26:29 -0600140// This is necessary to clear up for if statements at the end of files.
141void bc_parse_noElse(BcParse *p);
142
Gavin Howard10667092018-12-20 11:52:55 -0700143#if BC_ENABLE_SIGNALS
144extern const char bc_sig_msg[];
Gavin Howard10667092018-12-20 11:52:55 -0700145#endif // BC_ENABLE_SIGNALS
146
Gavin Howarda73c11b2018-12-17 11:30:39 -0700147extern const char* const bc_parse_const1;
Gavin Howard675b5cc2018-12-20 16:55:36 -0700148extern const uint8_t bc_parse_exprs[];
Gavin Howardc1902aa2018-12-20 15:54:28 -0700149extern const uchar bc_parse_ops[];
Gavin Howardf89006a2018-10-29 13:01:51 -0600150extern const BcParseNext bc_parse_next_expr;
151extern const BcParseNext bc_parse_next_param;
152extern const BcParseNext bc_parse_next_print;
153extern const BcParseNext bc_parse_next_rel;
154extern const BcParseNext bc_parse_next_elem;
155extern const BcParseNext bc_parse_next_for;
156extern const BcParseNext bc_parse_next_read;
157
Gavin Howarddf4fe792018-10-03 16:48:30 -0600158#endif // BC_ENABLED
159
Gavin Howard4ffe5a92018-09-26 20:58:31 -0600160#endif // BC_BC_H