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)();
|
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
|
* The common information
|
||||||
* that both operators and functions shared.
|
* that both operators and functions shared.
|
||||||
|
@ -34,7 +44,7 @@ struct libab_operator_s {
|
||||||
* Corresponds to token types associated with
|
* Corresponds to token types associated with
|
||||||
* each operator.
|
* each operator.
|
||||||
*/
|
*/
|
||||||
int type;
|
enum libab_operator_variant_e type;
|
||||||
/**
|
/**
|
||||||
* The precedence of the operator.
|
* The precedence of the operator.
|
||||||
*/
|
*/
|
||||||
|
@ -61,6 +71,7 @@ struct libab_function_s {
|
||||||
struct libab_behavior_s behavior;
|
struct libab_behavior_s behavior;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum libab_operator_variant_e libab_operator_variant;
|
||||||
typedef struct libab_behavior_s libab_behavior;
|
typedef struct libab_behavior_s libab_behavior;
|
||||||
typedef struct libab_operator_s libab_operator;
|
typedef struct libab_operator_s libab_operator;
|
||||||
typedef struct libab_function_s libab_function;
|
typedef struct libab_function_s libab_function;
|
||||||
|
|
|
@ -55,6 +55,7 @@ enum libab_lexer_token_e {
|
||||||
TOKEN_CHAR = 0,
|
TOKEN_CHAR = 0,
|
||||||
TOKEN_ID,
|
TOKEN_ID,
|
||||||
TOKEN_NUM,
|
TOKEN_NUM,
|
||||||
|
TOKEN_OP,
|
||||||
TOKEN_OP_INFIX,
|
TOKEN_OP_INFIX,
|
||||||
TOKEN_OP_PREFIX,
|
TOKEN_OP_PREFIX,
|
||||||
TOKEN_OP_POSTFIX,
|
TOKEN_OP_POSTFIX,
|
||||||
|
|
|
@ -49,7 +49,7 @@ libab_result _initialize_behavior(libab* ab, libab_behavior* behavior,
|
||||||
return result;
|
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];
|
char op_buffer[8];
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_table_entry* new_entry;
|
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) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
_sanitize(op_buffer, op, 8);
|
_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) {
|
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(result != LIBAB_SUCCESS) {
|
||||||
if(new_entry && new_entry->data_u.op.behavior.type)
|
if(new_entry && new_entry->data_u.op.behavior.type)
|
||||||
libab_parsetype_free_recursive(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);
|
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) {
|
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) {
|
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) {
|
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) {
|
libab_result libab_register_function(libab* ab, const char* name, const char* type, libab_function_ptr func) {
|
||||||
|
|
22
src/parser.c
22
src/parser.c
|
@ -748,7 +748,8 @@ libab_result _parser_append_op_node(struct parser_state* state, libab_lexer_matc
|
||||||
// Expression-specific utility functions
|
// Expression-specific utility functions
|
||||||
|
|
||||||
int _parser_match_is_op(libab_lexer_match* match) {
|
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_PREFIX ||
|
||||||
match->type == TOKEN_OP_POSTFIX ||
|
match->type == TOKEN_OP_POSTFIX ||
|
||||||
match->type == TOKEN_OP_RESERVED;
|
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];
|
char op_buffer[8];
|
||||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||||
if(match->type != TOKEN_OP_RESERVED) {
|
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->associativity = operator->associativity;
|
||||||
data->precedence = operator->precedence;
|
data->precedence = operator->precedence;
|
||||||
} else {
|
} 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 _parser_match_is_postfix_op(struct parser_state* state, libab_lexer_match* match) {
|
||||||
int is_postfix = 0;
|
int is_postfix = 0;
|
||||||
if(match->type == TOKEN_OP_POSTFIX) {
|
|
||||||
is_postfix = 1;
|
|
||||||
} else {
|
|
||||||
libab_operator* operator;
|
libab_operator* operator;
|
||||||
char op_buffer[8];
|
char op_buffer[8];
|
||||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||||
operator = libab_table_search_operator(state->base_table, op_buffer, TOKEN_OP_POSTFIX);
|
operator = libab_table_search_operator(state->base_table, op_buffer, OPERATOR_POSTFIX);
|
||||||
if(operator) is_postfix = 1;
|
if(operator) is_postfix = 1;
|
||||||
}
|
|
||||||
return is_postfix;
|
return is_postfix;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _parser_match_is_prefix_op(struct parser_state* state, libab_lexer_match* match) {
|
int _parser_match_is_prefix_op(struct parser_state* state, libab_lexer_match* match) {
|
||||||
int is_prefix = 0;
|
int is_prefix = 0;
|
||||||
if(match->type == TOKEN_OP_PREFIX) {
|
|
||||||
is_prefix = 1;
|
|
||||||
} else {
|
|
||||||
libab_operator* operator;
|
libab_operator* operator;
|
||||||
char op_buffer[8];
|
char op_buffer[8];
|
||||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
||||||
operator = libab_table_search_operator(state->base_table, op_buffer, TOKEN_OP_PREFIX);
|
operator = libab_table_search_operator(state->base_table, op_buffer, OPERATOR_PREFIX);
|
||||||
if(operator) is_prefix = 1;
|
if(operator) is_prefix = 1;
|
||||||
}
|
|
||||||
return is_prefix;
|
return is_prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _parser_match_is_infix_op(struct parser_state* state, libab_lexer_match* match) {
|
int _parser_match_is_infix_op(struct parser_state* state, libab_lexer_match* match) {
|
||||||
int is_infix = 0;
|
int is_infix = 0;
|
||||||
if(match->type == TOKEN_OP_INFIX || match->type == TOKEN_OP_RESERVED) {
|
if(match->type == TOKEN_OP_RESERVED) {
|
||||||
is_infix = 1;
|
is_infix = 1;
|
||||||
} else {
|
} else {
|
||||||
libab_operator* operator;
|
libab_operator* operator;
|
||||||
char op_buffer[8];
|
char op_buffer[8];
|
||||||
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
_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;
|
if(operator) is_infix = 1;
|
||||||
}
|
}
|
||||||
return is_infix;
|
return is_infix;
|
||||||
|
@ -946,6 +939,7 @@ libab_result _parse_expression(struct parser_state* state, libab_tree** store_in
|
||||||
_parser_state_step(state);
|
_parser_state_step(state);
|
||||||
new_type = EXPR_OP_POSTFIX;
|
new_type = EXPR_OP_POSTFIX;
|
||||||
} else if(_parser_match_is_infix_op(state, new_token)) {
|
} else if(_parser_match_is_infix_op(state, new_token)) {
|
||||||
|
if(new_token->type == TOKEN_OP)
|
||||||
new_token->type = TOKEN_OP_INFIX;
|
new_token->type = TOKEN_OP_INFIX;
|
||||||
_parser_find_operator_infix(state, new_token, &operator);
|
_parser_find_operator_infix(state, new_token, &operator);
|
||||||
_parser_state_step(state);
|
_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;\
|
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_prefix, OPERATOR_PREFIX)
|
||||||
OP_TYPE_COMPARATOR(_table_compare_infix, TOKEN_OP_INFIX)
|
OP_TYPE_COMPARATOR(_table_compare_infix, OPERATOR_INFIX)
|
||||||
OP_TYPE_COMPARATOR(_table_compare_postfix, TOKEN_OP_POSTFIX)
|
OP_TYPE_COMPARATOR(_table_compare_postfix, OPERATOR_POSTFIX)
|
||||||
|
|
||||||
libab_operator* libab_table_search_operator(libab_table* table, const char* string, int type) {
|
libab_operator* libab_table_search_operator(libab_table* table, const char* string, int type) {
|
||||||
libab_table_entry* entry = NULL;
|
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);
|
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);
|
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);
|
entry = libab_table_search_filter(table, string, NULL, _table_compare_postfix);
|
||||||
}
|
}
|
||||||
return entry ? &entry->data_u.op : NULL;
|
return entry ? &entry->data_u.op : NULL;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user