lang: re-arrange the operator table

This commit is contained in:
2024-12-01 13:19:01 +00:00
parent 051942e243
commit c9dbc2e7e4
2 changed files with 134 additions and 67 deletions

View File

@@ -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
#endif

View File

@@ -2,89 +2,156 @@
#include <ivy/lang/operator.h>
#include <stddef.h>
#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) {