#include #include #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 ""; } }