From c9dbc2e7e4f15cceb4532ad45a9e3a8806d91283 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 1 Dec 2024 13:19:01 +0000 Subject: [PATCH] lang: re-arrange the operator table --- lang/include/ivy/lang/operator.h | 7 +- lang/operator.c | 194 +++++++++++++++++++++---------- 2 files changed, 134 insertions(+), 67 deletions(-) diff --git a/lang/include/ivy/lang/operator.h b/lang/include/ivy/lang/operator.h index 0bccdb5..b580135 100644 --- a/lang/include/ivy/lang/operator.h +++ b/lang/include/ivy/lang/operator.h @@ -22,6 +22,7 @@ enum ivy_operator_precedence { IVY_PRECEDENCE_IS, IVY_PRECEDENCE_NOT, IVY_PRECEDENCE_SUBSCRIPT, + IVY_PRECEDENCE_PARENTHESIS, }; enum ivy_operator_associativity { @@ -85,14 +86,14 @@ enum ivy_operator_id { struct ivy_operator { enum ivy_operator_id op_id; - unsigned int op_token; enum ivy_operator_precedence op_precedence; enum ivy_operator_associativity op_associativity; enum ivy_operator_location op_location; enum ivy_operator_arity op_arity; }; -IVY_API const struct ivy_operator *ivy_operator_get(unsigned int token); +IVY_API const struct ivy_operator *ivy_operator_get_by_id(enum ivy_operator_id id); +IVY_API const struct ivy_operator *ivy_operator_get_by_token(unsigned int token); IVY_API const char *ivy_operator_id_to_string(enum ivy_operator_id op); -#endif \ No newline at end of file +#endif diff --git a/lang/operator.c b/lang/operator.c index 881041a..8436aeb 100644 --- a/lang/operator.c +++ b/lang/operator.c @@ -2,89 +2,156 @@ #include #include -#define TOK_OP(id, t, p, a, l, u) \ - [IVY_TOK_##t] = { \ +#define OP(id, p, a, l, u) \ + [IVY_OP_##id] = { \ .op_id = (IVY_OP_##id), \ - .op_token = (IVY_TOK_##t), \ .op_precedence = (IVY_PRECEDENCE_##p), \ .op_associativity = (IVY_ASSOCIATIVITY_##a), \ .op_location = (IVY_OP_##l), \ .op_arity = (IVY_OP_##u), \ } -#define SYM_OP(id, t, p, a, l, u) \ - [IVY_SYM_##t] = { \ - .op_id = (IVY_OP_##id), \ - .op_token = (IVY_SYM_##t), \ - .op_precedence = (IVY_PRECEDENCE_##p), \ - .op_associativity = (IVY_ASSOCIATIVITY_##a), \ - .op_location = (IVY_OP_##l), \ - .op_arity = (IVY_OP_##u), \ - } -#define KW_OP(id, t, p, a, l, u) \ - [IVY_KW_##t] = { \ - .op_id = (IVY_OP_##id), \ - .op_token = (IVY_KW_##t), \ - .op_precedence = (IVY_PRECEDENCE_##p), \ - .op_associativity = (IVY_ASSOCIATIVITY_##a), \ - .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[] = { - SYM_OP(ASSIGN, EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(ADD, PLUS, ADDITION, LEFT, INFIX, BINARY), - SYM_OP(SUBTRACT, HYPHEN, ADDITION, LEFT, INFIX, BINARY), - SYM_OP(MULTIPLY, ASTERISK, MULTIPLICATION, LEFT, INFIX, BINARY), - SYM_OP(DIVIDE, FORWARD_SLASH, MULTIPLICATION, LEFT, INFIX, BINARY), - SYM_OP(MODULO, PERCENT, MULTIPLICATION, LEFT, INFIX, BINARY), - SYM_OP(LEFT_SHIFT, DOUBLE_LEFT_ANGLE, BITSHIFT, LEFT, INFIX, BINARY), - SYM_OP(RIGHT_SHIFT, DOUBLE_RIGHT_ANGLE, BITSHIFT, LEFT, INFIX, BINARY), - SYM_OP(BINARY_AND, AMPERSAND, BITWISE_AND, LEFT, INFIX, BINARY), - SYM_OP(BINARY_OR, PIPE, BITWISE_OR, LEFT, INFIX, BINARY), - SYM_OP(BINARY_XOR, CARET, BITWISE_XOR, LEFT, INFIX, BINARY), - SYM_OP(LESS_THAN, LEFT_ANGLE, COMPARISON, LEFT, INFIX, BINARY), - SYM_OP(GREATER_THAN, RIGHT_ANGLE, COMPARISON, LEFT, INFIX, BINARY), - SYM_OP(CASCADE, SEMICOLON, CASCADE, LEFT, INFIX, BINARY), - SYM_OP(EQUAL, DOUBLE_EQUAL, EQUALITY, LEFT, INFIX, BINARY), - SYM_OP(NOT_EQUAL, BANG_EQUAL, EQUALITY, LEFT, INFIX, BINARY), - SYM_OP(LESS_EQUAL, LEFT_ANGLE_EQUAL, COMPARISON, LEFT, INFIX, BINARY), - SYM_OP(GREATER_EQUAL, RIGHT_ANGLE_EQUAL, COMPARISON, LEFT, INFIX, BINARY), - SYM_OP(ADD_ASSIGN, PLUS_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(SUBTRACT_ASSIGN, HYPHEN_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(MULTIPLY_ASSIGN, ASTERISK_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(DIVIDE_ASSIGN, FORWARD_SLASH_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(MODULO_ASSIGN, PERCENT_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(LEFT_SHIFT_ASSIGN, DOUBLE_LEFT_ANGLE_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(RIGHT_SHIFT_ASSIGN, DOUBLE_RIGHT_ANGLE_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(BINARY_AND_ASSIGN, AMPERSAND_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(BINARY_OR_ASSIGN, PIPE_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - SYM_OP(BINARY_XOR_ASSIGN, CARET_EQUAL, ASSIGN, RIGHT, INFIX, BINARY), - KW_OP(AND, AND, LOGICAL_AND, LEFT, INFIX, BINARY), - KW_OP(OR, OR, LOGICAL_OR, LEFT, INFIX, BINARY), - KW_OP(IS, IS, IS, LEFT, INFIX, BINARY), - KW_OP(NOT, NOT, NOT, LEFT, PREFIX, UNARY), - KW_OP(UNDERSTANDS, UNDERSTANDS, IS, LEFT, INFIX, BINARY), - SYM_OP(SELF_ACCESS, DOUBLE_COLON, SUBSCRIPT, LEFT, INFIX, BINARY), - SYM_OP(PKG_ACCESS, HYPHEN_RIGHT_ANGLE, SUBSCRIPT, LEFT, INFIX, BINARY), + 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), /* parser-internal pseudo-operators. */ - TOK_OP(MSG, IDENT, UNARY_MSG, LEFT, POSTFIX, UNARY), - SYM_OP(LEFT_PAREN, LEFT_PAREN, SUBSCRIPT, LEFT, INFIX, UNARY), + 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(unsigned int token) +const struct ivy_operator *ivy_operator_get_by_token(unsigned int token) { - if (token >= nr_operators) { + 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; } - const struct ivy_operator *op = &operators[token]; - if (op->op_token != token) { + 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; } @@ -95,7 +162,6 @@ const struct ivy_operator *ivy_operator_get(unsigned int token) case x: \ return #x - const char *ivy_operator_id_to_string(enum ivy_operator_id op) { switch (op) {