bshell: re-organise build into three separate components
bshell: the front-end binary bshell.runtime: contains the parser, compiler, and classes needed to run bshell scripts bshell.core: contains the builtin commandlets and aliases
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
#include <bshell/parse/token.h>
|
||||
#include <bshell/runtime/operator.h>
|
||||
|
||||
#define OP(id, p, a, l, u) \
|
||||
[BSHELL_OP_##id] = { \
|
||||
.op_id = (BSHELL_OP_##id), \
|
||||
.op_precedence = (BSHELL_PRECEDENCE_##p), \
|
||||
.op_associativity = (BSHELL_ASSOCIATIVITY_##a), \
|
||||
.op_location = (BSHELL_OPL_##l), \
|
||||
.op_arity = (BSHELL_OPA_##u), \
|
||||
}
|
||||
|
||||
#define BSHELL_TOK_OP(id, tok) \
|
||||
[BSHELL_TOK_##tok - __BSHELL_TOK_INDEX_BASE] = &operators[BSHELL_OP_##id]
|
||||
#define BSHELL_SYM_OP(id, sym) \
|
||||
[BSHELL_SYM_##sym - __BSHELL_SYM_INDEX_BASE] = &operators[BSHELL_OP_##id]
|
||||
#define BSHELL_KW_OP(id, kw) [BSHELL_KW_##kw - __BSHELL_KW_INDEX_BASE] = &operators[BSHELL_OP_##id]
|
||||
#define BSHELL_TKOP_OP(id, kw) \
|
||||
[BSHELL_TKOP_##kw - __BSHELL_TKOP_INDEX_BASE] \
|
||||
= &operators[BSHELL_OP_##id]
|
||||
|
||||
/* clang-format off */
|
||||
static const struct bshell_operator_info operators[] = {
|
||||
OP(ACCESS, MEMBER_ACCESS, LEFT, INFIX, BINARY),
|
||||
OP(CONDITIONAL_ACCESS, MEMBER_ACCESS, LEFT, INFIX, BINARY),
|
||||
OP(STATIC_ACCESS, STATIC_ACCESS, LEFT, INFIX, BINARY),
|
||||
OP(SUBSCRIPT, SUBSCRIPT, LEFT, INFIX, BINARY),
|
||||
OP(CONDITIONAL_SUBSCRIPT, SUBSCRIPT, LEFT, INFIX, BINARY),
|
||||
OP(CAST, CAST, LEFT, PREFIX, UNARY),
|
||||
OP(USPLIT, SPLIT, LEFT, PREFIX, UNARY),
|
||||
OP(UJOIN, JOIN, LEFT, PREFIX, UNARY),
|
||||
OP(ARRAY_DELIMITER, ARRAY, LEFT, INFIX, BINARY),
|
||||
OP(INCREMENT, INCREMENT, LEFT, INFIX, BINARY),
|
||||
OP(LOGICAL_NOT, NOT, LEFT, PREFIX, UNARY),
|
||||
OP(RANGE, RANGE, LEFT, INFIX, BINARY),
|
||||
OP(FORMAT, FORMAT, LEFT, INFIX, BINARY),
|
||||
OP(MULTIPLY, MULTIPLICATION, LEFT, INFIX, BINARY),
|
||||
OP(DIVIDE, MULTIPLICATION, LEFT, INFIX, BINARY),
|
||||
OP(MODULO, MULTIPLICATION, LEFT, INFIX, BINARY),
|
||||
OP(ADD, ADDITION, LEFT, INFIX, BINARY),
|
||||
OP(SUBTRACT, ADDITION, LEFT, INFIX, BINARY),
|
||||
|
||||
OP(BSPLIT, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(BJOIN, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(IS, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(ISNOT, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(AS, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(EQUAL, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(NOT_EQUAL, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(GREATER_THAN, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(LESS_THAN, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(GREATER_EQUAL, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(LESS_EQUAL, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(LIKE, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(NOTLIKE, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(MATCH, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(NOTMATCH, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(IN, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(NOTIN, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(CONTAINS, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(NOTCONTAINS, COMPARISON, LEFT, INFIX, BINARY),
|
||||
OP(REPLACE, COMPARISON, LEFT, INFIX, BINARY),
|
||||
|
||||
OP(LOGICAL_AND, LOGICAL, LEFT, INFIX, BINARY),
|
||||
OP(LOGICAL_OR, LOGICAL, LEFT, INFIX, BINARY),
|
||||
OP(LOGICAL_XOR, LOGICAL, LEFT, INFIX, BINARY),
|
||||
|
||||
OP(BINARY_AND, BITWISE, LEFT, INFIX, BINARY),
|
||||
OP(BINARY_OR, BITWISE, LEFT, INFIX, BINARY),
|
||||
OP(BINARY_NOT, BITWISE, LEFT, INFIX, BINARY),
|
||||
OP(BINARY_XOR, BITWISE, LEFT, INFIX, BINARY),
|
||||
OP(LEFT_SHIFT, BITWISE, LEFT, INFIX, BINARY),
|
||||
OP(RIGHT_SHIFT, BITWISE, LEFT, INFIX, BINARY),
|
||||
|
||||
OP(ASSIGN, ASSIGN, RIGHT, INFIX, BINARY),
|
||||
OP(ADD_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY),
|
||||
OP(SUBTRACT_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY),
|
||||
OP(MULTIPLY_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY),
|
||||
OP(DIVIDE_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY),
|
||||
OP(MODULO_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY),
|
||||
|
||||
/* these are not real operators, and are just used internally by the
|
||||
* parser. */
|
||||
OP(SUBEXPR, PARENTHESIS, LEFT, PREFIX, UNARY),
|
||||
OP(ARRAY_START, PARENTHESIS, LEFT, PREFIX, UNARY),
|
||||
OP(PAREN, PARENTHESIS, LEFT, PREFIX, UNARY),
|
||||
OP(HASHTABLE_START, PARENTHESIS, LEFT, PREFIX, UNARY),
|
||||
OP(SCRIPTBLOCK, PARENTHESIS, LEFT, PREFIX, UNARY),
|
||||
};
|
||||
static const size_t nr_operators = sizeof operators / sizeof operators[0];
|
||||
|
||||
static const struct bshell_operator_info *bshell_operator_symbols[] = {
|
||||
BSHELL_SYM_OP(LOGICAL_NOT, BANG),
|
||||
BSHELL_SYM_OP(ASSIGN, EQUAL),
|
||||
BSHELL_SYM_OP(ADD, PLUS),
|
||||
BSHELL_SYM_OP(SUBTRACT, HYPHEN),
|
||||
BSHELL_SYM_OP(MULTIPLY, ASTERISK),
|
||||
BSHELL_SYM_OP(DIVIDE, FORWARD_SLASH),
|
||||
BSHELL_SYM_OP(MODULO, PERCENT),
|
||||
BSHELL_SYM_OP(ADD_ASSIGN, PLUS_EQUAL),
|
||||
BSHELL_SYM_OP(SUBTRACT_ASSIGN, HYPHEN_EQUAL),
|
||||
BSHELL_SYM_OP(MULTIPLY_ASSIGN, ASTERISK_EQUAL),
|
||||
BSHELL_SYM_OP(DIVIDE_ASSIGN, FORWARD_SLASH_EQUAL),
|
||||
BSHELL_SYM_OP(MODULO_ASSIGN, PERCENT_EQUAL),
|
||||
BSHELL_SYM_OP(RANGE, DOT_DOT),
|
||||
BSHELL_SYM_OP(SUBSCRIPT, LEFT_BRACKET),
|
||||
BSHELL_SYM_OP(CONDITIONAL_SUBSCRIPT, QUESTION_LEFT_BRACKET),
|
||||
|
||||
BSHELL_SYM_OP(ACCESS, DOT),
|
||||
BSHELL_SYM_OP(CONDITIONAL_ACCESS, QUESTION_DOT),
|
||||
BSHELL_SYM_OP(STATIC_ACCESS, COLON_COLON),
|
||||
|
||||
/* parser-internal pseudo-operators. */
|
||||
|
||||
/* CAST uses the same symbol as SUBSCRIPT */
|
||||
/* BSHELL_SYM_OP(CAST, LEFT_BRACKET), */
|
||||
BSHELL_SYM_OP(SUBEXPR, DOLLAR_LEFT_PAREN),
|
||||
BSHELL_SYM_OP(PAREN, LEFT_PAREN),
|
||||
BSHELL_SYM_OP(ARRAY_START, AT_LEFT_PAREN),
|
||||
BSHELL_SYM_OP(HASHTABLE_START, AT_LEFT_BRACE),
|
||||
};
|
||||
static const size_t nr_bshell_operator_symbols = sizeof bshell_operator_symbols / sizeof bshell_operator_symbols[0];
|
||||
|
||||
static const struct bshell_operator_info *bshell_operator_token_ops[] = {
|
||||
BSHELL_TKOP_OP(FORMAT, F),
|
||||
BSHELL_TKOP_OP(BINARY_AND, BAND),
|
||||
BSHELL_TKOP_OP(BINARY_OR, BOR),
|
||||
BSHELL_TKOP_OP(BINARY_XOR, BXOR),
|
||||
BSHELL_TKOP_OP(BINARY_NOT, BNOT),
|
||||
BSHELL_TKOP_OP(LEFT_SHIFT, SHL),
|
||||
BSHELL_TKOP_OP(RIGHT_SHIFT, SHR),
|
||||
BSHELL_TKOP_OP(EQUAL, EQ),
|
||||
BSHELL_TKOP_OP(NOT_EQUAL, NE),
|
||||
BSHELL_TKOP_OP(GREATER_THAN, GT),
|
||||
BSHELL_TKOP_OP(LESS_THAN, LT),
|
||||
BSHELL_TKOP_OP(GREATER_EQUAL, GE),
|
||||
BSHELL_TKOP_OP(LESS_EQUAL, LE),
|
||||
BSHELL_TKOP_OP(MATCH, MATCH),
|
||||
BSHELL_TKOP_OP(NOTMATCH, NOTMATCH),
|
||||
BSHELL_TKOP_OP(REPLACE, REPLACE),
|
||||
BSHELL_TKOP_OP(LIKE, LIKE),
|
||||
BSHELL_TKOP_OP(NOTLIKE, NOTLIKE),
|
||||
BSHELL_TKOP_OP(IN, IN),
|
||||
BSHELL_TKOP_OP(NOTIN, NOTIN),
|
||||
BSHELL_TKOP_OP(CONTAINS, CONTAINS),
|
||||
BSHELL_TKOP_OP(NOTCONTAINS, NOTCONTAINS),
|
||||
BSHELL_TKOP_OP(LOGICAL_AND, AND),
|
||||
BSHELL_TKOP_OP(LOGICAL_OR, OR),
|
||||
BSHELL_TKOP_OP(LOGICAL_XOR, XOR),
|
||||
BSHELL_TKOP_OP(LOGICAL_NOT, NOT),
|
||||
/* there are also unary versions of these operators */
|
||||
BSHELL_TKOP_OP(BSPLIT, SPLIT),
|
||||
BSHELL_TKOP_OP(BJOIN, JOIN),
|
||||
|
||||
BSHELL_TKOP_OP(IS, IS),
|
||||
BSHELL_TKOP_OP(ISNOT, ISNOT),
|
||||
BSHELL_TKOP_OP(AS, AS),
|
||||
};
|
||||
static const size_t nr_bshell_operator_token_ops = sizeof bshell_operator_token_ops / sizeof bshell_operator_token_ops[0];
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
const struct bshell_operator_info *bshell_operator_get_by_token(
|
||||
unsigned int token)
|
||||
{
|
||||
const struct bshell_operator_info **op_list = NULL;
|
||||
size_t base = 0;
|
||||
size_t op_list_size = 0;
|
||||
|
||||
if (token > __BSHELL_TKOP_INDEX_BASE
|
||||
&& token < __BSHELL_TKOP_INDEX_LIMIT) {
|
||||
op_list = bshell_operator_token_ops;
|
||||
base = __BSHELL_TKOP_INDEX_BASE;
|
||||
op_list_size = nr_bshell_operator_token_ops;
|
||||
} else if (token > __BSHELL_SYM_INDEX_BASE && token < __BSHELL_SYM_INDEX_LIMIT) {
|
||||
op_list = bshell_operator_symbols;
|
||||
base = __BSHELL_SYM_INDEX_BASE;
|
||||
op_list_size = nr_bshell_operator_symbols;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (token - base >= op_list_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return op_list[token - base];
|
||||
}
|
||||
|
||||
const struct bshell_operator_info *bshell_operator_get_by_id(
|
||||
enum bshell_operator_id id)
|
||||
{
|
||||
if (id >= nr_operators) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct bshell_operator_info *op = &operators[id];
|
||||
if (op->op_id != id) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
#define ENUM_STR(x) \
|
||||
case x: \
|
||||
return #x
|
||||
|
||||
const char *bshell_operator_id_to_string(enum bshell_operator_id op)
|
||||
{
|
||||
switch (op) {
|
||||
ENUM_STR(BSHELL_OP_NONE);
|
||||
ENUM_STR(BSHELL_OP_ADD);
|
||||
ENUM_STR(BSHELL_OP_SUBTRACT);
|
||||
ENUM_STR(BSHELL_OP_MULTIPLY);
|
||||
ENUM_STR(BSHELL_OP_DIVIDE);
|
||||
ENUM_STR(BSHELL_OP_MODULO);
|
||||
ENUM_STR(BSHELL_OP_INCREMENT);
|
||||
ENUM_STR(BSHELL_OP_DECREMENT);
|
||||
ENUM_STR(BSHELL_OP_LEFT_SHIFT);
|
||||
ENUM_STR(BSHELL_OP_RIGHT_SHIFT);
|
||||
ENUM_STR(BSHELL_OP_BINARY_AND);
|
||||
ENUM_STR(BSHELL_OP_BINARY_OR);
|
||||
ENUM_STR(BSHELL_OP_BINARY_XOR);
|
||||
ENUM_STR(BSHELL_OP_BINARY_NOT);
|
||||
ENUM_STR(BSHELL_OP_LESS_THAN);
|
||||
ENUM_STR(BSHELL_OP_GREATER_THAN);
|
||||
ENUM_STR(BSHELL_OP_EQUAL);
|
||||
ENUM_STR(BSHELL_OP_NOT_EQUAL);
|
||||
ENUM_STR(BSHELL_OP_LESS_EQUAL);
|
||||
ENUM_STR(BSHELL_OP_GREATER_EQUAL);
|
||||
ENUM_STR(BSHELL_OP_ASSIGN);
|
||||
ENUM_STR(BSHELL_OP_ADD_ASSIGN);
|
||||
ENUM_STR(BSHELL_OP_SUBTRACT_ASSIGN);
|
||||
ENUM_STR(BSHELL_OP_MULTIPLY_ASSIGN);
|
||||
ENUM_STR(BSHELL_OP_DIVIDE_ASSIGN);
|
||||
ENUM_STR(BSHELL_OP_MODULO_ASSIGN);
|
||||
ENUM_STR(BSHELL_OP_LOGICAL_AND);
|
||||
ENUM_STR(BSHELL_OP_LOGICAL_OR);
|
||||
ENUM_STR(BSHELL_OP_LOGICAL_XOR);
|
||||
ENUM_STR(BSHELL_OP_LOGICAL_NOT);
|
||||
ENUM_STR(BSHELL_OP_RANGE);
|
||||
ENUM_STR(BSHELL_OP_MATCH);
|
||||
ENUM_STR(BSHELL_OP_NOTMATCH);
|
||||
ENUM_STR(BSHELL_OP_REPLACE);
|
||||
ENUM_STR(BSHELL_OP_LIKE);
|
||||
ENUM_STR(BSHELL_OP_NOTLIKE);
|
||||
ENUM_STR(BSHELL_OP_IN);
|
||||
ENUM_STR(BSHELL_OP_NOTIN);
|
||||
ENUM_STR(BSHELL_OP_FORMAT);
|
||||
ENUM_STR(BSHELL_OP_CONTAINS);
|
||||
ENUM_STR(BSHELL_OP_NOTCONTAINS);
|
||||
ENUM_STR(BSHELL_OP_USPLIT);
|
||||
ENUM_STR(BSHELL_OP_BSPLIT);
|
||||
ENUM_STR(BSHELL_OP_UJOIN);
|
||||
ENUM_STR(BSHELL_OP_BJOIN);
|
||||
ENUM_STR(BSHELL_OP_IS);
|
||||
ENUM_STR(BSHELL_OP_ISNOT);
|
||||
ENUM_STR(BSHELL_OP_AS);
|
||||
ENUM_STR(BSHELL_OP_SUBSCRIPT);
|
||||
ENUM_STR(BSHELL_OP_CONDITIONAL_SUBSCRIPT);
|
||||
ENUM_STR(BSHELL_OP_ARRAY_DELIMITER);
|
||||
ENUM_STR(BSHELL_OP_ACCESS);
|
||||
ENUM_STR(BSHELL_OP_STATIC_ACCESS);
|
||||
ENUM_STR(BSHELL_OP_CONDITIONAL_ACCESS);
|
||||
ENUM_STR(BSHELL_OP_CAST);
|
||||
ENUM_STR(BSHELL_OP_SUBEXPR);
|
||||
ENUM_STR(BSHELL_OP_PAREN);
|
||||
ENUM_STR(BSHELL_OP_ARRAY_START);
|
||||
ENUM_STR(BSHELL_OP_HASHTABLE_START);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user