#include #include #include #define OP(id, p, a, l, u) \ [IVY_OP_##id] = { \ .op_id = (IVY_OP_##id), \ .op_precedence = (IVY_PRECEDENCE_##p), \ .op_associativity = (IVY_ASSOCIATIVITY_##a), \ .op_location = (IVY_OP_##l), \ .op_arity = (IVY_OP_##u), \ } #define TOK_OP(id, tok) \ [IVY_TOK_##tok - __IVY_TOK_INDEX_BASE] = &operators[IVY_OP_##id] #define SYM_OP(id, sym) \ [IVY_SYM_##sym - __IVY_SYM_INDEX_BASE] = &operators[IVY_OP_##id] #define KW_OP(id, kw) \ [IVY_KW_##kw - __IVY_KW_INDEX_BASE] = &operators[IVY_OP_##id] /* clang-format off */ static const struct ivy_operator operators[] = { OP(ASSIGN, ASSIGN, RIGHT, INFIX, BINARY), OP(ADD, ADDITION, LEFT, INFIX, BINARY), OP(SUBTRACT, ADDITION, LEFT, INFIX, BINARY), OP(MULTIPLY, MULTIPLICATION, LEFT, INFIX, BINARY), OP(DIVIDE, MULTIPLICATION, LEFT, INFIX, BINARY), OP(MODULO, MULTIPLICATION, LEFT, INFIX, BINARY), OP(LEFT_SHIFT, BITSHIFT, LEFT, INFIX, BINARY), OP(RIGHT_SHIFT, BITSHIFT, LEFT, INFIX, BINARY), OP(BINARY_AND, BITWISE_AND, LEFT, INFIX, BINARY), OP(BINARY_OR, BITWISE_OR, LEFT, INFIX, BINARY), OP(BINARY_XOR, BITWISE_XOR, LEFT, INFIX, BINARY), OP(LESS_THAN, COMPARISON, LEFT, INFIX, BINARY), OP(GREATER_THAN, COMPARISON, LEFT, INFIX, BINARY), OP(CASCADE, CASCADE, LEFT, INFIX, BINARY), OP(EQUAL, EQUALITY, LEFT, INFIX, BINARY), OP(NOT_EQUAL, EQUALITY, LEFT, INFIX, BINARY), OP(LESS_EQUAL, COMPARISON, LEFT, INFIX, BINARY), OP(GREATER_EQUAL, COMPARISON, LEFT, 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), OP(LEFT_SHIFT_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY), OP(RIGHT_SHIFT_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY), OP(BINARY_AND_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY), OP(BINARY_OR_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY), OP(BINARY_XOR_ASSIGN, ASSIGN, RIGHT, INFIX, BINARY), OP(AND, LOGICAL_AND, LEFT, INFIX, BINARY), OP(OR, LOGICAL_OR, LEFT, INFIX, BINARY), OP(IS, IS, LEFT, INFIX, BINARY), OP(NOT, NOT, LEFT, PREFIX, UNARY), OP(UNDERSTANDS, IS, LEFT, INFIX, BINARY), OP(SELF_ACCESS, SUBSCRIPT, LEFT, INFIX, BINARY), OP(PKG_ACCESS, SUBSCRIPT, LEFT, INFIX, BINARY), OP(SUBSCRIPT, SUBSCRIPT, LEFT, INFIX, BINARY), /* parser-internal pseudo-operators. */ OP(MSG, UNARY_MSG, LEFT, POSTFIX, UNARY), OP(LEFT_PAREN, PARENTHESIS, LEFT, INFIX, UNARY), }; static const size_t nr_operators = sizeof operators / sizeof operators[0]; static const struct ivy_operator *operator_symbols[] = { SYM_OP(ASSIGN, EQUAL), SYM_OP(ADD, PLUS), SYM_OP(SUBTRACT, HYPHEN), SYM_OP(MULTIPLY, ASTERISK), SYM_OP(DIVIDE, FORWARD_SLASH), SYM_OP(MODULO, PERCENT), SYM_OP(LEFT_SHIFT, DOUBLE_LEFT_ANGLE), SYM_OP(RIGHT_SHIFT, DOUBLE_RIGHT_ANGLE), SYM_OP(BINARY_AND, AMPERSAND), SYM_OP(BINARY_OR, PIPE), SYM_OP(BINARY_XOR, CARET), SYM_OP(LESS_THAN, LEFT_ANGLE), SYM_OP(GREATER_THAN, RIGHT_ANGLE), SYM_OP(CASCADE, SEMICOLON), SYM_OP(EQUAL, DOUBLE_EQUAL), SYM_OP(NOT_EQUAL, BANG_EQUAL), SYM_OP(LESS_EQUAL, LEFT_ANGLE_EQUAL), SYM_OP(GREATER_EQUAL, RIGHT_ANGLE_EQUAL), SYM_OP(ADD_ASSIGN, PLUS_EQUAL), SYM_OP(SUBTRACT_ASSIGN, HYPHEN_EQUAL), SYM_OP(MULTIPLY_ASSIGN, ASTERISK_EQUAL), SYM_OP(DIVIDE_ASSIGN, FORWARD_SLASH_EQUAL), SYM_OP(MODULO_ASSIGN, PERCENT_EQUAL), SYM_OP(LEFT_SHIFT_ASSIGN, DOUBLE_LEFT_ANGLE_EQUAL), SYM_OP(RIGHT_SHIFT_ASSIGN, DOUBLE_RIGHT_ANGLE_EQUAL), SYM_OP(BINARY_AND_ASSIGN, AMPERSAND_EQUAL), SYM_OP(BINARY_OR_ASSIGN, PIPE_EQUAL), SYM_OP(BINARY_XOR_ASSIGN, CARET_EQUAL), SYM_OP(SELF_ACCESS, DOUBLE_COLON), SYM_OP(PKG_ACCESS, HYPHEN_RIGHT_ANGLE), /* parser-internal pseudo-operators. */ SYM_OP(LEFT_PAREN, LEFT_PAREN), }; static const size_t nr_operator_symbols = sizeof operator_symbols / sizeof operator_symbols[0]; static const struct ivy_operator *operator_keywords[] = { KW_OP(AND, AND), KW_OP(OR, OR), KW_OP(IS, IS), KW_OP(NOT, NOT), KW_OP(UNDERSTANDS, UNDERSTANDS), }; static const size_t nr_operator_keywords = sizeof operator_keywords / sizeof operator_keywords[0]; static const struct ivy_operator *operator_tokens[] = { /* parser-internal pseudo-operators. */ TOK_OP(MSG, IDENT), }; static const size_t nr_operator_tokens = sizeof operator_keywords / sizeof operator_keywords[0]; /* clang-format on */ const struct ivy_operator *ivy_operator_get_by_token(unsigned int token) { const struct ivy_operator **op_list = NULL; size_t base = 0; size_t op_list_size = 0; if (token > __IVY_TOK_INDEX_BASE && token < __IVY_TOK_INDEX_LIMIT) { op_list = operator_tokens; base = __IVY_TOK_INDEX_BASE; op_list_size = nr_operator_tokens; } else if (token > __IVY_KW_INDEX_BASE && token < __IVY_KW_INDEX_LIMIT) { op_list = operator_keywords; base = __IVY_KW_INDEX_BASE; op_list_size = nr_operator_keywords; } else if (token > __IVY_SYM_INDEX_BASE && token < __IVY_SYM_INDEX_LIMIT) { op_list = operator_symbols; base = __IVY_SYM_INDEX_BASE; op_list_size = nr_operator_symbols; } else { return NULL; } if (token - base >= op_list_size) { return NULL; } return op_list[token - base]; } const struct ivy_operator *ivy_operator_get_by_id(enum ivy_operator_id id) { if (id >= nr_operators) { return NULL; } const struct ivy_operator *op = &operators[id]; if (op->op_id != id) { return NULL; } return op; } #define ENUM_STR(x) \ case x: \ return #x const char *ivy_operator_id_to_string(enum ivy_operator_id op) { switch (op) { ENUM_STR(IVY_OP_NONE); ENUM_STR(IVY_OP_ASSIGN); ENUM_STR(IVY_OP_ADD); ENUM_STR(IVY_OP_SUBTRACT); ENUM_STR(IVY_OP_MULTIPLY); ENUM_STR(IVY_OP_DIVIDE); ENUM_STR(IVY_OP_MODULO); ENUM_STR(IVY_OP_LEFT_SHIFT); ENUM_STR(IVY_OP_RIGHT_SHIFT); ENUM_STR(IVY_OP_BINARY_AND); ENUM_STR(IVY_OP_BINARY_OR); ENUM_STR(IVY_OP_BINARY_XOR); ENUM_STR(IVY_OP_LESS_THAN); ENUM_STR(IVY_OP_GREATER_THAN); ENUM_STR(IVY_OP_CASCADE); ENUM_STR(IVY_OP_EQUAL); ENUM_STR(IVY_OP_NOT_EQUAL); ENUM_STR(IVY_OP_LESS_EQUAL); ENUM_STR(IVY_OP_GREATER_EQUAL); ENUM_STR(IVY_OP_ADD_ASSIGN); ENUM_STR(IVY_OP_SUBTRACT_ASSIGN); ENUM_STR(IVY_OP_MULTIPLY_ASSIGN); ENUM_STR(IVY_OP_DIVIDE_ASSIGN); ENUM_STR(IVY_OP_MODULO_ASSIGN); ENUM_STR(IVY_OP_LEFT_SHIFT_ASSIGN); ENUM_STR(IVY_OP_RIGHT_SHIFT_ASSIGN); ENUM_STR(IVY_OP_BINARY_AND_ASSIGN); ENUM_STR(IVY_OP_BINARY_OR_ASSIGN); ENUM_STR(IVY_OP_BINARY_XOR_ASSIGN); ENUM_STR(IVY_OP_AND); ENUM_STR(IVY_OP_OR); ENUM_STR(IVY_OP_IS); ENUM_STR(IVY_OP_NOT); ENUM_STR(IVY_OP_UNDERSTANDS); ENUM_STR(IVY_OP_SELF_ACCESS); ENUM_STR(IVY_OP_PKG_ACCESS); ENUM_STR(IVY_OP_SUBSCRIPT); ENUM_STR(IVY_OP_MSG); ENUM_STR(IVY_OP_LEFT_PAREN); default: return ""; } }