Complete the "rearrange" part of Shunting Yard in the parser.
This commit is contained in:
parent
b1aa2a4bf5
commit
68b4fb5807
95
src/parser.c
95
src/parser.c
|
@ -77,28 +77,40 @@ int _parser_match_is_op(libab_lexer_match* match) {
|
||||||
match->type == TOKEN_OP_POSTFIX;
|
match->type == TOKEN_OP_POSTFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _parser_construct_op_node(struct parser_state* state, libab_lexer_match* match, libab_tree** into) {
|
libab_result _parser_construct_node_string(struct parser_state* state, libab_lexer_match* match, libab_tree** into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
if((*into = malloc(sizeof(**into)))) {
|
if(((*into) = malloc(sizeof(**into)))) {
|
||||||
result = _parser_extract_token(state, &(*into)->string_value, match);
|
result = _parser_extract_token(state, &(*into)->string_value, match);
|
||||||
} else {
|
} else {
|
||||||
result = LIBAB_MALLOC;
|
result = LIBAB_MALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
free(*into);
|
||||||
|
*into = NULL;
|
||||||
|
} else {
|
||||||
|
(*into)->from = match->from;
|
||||||
|
(*into)->to = match->to;
|
||||||
|
(*into)->line = match->line;
|
||||||
|
(*into)->line_from = match->line_from;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parser_construct_op_node(struct parser_state* state, libab_lexer_match* match, libab_tree** into) {
|
||||||
|
libab_result result = _parser_construct_node_string(state, match, into);
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
result = libab_convert_ds_result(vec_init(&(*into)->children));
|
result = libab_convert_ds_result(vec_init(&(*into)->children));
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
(*into)->variant = OP;
|
(*into)->variant = OP;
|
||||||
(*into)->from = match->from;
|
|
||||||
(*into)->to = match->to;
|
|
||||||
(*into)->line = match->line;
|
|
||||||
(*into)->line_from = match->line_from;
|
|
||||||
} else {
|
} else {
|
||||||
free((*into)->string_value);
|
free((*into)->string_value);
|
||||||
|
free(*into);
|
||||||
|
*into = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
free(*into);
|
|
||||||
*into = NULL;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +134,6 @@ libab_result _parser_pop_brackets(struct parser_state* state, ll* pop_from, ll*
|
||||||
while(result == LIBAB_SUCCESS && _parser_match_is_op(pop_from->tail->data)) {
|
while(result == LIBAB_SUCCESS && _parser_match_is_op(pop_from->tail->data)) {
|
||||||
libab_lexer_match* new_match = ll_poptail(pop_from);
|
libab_lexer_match* new_match = ll_poptail(pop_from);
|
||||||
result = _parser_append_op_node(state, new_match, push_to);
|
result = _parser_append_op_node(state, new_match, push_to);
|
||||||
free(new_match);
|
|
||||||
}
|
}
|
||||||
remaining_match = (pop_from->tail) ? pop_from->tail->data : NULL;
|
remaining_match = (pop_from->tail) ? pop_from->tail->data : NULL;
|
||||||
*success = remaining_match && (remaining_match->type == TOKEN_CHAR) && (state->string[remaining_match->from] == bracket);
|
*success = remaining_match && (remaining_match->type == TOKEN_CHAR) && (state->string[remaining_match->from] == bracket);
|
||||||
|
@ -147,6 +158,43 @@ int _parser_can_postfix_follow(enum parser_expression_type type) {
|
||||||
return type == EXPR_CLOSE_PARENTH || type == EXPR_ATOM || type == EXPR_OP_POSTFIX;
|
return type == EXPR_CLOSE_PARENTH || type == EXPR_ATOM || type == EXPR_OP_POSTFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libab_operator* _parser_find_operator(struct parser_state* state, libab_lexer_match* match) {
|
||||||
|
char op_buffer[8];
|
||||||
|
size_t token_size = match->to - match->from;
|
||||||
|
size_t buffer_length = (token_size < 7) ? token_size : 7;
|
||||||
|
strncpy(op_buffer, state->string + match->from, buffer_length);
|
||||||
|
op_buffer[buffer_length] = '\0';
|
||||||
|
return libab_table_search_operator(state->base_table, op_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parse_atom(struct parser_state* state, libab_tree** store_into) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
if(_parser_is_type(state, TOKEN_NUM) || _parser_is_type(state, TOKEN_ID)) {
|
||||||
|
result = _parser_construct_node_string(state, state->current_match, store_into);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
(*store_into)->variant = (state->current_match->type == TOKEN_NUM) ? NUM : ID;
|
||||||
|
}
|
||||||
|
_parser_state_step(state);
|
||||||
|
} else {
|
||||||
|
result = LIBAB_UNEXPECTED;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parser_append_atom(struct parser_state* state, ll* append_to) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
libab_tree* tree;
|
||||||
|
result = _parse_atom(state, &tree);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_convert_ds_result(ll_append(append_to, tree));
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
libab_tree_free(tree);
|
||||||
|
free(tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
libab_result _parse_expression(struct parser_state* state, libab_tree** store_into) {
|
libab_result _parse_expression(struct parser_state* state, libab_tree** store_into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
ll out_stack;
|
ll out_stack;
|
||||||
|
@ -170,7 +218,7 @@ libab_result _parse_expression(struct parser_state* state, libab_tree** store_in
|
||||||
} else if(current_char == ')') {
|
} else if(current_char == ')') {
|
||||||
result = _parser_pop_brackets(state, &op_stack, &out_stack, '(', &pop_success);
|
result = _parser_pop_brackets(state, &op_stack, &out_stack, '(', &pop_success);
|
||||||
if(result != LIBAB_SUCCESS || !pop_success) break;
|
if(result != LIBAB_SUCCESS || !pop_success) break;
|
||||||
free(ll_poptail(&op_stack));
|
ll_poptail(&op_stack);
|
||||||
_parser_state_step(state);
|
_parser_state_step(state);
|
||||||
new_type = EXPR_CLOSE_PARENTH;
|
new_type = EXPR_CLOSE_PARENTH;
|
||||||
} else {
|
} else {
|
||||||
|
@ -184,9 +232,32 @@ libab_result _parse_expression(struct parser_state* state, libab_tree** store_in
|
||||||
} else if(new_token->type == TOKEN_OP_POSTFIX && _parser_can_postfix_follow(last_type)) {
|
} else if(new_token->type == TOKEN_OP_POSTFIX && _parser_can_postfix_follow(last_type)) {
|
||||||
result = _parser_append_op_node(state, new_token, &out_stack);
|
result = _parser_append_op_node(state, new_token, &out_stack);
|
||||||
} else if(new_token->type == TOKEN_OP_INFIX) {
|
} else if(new_token->type == TOKEN_OP_INFIX) {
|
||||||
|
libab_operator* operator = _parser_find_operator(state, new_token);
|
||||||
|
_parser_state_step(state);
|
||||||
|
|
||||||
|
while(result == LIBAB_SUCCESS && op_stack.tail &&
|
||||||
|
_parser_match_is_op(op_stack.tail->data)) {
|
||||||
|
libab_operator* other_operator = _parser_find_operator(state, new_token);
|
||||||
|
|
||||||
|
if(new_token->type == TOKEN_OP_PREFIX ||
|
||||||
|
(operator->associativity == -1 &&
|
||||||
|
operator->precedence <= other_operator->precedence) ||
|
||||||
|
(operator->associativity == 1 &&
|
||||||
|
operator->precedence < other_operator->precedence)) {
|
||||||
|
libab_lexer_match* match = ll_poptail(&op_stack);
|
||||||
|
result = _parser_append_op_node(state, match, &out_stack);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_convert_ds_result(ll_append(&op_stack, new_token));
|
||||||
|
}
|
||||||
|
new_type = EXPR_OP_INFIX;
|
||||||
} else {
|
} else {
|
||||||
|
if(last_type == EXPR_ATOM) break;
|
||||||
|
result = _parser_append_atom(state, &out_stack);
|
||||||
|
new_type = EXPR_ATOM;
|
||||||
}
|
}
|
||||||
last_type = new_type;
|
last_type = new_type;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user