Make a single "operator" token, and specialize after parse.
This commit is contained in:
parent
156c02908d
commit
9500a6f9b0
|
@ -9,6 +9,16 @@
|
|||
*/
|
||||
typedef void(*libab_function_ptr)();
|
||||
|
||||
/**
|
||||
* The variant of the operator that
|
||||
* has been registered with libabacus.
|
||||
*/
|
||||
enum libab_operator_variant_e {
|
||||
OPERATOR_PREFIX,
|
||||
OPERATOR_INFIX,
|
||||
OPERATOR_POSTFIX
|
||||
};
|
||||
|
||||
/**
|
||||
* The common information
|
||||
* that both operators and functions shared.
|
||||
|
@ -34,7 +44,7 @@ struct libab_operator_s {
|
|||
* Corresponds to token types associated with
|
||||
* each operator.
|
||||
*/
|
||||
int type;
|
||||
enum libab_operator_variant_e type;
|
||||
/**
|
||||
* The precedence of the operator.
|
||||
*/
|
||||
|
@ -61,6 +71,7 @@ struct libab_function_s {
|
|||
struct libab_behavior_s behavior;
|
||||
};
|
||||
|
||||
typedef enum libab_operator_variant_e libab_operator_variant;
|
||||
typedef struct libab_behavior_s libab_behavior;
|
||||
typedef struct libab_operator_s libab_operator;
|
||||
typedef struct libab_function_s libab_function;
|
||||
|
|
|
@ -55,6 +55,7 @@ enum libab_lexer_token_e {
|
|||
TOKEN_CHAR = 0,
|
||||
TOKEN_ID,
|
||||
TOKEN_NUM,
|
||||
TOKEN_OP,
|
||||
TOKEN_OP_INFIX,
|
||||
TOKEN_OP_PREFIX,
|
||||
TOKEN_OP_POSTFIX,
|
||||
|
|
|
@ -49,7 +49,7 @@ libab_result _initialize_behavior(libab* ab, libab_behavior* behavior,
|
|||
return result;
|
||||
}
|
||||
|
||||
libab_result _register_operator(libab* ab, const char* op, int token_type, int precedence, int associativity, const char* type, libab_function_ptr func) {
|
||||
libab_result _register_operator(libab* ab, const char* op, libab_operator_variant token_type, int precedence, int associativity, const char* type, libab_function_ptr func) {
|
||||
char op_buffer[8];
|
||||
libab_result result = LIBAB_SUCCESS;
|
||||
libab_table_entry* new_entry;
|
||||
|
@ -69,7 +69,7 @@ libab_result _register_operator(libab* ab, const char* op, int token_type, int p
|
|||
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
_sanitize(op_buffer, op, 8);
|
||||
result = libab_convert_lex_result(eval_config_add(&ab->lexer.config, op_buffer, token_type));
|
||||
result = libab_convert_lex_result(eval_config_add(&ab->lexer.config, op_buffer, TOKEN_OP));
|
||||
}
|
||||
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
|
@ -79,7 +79,7 @@ libab_result _register_operator(libab* ab, const char* op, int token_type, int p
|
|||
if(result != LIBAB_SUCCESS) {
|
||||
if(new_entry && new_entry->data_u.op.behavior.type)
|
||||
libab_parsetype_free_recursive(new_entry->data_u.op.behavior.type);
|
||||
eval_config_remove(&ab->lexer.config, op, token_type);
|
||||
eval_config_remove(&ab->lexer.config, op, TOKEN_OP);
|
||||
free(new_entry);
|
||||
}
|
||||
|
||||
|
@ -87,15 +87,15 @@ libab_result _register_operator(libab* ab, const char* op, int token_type, int p
|
|||
}
|
||||
|
||||
libab_result libab_register_operator_infix(libab* ab, const char* op, int precedence, int associativity, const char* type, libab_function_ptr func) {
|
||||
return _register_operator(ab, op, TOKEN_OP_INFIX, precedence, associativity, type, func);
|
||||
return _register_operator(ab, op, OPERATOR_INFIX, precedence, associativity, type, func);
|
||||
}
|
||||
|
||||
libab_result libab_register_operator_prefix(libab* ab, const char* op, const char* type, libab_function_ptr func) {
|
||||
return _register_operator(ab, op, TOKEN_OP_PREFIX, 0, 0, type, func);
|
||||
return _register_operator(ab, op, OPERATOR_PREFIX, 0, 0, type, func);
|
||||
}
|
||||
|
||||
libab_result libab_register_operator_postfix(libab* ab, const char* op, const char* type, libab_function_ptr func) {
|
||||
return _register_operator(ab, op, TOKEN_OP_POSTFIX, 0, 0, type, func);
|
||||
return _register_operator(ab, op, OPERATOR_POSTFIX, 0, 0, type, func);
|
||||
}
|
||||
|
||||
libab_result libab_register_function(libab* ab, const char* name, const char* type, libab_function_ptr func) {
|
||||
|
|
40
src/parser.c
40
src/parser.c
|
@ -748,7 +748,8 @@ libab_result _parser_append_op_node(struct parser_state* state, libab_lexer_matc
|
|||
// Expression-specific utility functions
|
||||
|
||||
int _parser_match_is_op(libab_lexer_match* match) {
|
||||
return match->type == TOKEN_OP_INFIX ||
|
||||
return match->type == TOKEN_OP ||
|
||||
match->type == TOKEN_OP_INFIX ||
|
||||
match->type == TOKEN_OP_PREFIX ||
|
||||
match->type == TOKEN_OP_POSTFIX ||
|
||||
match->type == TOKEN_OP_RESERVED;
|
||||
|
@ -792,7 +793,7 @@ void _parser_find_operator_infix(struct parser_state* state, libab_lexer_match*
|
|||
char op_buffer[8];
|
||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||
if(match->type != TOKEN_OP_RESERVED) {
|
||||
libab_operator* operator = libab_table_search_operator(state->base_table, op_buffer, TOKEN_OP_INFIX);
|
||||
libab_operator* operator = libab_table_search_operator(state->base_table, op_buffer, OPERATOR_INFIX);
|
||||
data->associativity = operator->associativity;
|
||||
data->precedence = operator->precedence;
|
||||
} else {
|
||||
|
@ -856,41 +857,33 @@ libab_result _parser_expression_tree(struct parser_state* state, ll* source, lib
|
|||
|
||||
int _parser_match_is_postfix_op(struct parser_state* state, libab_lexer_match* match) {
|
||||
int is_postfix = 0;
|
||||
if(match->type == TOKEN_OP_POSTFIX) {
|
||||
is_postfix = 1;
|
||||
} else {
|
||||
libab_operator* operator;
|
||||
char op_buffer[8];
|
||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||
operator = libab_table_search_operator(state->base_table, op_buffer, TOKEN_OP_POSTFIX);
|
||||
if(operator) is_postfix = 1;
|
||||
}
|
||||
libab_operator* operator;
|
||||
char op_buffer[8];
|
||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||
operator = libab_table_search_operator(state->base_table, op_buffer, OPERATOR_POSTFIX);
|
||||
if(operator) is_postfix = 1;
|
||||
return is_postfix;
|
||||
}
|
||||
|
||||
int _parser_match_is_prefix_op(struct parser_state* state, libab_lexer_match* match) {
|
||||
int is_prefix = 0;
|
||||
if(match->type == TOKEN_OP_PREFIX) {
|
||||
is_prefix = 1;
|
||||
} else {
|
||||
libab_operator* operator;
|
||||
char op_buffer[8];
|
||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||
operator = libab_table_search_operator(state->base_table, op_buffer, TOKEN_OP_PREFIX);
|
||||
if(operator) is_prefix = 1;
|
||||
}
|
||||
libab_operator* operator;
|
||||
char op_buffer[8];
|
||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||
operator = libab_table_search_operator(state->base_table, op_buffer, OPERATOR_PREFIX);
|
||||
if(operator) is_prefix = 1;
|
||||
return is_prefix;
|
||||
}
|
||||
|
||||
int _parser_match_is_infix_op(struct parser_state* state, libab_lexer_match* match) {
|
||||
int is_infix = 0;
|
||||
if(match->type == TOKEN_OP_INFIX || match->type == TOKEN_OP_RESERVED) {
|
||||
if(match->type == TOKEN_OP_RESERVED) {
|
||||
is_infix = 1;
|
||||
} else {
|
||||
libab_operator* operator;
|
||||
char op_buffer[8];
|
||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||
operator = libab_table_search_operator(state->base_table, op_buffer, TOKEN_OP_INFIX);
|
||||
operator = libab_table_search_operator(state->base_table, op_buffer, OPERATOR_INFIX);
|
||||
if(operator) is_infix = 1;
|
||||
}
|
||||
return is_infix;
|
||||
|
@ -946,7 +939,8 @@ libab_result _parse_expression(struct parser_state* state, libab_tree** store_in
|
|||
_parser_state_step(state);
|
||||
new_type = EXPR_OP_POSTFIX;
|
||||
} else if(_parser_match_is_infix_op(state, new_token)) {
|
||||
new_token->type = TOKEN_OP_INFIX;
|
||||
if(new_token->type == TOKEN_OP)
|
||||
new_token->type = TOKEN_OP_INFIX;
|
||||
_parser_find_operator_infix(state, new_token, &operator);
|
||||
_parser_state_step(state);
|
||||
|
||||
|
|
12
src/table.c
12
src/table.c
|
@ -29,17 +29,17 @@ libab_table_entry* libab_table_search(libab_table* table, const char* string) {
|
|||
return entry->variant == ENTRY_OP && entry->data_u.op.type == TYPE;\
|
||||
}
|
||||
|
||||
OP_TYPE_COMPARATOR(_table_compare_prefix, TOKEN_OP_PREFIX)
|
||||
OP_TYPE_COMPARATOR(_table_compare_infix, TOKEN_OP_INFIX)
|
||||
OP_TYPE_COMPARATOR(_table_compare_postfix, TOKEN_OP_POSTFIX)
|
||||
OP_TYPE_COMPARATOR(_table_compare_prefix, OPERATOR_PREFIX)
|
||||
OP_TYPE_COMPARATOR(_table_compare_infix, OPERATOR_INFIX)
|
||||
OP_TYPE_COMPARATOR(_table_compare_postfix, OPERATOR_POSTFIX)
|
||||
|
||||
libab_operator* libab_table_search_operator(libab_table* table, const char* string, int type) {
|
||||
libab_table_entry* entry = NULL;
|
||||
if(type == TOKEN_OP_PREFIX) {
|
||||
if(type == OPERATOR_PREFIX) {
|
||||
entry = libab_table_search_filter(table, string, NULL, _table_compare_prefix);
|
||||
} else if(type == TOKEN_OP_INFIX) {
|
||||
} else if(type == OPERATOR_INFIX) {
|
||||
entry = libab_table_search_filter(table, string, NULL, _table_compare_infix);
|
||||
} else if(type == TOKEN_OP_POSTFIX) {
|
||||
} else if(type == OPERATOR_PREFIX) {
|
||||
entry = libab_table_search_filter(table, string, NULL, _table_compare_postfix);
|
||||
}
|
||||
return entry ? &entry->data_u.op : NULL;
|
||||
|
|
Loading…
Reference in New Issue
Block a user