2018-02-10 22:40:34 -08:00
|
|
|
#include "parser.h"
|
|
|
|
#include "lexer.h"
|
2018-04-21 14:09:01 -07:00
|
|
|
#include "reserved.h"
|
|
|
|
#include "result.h"
|
|
|
|
#include "util.h"
|
2018-02-10 22:40:34 -08:00
|
|
|
#include <stdlib.h>
|
2018-02-11 13:42:05 -08:00
|
|
|
#include <string.h>
|
2018-02-10 22:40:34 -08:00
|
|
|
|
2018-02-10 22:17:08 -08:00
|
|
|
struct parser_state {
|
|
|
|
ll_node* current_node;
|
2018-02-11 21:09:41 -08:00
|
|
|
libab_lexer_match* current_match;
|
2018-02-21 18:55:05 -08:00
|
|
|
libab_lexer_match* last_match;
|
2018-02-10 22:17:08 -08:00
|
|
|
const char* string;
|
2018-02-11 22:23:02 -08:00
|
|
|
libab_table* base_table;
|
2018-02-10 22:17:08 -08:00
|
|
|
};
|
|
|
|
|
2018-03-16 23:09:41 -07:00
|
|
|
struct operator_data {
|
|
|
|
int associativity;
|
|
|
|
int precedence;
|
|
|
|
};
|
|
|
|
|
2018-03-18 19:21:09 -07:00
|
|
|
/* Utilities */
|
2018-04-21 14:09:01 -07:00
|
|
|
#define PARSE_CHILD(result, state, parse_function, parse_into, into) \
|
|
|
|
do { \
|
|
|
|
result = parse_function(state, &parse_into); \
|
|
|
|
if (result == LIBAB_SUCCESS) { \
|
|
|
|
result = libab_convert_ds_result(vec_add(into, parse_into)); \
|
|
|
|
if (result != LIBAB_SUCCESS) { \
|
|
|
|
libab_tree_free_recursive(parse_into); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} while (0);
|
2018-02-27 11:29:59 -08:00
|
|
|
|
2018-03-17 17:39:44 -07:00
|
|
|
void _parser_extract_token_buffer(struct parser_state* state, char* buffer,
|
2018-04-21 14:09:01 -07:00
|
|
|
size_t length, libab_lexer_match* match) {
|
2018-03-17 17:39:44 -07:00
|
|
|
size_t token_size = match->to - match->from;
|
2018-04-21 14:09:01 -07:00
|
|
|
size_t buffer_length =
|
|
|
|
(token_size < (length - 1)) ? token_size : (length - 1);
|
2018-03-17 17:39:44 -07:00
|
|
|
strncpy(buffer, state->string + match->from, buffer_length);
|
|
|
|
buffer[buffer_length] = '\0';
|
|
|
|
}
|
|
|
|
|
2018-02-17 20:16:50 -08:00
|
|
|
int _parser_foreach_free_tree(void* data, va_list args) {
|
2018-06-12 02:09:51 -07:00
|
|
|
libab_tree_free_recursive(data);
|
2018-02-17 20:16:50 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_extract_token(struct parser_state* state, char** into,
|
|
|
|
libab_lexer_match* match) {
|
2018-03-06 16:47:11 -08:00
|
|
|
return libab_copy_string_range(into, state->string, match->from, match->to);
|
2018-02-17 20:16:50 -08:00
|
|
|
}
|
|
|
|
|
2018-03-18 19:21:09 -07:00
|
|
|
/* State functions */
|
2018-02-10 22:17:08 -08:00
|
|
|
void _parser_state_update(struct parser_state* state) {
|
2018-04-21 14:09:01 -07:00
|
|
|
state->current_match =
|
|
|
|
state->current_node ? state->current_node->data : NULL;
|
|
|
|
if (state->current_match)
|
|
|
|
state->last_match = state->current_match;
|
2018-02-10 22:17:08 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
void _parser_state_init(struct parser_state* state, ll* tokens,
|
|
|
|
const char* string, libab_table* table) {
|
2018-02-21 18:55:05 -08:00
|
|
|
state->last_match = NULL;
|
2018-02-10 22:17:08 -08:00
|
|
|
state->current_node = tokens->head;
|
|
|
|
state->string = string;
|
2018-02-11 22:23:02 -08:00
|
|
|
state->base_table = table;
|
2018-02-10 22:17:08 -08:00
|
|
|
_parser_state_update(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
void _parser_state_step(struct parser_state* state) {
|
2018-04-21 14:09:01 -07:00
|
|
|
if (state->current_node) {
|
2018-02-10 22:17:08 -08:00
|
|
|
state->current_node = state->current_node->next;
|
|
|
|
}
|
|
|
|
_parser_state_update(state);
|
|
|
|
}
|
2018-02-10 22:40:34 -08:00
|
|
|
|
|
|
|
int _parser_is_char(struct parser_state* state, char to_expect) {
|
|
|
|
return (state->current_match && state->current_match->type == TOKEN_CHAR &&
|
|
|
|
state->string[state->current_match->from] == to_expect);
|
|
|
|
}
|
|
|
|
|
2018-02-11 21:09:41 -08:00
|
|
|
int _parser_is_type(struct parser_state* state, libab_lexer_token to_expect) {
|
2018-02-10 23:06:37 -08:00
|
|
|
return (state->current_match && state->current_match->type == to_expect);
|
|
|
|
}
|
|
|
|
|
2018-02-10 22:40:34 -08:00
|
|
|
int _parser_eof(struct parser_state* state) {
|
|
|
|
return state->current_match == NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
libab_result _parser_consume_char(struct parser_state* state, char to_consume) {
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-04-21 14:09:01 -07:00
|
|
|
if (state->current_match == NULL) {
|
2018-02-10 22:40:34 -08:00
|
|
|
result = LIBAB_EOF;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (state->current_match->type != TOKEN_CHAR ||
|
|
|
|
state->string[state->current_match->from] != to_consume) {
|
2018-02-10 22:40:34 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
} else {
|
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-20 16:38:02 -08:00
|
|
|
libab_result _parser_consume_type(struct parser_state* state,
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_lexer_token to_consume) {
|
2018-02-20 16:38:02 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-04-21 14:09:01 -07:00
|
|
|
if (state->current_match == NULL) {
|
2018-02-20 16:38:02 -08:00
|
|
|
result = LIBAB_EOF;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (state->current_match->type != to_consume) {
|
2018-02-20 16:38:02 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
} else {
|
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-03-18 19:21:09 -07:00
|
|
|
/* Basic Tree Constructors */
|
2018-02-10 23:06:37 -08:00
|
|
|
|
2018-02-17 20:16:50 -08:00
|
|
|
libab_result _parse_block(struct parser_state*, libab_tree**, int);
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_expression(struct parser_state* state,
|
|
|
|
libab_tree** store_into);
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_result _parse_type(struct parser_state* state, libab_ref* ref);
|
2018-03-06 16:47:11 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_braced_block(struct parser_state* state,
|
|
|
|
libab_tree** store_into) {
|
2018-03-08 21:10:05 -08:00
|
|
|
return _parse_block(state, store_into, 1);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_allocate_type(libab_parsetype** into, const char* source,
|
|
|
|
size_t from, size_t to) {
|
2018-03-06 16:47:11 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-04-21 14:09:01 -07:00
|
|
|
if ((*into = malloc(sizeof(**into)))) {
|
2018-04-17 15:49:09 -07:00
|
|
|
(*into)->variant = 0;
|
2018-04-21 14:09:01 -07:00
|
|
|
result =
|
|
|
|
libab_copy_string_range(&(*into)->data_u.name, source, from, to);
|
2018-03-06 16:47:11 -08:00
|
|
|
} else {
|
|
|
|
result = LIBAB_MALLOC;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-03-06 16:47:11 -08:00
|
|
|
free(*into);
|
|
|
|
*into = NULL;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_append_type(struct parser_state* state,
|
|
|
|
libab_ref_vec* into) {
|
2018-03-06 16:47:11 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_ref temp;
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parse_type(state, &temp);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-04-17 22:14:07 -07:00
|
|
|
result = libab_ref_vec_insert(into, &temp);
|
|
|
|
libab_ref_free(&temp);
|
2018-03-06 16:47:11 -08:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_type_list(struct parser_state* state, libab_ref_vec* into,
|
|
|
|
char end_char) {
|
2018-03-06 16:47:11 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
int is_parenth, is_comma;
|
2018-04-21 14:09:01 -07:00
|
|
|
while (result == LIBAB_SUCCESS && !_parser_eof(state) &&
|
|
|
|
!_parser_is_char(state, end_char)) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parser_append_type(state, into);
|
|
|
|
is_parenth = _parser_is_char(state, end_char);
|
|
|
|
is_comma = _parser_is_char(state, ',');
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS && !(is_parenth || is_comma)) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (result == LIBAB_SUCCESS && is_comma) {
|
2018-03-06 16:47:11 -08:00
|
|
|
_parser_state_step(state);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_char(state, end_char)) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parser_consume_char(state, end_char);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_type_id(struct parser_state* state,
|
|
|
|
libab_parsetype** into) {
|
2018-04-07 14:50:06 -07:00
|
|
|
libab_result result;
|
|
|
|
int placeholder_flag = 0;
|
|
|
|
*into = NULL;
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_char(state, '\'')) {
|
2018-04-17 15:49:09 -07:00
|
|
|
placeholder_flag = LIBABACUS_TYPE_F_PLACE;
|
2018-04-07 14:50:06 -07:00
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_type(state, TOKEN_ID)) {
|
|
|
|
result = _parser_allocate_type(into, state->string,
|
|
|
|
state->current_match->from,
|
|
|
|
state->current_match->to);
|
2018-04-07 14:50:06 -07:00
|
|
|
} else {
|
|
|
|
result = _parser_consume_type(state, TOKEN_ID);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-04-17 15:49:09 -07:00
|
|
|
(*into)->variant |= placeholder_flag;
|
2018-03-06 16:47:11 -08:00
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS && _parser_is_char(state, '(')) {
|
|
|
|
if (placeholder_flag) {
|
2018-04-07 14:50:06 -07:00
|
|
|
result = LIBAB_UNEXPECTED;
|
2018-03-06 16:47:11 -08:00
|
|
|
} else {
|
2018-04-17 22:14:07 -07:00
|
|
|
result = libab_ref_vec_init(&(*into)->children);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-04-17 15:49:09 -07:00
|
|
|
free((*into)->data_u.name);
|
2018-04-07 14:50:06 -07:00
|
|
|
free(*into);
|
|
|
|
*into = NULL;
|
|
|
|
} else {
|
2018-04-17 15:49:09 -07:00
|
|
|
(*into)->variant |= LIBABACUS_TYPE_F_PARENT;
|
2018-04-07 14:50:06 -07:00
|
|
|
_parser_state_step(state);
|
|
|
|
result = _parse_type_list(state, &(*into)->children, ')');
|
|
|
|
}
|
2018-03-06 16:47:11 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS && *into) {
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_parsetype_free(*into);
|
2018-03-06 16:47:11 -08:00
|
|
|
*into = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2018-04-21 14:09:01 -07:00
|
|
|
}
|
2018-03-06 16:47:11 -08:00
|
|
|
|
|
|
|
libab_result _parse_type_function(struct parser_state* state,
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_parsetype** into) {
|
2018-03-06 16:47:11 -08:00
|
|
|
libab_result result = _parser_allocate_type(into, "function", 0, 8);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-04-17 15:49:09 -07:00
|
|
|
(*into)->variant |= LIBABACUS_TYPE_F_PARENT;
|
2018-04-17 22:14:07 -07:00
|
|
|
result = libab_ref_vec_init(&(*into)->children);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-04-17 15:49:09 -07:00
|
|
|
free((*into)->data_u.name);
|
2018-03-06 16:47:11 -08:00
|
|
|
free(*into);
|
|
|
|
*into = NULL;
|
|
|
|
} else {
|
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parse_type_list(state, &(*into)->children, ')');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parser_consume_type(state, TOKEN_KW_ARROW);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parser_append_type(state, &(*into)->children);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS && *into) {
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_parsetype_free(*into);
|
2018-03-06 16:47:11 -08:00
|
|
|
*into = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
libab_result _parse_type_array(struct parser_state* state,
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_parsetype** into) {
|
2018-03-06 16:47:11 -08:00
|
|
|
libab_result result = _parser_allocate_type(into, "array", 0, 5);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-04-17 15:49:09 -07:00
|
|
|
(*into)->variant |= LIBABACUS_TYPE_F_PARENT;
|
2018-04-17 22:14:07 -07:00
|
|
|
result = libab_ref_vec_init(&(*into)->children);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-04-17 15:49:09 -07:00
|
|
|
free((*into)->data_u.name);
|
2018-03-06 16:47:11 -08:00
|
|
|
free(*into);
|
|
|
|
*into = NULL;
|
|
|
|
} else {
|
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parser_append_type(state, &(*into)->children);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parser_consume_char(state, ']');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS && *into) {
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_parsetype_free(*into);
|
2018-03-06 16:47:11 -08:00
|
|
|
*into = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_type_raw(struct parser_state* state,
|
|
|
|
libab_parsetype** into) {
|
2018-03-06 16:47:11 -08:00
|
|
|
libab_result result;
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_type(state, TOKEN_ID) || _parser_is_char(state, '\'')) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parse_type_id(state, into);
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_char(state, '(')) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parse_type_function(state, into);
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_char(state, '[')) {
|
2018-03-06 16:47:11 -08:00
|
|
|
result = _parse_type_array(state, into);
|
|
|
|
} else {
|
|
|
|
*into = NULL;
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2018-02-15 23:12:47 -08:00
|
|
|
|
2018-04-21 17:05:51 -07:00
|
|
|
void _parse_type_free(void* data) {
|
|
|
|
libab_parsetype_free(data);
|
|
|
|
free(data);
|
|
|
|
}
|
2018-04-17 22:14:07 -07:00
|
|
|
|
|
|
|
libab_result _parse_type(struct parser_state* state, libab_ref* into) {
|
|
|
|
libab_parsetype* store_into;
|
|
|
|
libab_result result = _parse_type_raw(state, &store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-04-17 22:14:07 -07:00
|
|
|
result = libab_ref_new(into, store_into, _parse_type_free);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_parsetype_free(store_into);
|
|
|
|
}
|
|
|
|
}
|
2018-04-22 21:24:43 -07:00
|
|
|
|
2018-05-17 14:53:48 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-04-22 21:24:43 -07:00
|
|
|
libab_ref_null(into);
|
|
|
|
}
|
|
|
|
|
2018-04-17 22:14:07 -07:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_allocate_node(libab_lexer_match* match,
|
|
|
|
libab_tree** into) {
|
2018-02-15 23:12:47 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-04-21 14:09:01 -07:00
|
|
|
if (((*into) = malloc(sizeof(**into))) == NULL) {
|
2018-02-15 23:12:47 -08:00
|
|
|
result = LIBAB_MALLOC;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (match) {
|
2018-02-17 16:01:04 -08:00
|
|
|
(*into)->from = match->from;
|
|
|
|
(*into)->to = match->to;
|
|
|
|
(*into)->line = match->line;
|
|
|
|
(*into)->line_from = match->line_from;
|
|
|
|
}
|
2018-02-20 13:11:40 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_construct_node_string(struct parser_state* state,
|
|
|
|
libab_lexer_match* match,
|
|
|
|
libab_tree** into) {
|
2018-02-21 19:06:00 -08:00
|
|
|
libab_result result = _parser_allocate_node(match, into);
|
2018-02-20 13:11:40 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-20 13:11:40 -08:00
|
|
|
result = _parser_extract_token(state, &(*into)->string_value, match);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-02-20 13:11:40 -08:00
|
|
|
free(*into);
|
|
|
|
*into = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_construct_node_vec(libab_lexer_match* match,
|
|
|
|
libab_tree** into) {
|
2018-02-21 19:06:00 -08:00
|
|
|
libab_result result = _parser_allocate_node(match, into);
|
2018-02-20 13:11:40 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-20 13:11:40 -08:00
|
|
|
result = libab_convert_ds_result(vec_init(&(*into)->children));
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-02-20 13:11:40 -08:00
|
|
|
free(*into);
|
|
|
|
*into = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2018-02-17 16:01:04 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_construct_node_both(struct parser_state* state,
|
|
|
|
libab_lexer_match* match,
|
|
|
|
libab_tree** store_into) {
|
|
|
|
libab_result result =
|
|
|
|
_parser_construct_node_string(state, match, store_into);
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-24 20:07:44 -08:00
|
|
|
result = libab_convert_ds_result(vec_init(&(*store_into)->children));
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-02-24 20:07:44 -08:00
|
|
|
free((*store_into)->string_value);
|
|
|
|
free(*store_into);
|
|
|
|
*store_into = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-27 11:29:59 -08:00
|
|
|
libab_result _parse_void(struct parser_state* state, libab_tree** store_into) {
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-04-21 14:09:01 -07:00
|
|
|
if ((*store_into = malloc(sizeof(**store_into)))) {
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_VOID;
|
2018-02-27 11:29:59 -08:00
|
|
|
} else {
|
|
|
|
result = LIBAB_MALLOC;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-20 16:38:02 -08:00
|
|
|
libab_result _parse_if(struct parser_state* state, libab_tree** store_into) {
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-02-21 18:58:32 -08:00
|
|
|
libab_tree* condition = NULL;
|
|
|
|
libab_tree* if_branch = NULL;
|
|
|
|
libab_tree* else_branch = NULL;
|
2018-02-20 16:38:02 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_type(state, TOKEN_KW_IF)) {
|
2018-02-21 19:06:00 -08:00
|
|
|
result = _parser_construct_node_vec(state->current_match, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_IF;
|
2018-02-24 20:07:54 -08:00
|
|
|
_parser_state_step(state);
|
2018-02-21 19:00:04 -08:00
|
|
|
}
|
2018-02-24 20:07:54 -08:00
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
2018-02-20 16:38:02 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-20 16:38:02 -08:00
|
|
|
result = _parser_consume_char(state, '(');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, condition,
|
|
|
|
&(*store_into)->children);
|
2018-02-20 16:38:02 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-20 16:38:02 -08:00
|
|
|
result = _parser_consume_char(state, ')');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, if_branch,
|
|
|
|
&(*store_into)->children);
|
2018-02-20 16:38:02 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
if (_parser_is_type(state, TOKEN_KW_ELSE)) {
|
2018-02-20 16:38:02 -08:00
|
|
|
_parser_state_step(state);
|
2018-04-21 14:09:01 -07:00
|
|
|
PARSE_CHILD(result, state, _parse_expression, else_branch,
|
|
|
|
&(*store_into)->children);
|
2018-02-20 16:38:02 -08:00
|
|
|
} else {
|
2018-04-21 14:09:01 -07:00
|
|
|
PARSE_CHILD(result, state, _parse_void, else_branch,
|
|
|
|
&(*store_into)->children);
|
2018-02-20 16:38:02 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
if (*store_into)
|
|
|
|
libab_tree_free_recursive(*store_into);
|
2018-02-20 16:38:02 -08:00
|
|
|
*store_into = NULL;
|
|
|
|
}
|
|
|
|
|
2018-02-17 16:01:04 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_fun_param(struct parser_state* state,
|
|
|
|
libab_tree** store_into) {
|
2018-03-08 21:10:05 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_type(state, TOKEN_ID)) {
|
|
|
|
result = _parser_construct_node_string(state, state->current_match,
|
|
|
|
store_into);
|
2018-03-08 21:10:05 -08:00
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:10:05 -08:00
|
|
|
_parser_state_step(state);
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_FUN_PARAM;
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_ref_null(&(*store_into)->type);
|
2018-03-08 21:10:05 -08:00
|
|
|
result = _parser_consume_char(state, ':');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_ref_free(&(*store_into)->type);
|
|
|
|
result = _parse_type(state, &(*store_into)->type);
|
2018-03-08 21:10:05 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS && *store_into) {
|
2018-03-08 21:10:05 -08:00
|
|
|
libab_tree_free_recursive(*store_into);
|
|
|
|
*store_into = NULL;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
libab_result _parse_fun(struct parser_state* state, libab_tree** store_into) {
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
int is_parenth, is_comma;
|
|
|
|
libab_tree* temp;
|
|
|
|
result = _parser_consume_type(state, TOKEN_KW_FUN);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
if (_parser_is_type(state, TOKEN_ID)) {
|
|
|
|
result = _parser_construct_node_both(state, state->current_match,
|
|
|
|
store_into);
|
2018-03-08 21:10:05 -08:00
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:10:05 -08:00
|
|
|
_parser_state_step(state);
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_ref_null(&(*store_into)->type);
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_FUN;
|
2018-06-12 23:34:18 -07:00
|
|
|
(*store_into)->int_value = 1;
|
2018-03-08 21:10:05 -08:00
|
|
|
result = _parser_consume_char(state, '(');
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
while (result == LIBAB_SUCCESS && !_parser_eof(state) &&
|
|
|
|
!_parser_is_char(state, ')')) {
|
|
|
|
PARSE_CHILD(result, state, _parse_fun_param, temp,
|
|
|
|
&(*store_into)->children);
|
2018-03-08 21:10:05 -08:00
|
|
|
is_parenth = _parser_is_char(state, ')');
|
|
|
|
is_comma = _parser_is_char(state, ',');
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS && !(is_parenth || is_comma)) {
|
2018-03-08 21:10:05 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (result == LIBAB_SUCCESS && is_comma) {
|
2018-03-08 21:10:05 -08:00
|
|
|
_parser_state_step(state);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_char(state, ')')) {
|
2018-03-08 21:10:05 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:10:05 -08:00
|
|
|
result = _parser_consume_char(state, ')');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:10:05 -08:00
|
|
|
result = _parser_consume_char(state, ':');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-04-17 22:14:07 -07:00
|
|
|
libab_ref_free(&(*store_into)->type);
|
|
|
|
result = _parse_type(state, &(*store_into)->type);
|
2018-03-08 21:10:05 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
PARSE_CHILD(result, state, _parse_braced_block, temp,
|
|
|
|
&(*store_into)->children);
|
2018-03-08 21:10:05 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS && *store_into) {
|
2018-03-08 21:10:05 -08:00
|
|
|
libab_tree_free_recursive(*store_into);
|
|
|
|
*store_into = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_return(struct parser_state* state,
|
|
|
|
libab_tree** store_into) {
|
2018-03-08 21:31:24 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
libab_tree* child = NULL;
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_type(state, TOKEN_KW_RETURN)) {
|
2018-03-08 21:31:24 -08:00
|
|
|
result = _parser_construct_node_vec(state->current_match, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:31:24 -08:00
|
|
|
(*store_into)->variant = TREE_RETURN;
|
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, child,
|
|
|
|
&(*store_into)->children);
|
2018-03-08 21:31:24 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
if (*store_into)
|
|
|
|
libab_tree_free_recursive(*store_into);
|
2018-03-08 21:31:24 -08:00
|
|
|
*store_into = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-27 11:57:45 -08:00
|
|
|
libab_result _parse_while(struct parser_state* state, libab_tree** store_into) {
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
libab_tree* condition = NULL;
|
|
|
|
libab_tree* value = NULL;
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_type(state, TOKEN_KW_WHILE)) {
|
2018-02-27 11:57:45 -08:00
|
|
|
result = _parser_construct_node_vec(state->current_match, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_WHILE;
|
2018-02-27 11:57:45 -08:00
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-27 11:57:45 -08:00
|
|
|
result = _parser_consume_char(state, '(');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, condition,
|
|
|
|
&(*store_into)->children);
|
2018-02-27 11:57:45 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-27 11:57:45 -08:00
|
|
|
result = _parser_consume_char(state, ')');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, value,
|
|
|
|
&(*store_into)->children);
|
2018-02-27 11:57:45 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
if (*store_into)
|
|
|
|
libab_tree_free_recursive(*store_into);
|
2018-02-27 11:57:45 -08:00
|
|
|
*store_into = NULL;
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
|
2018-02-27 11:57:45 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_dowhile(struct parser_state* state,
|
|
|
|
libab_tree** store_into) {
|
2018-02-27 12:30:37 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
libab_tree* value = NULL;
|
|
|
|
libab_tree* condition = NULL;
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_type(state, TOKEN_KW_DO)) {
|
2018-02-27 12:30:37 -08:00
|
|
|
result = _parser_construct_node_vec(state->current_match, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_DOWHILE;
|
2018-02-27 12:30:37 -08:00
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, value,
|
|
|
|
&(*store_into)->children);
|
2018-02-27 12:30:37 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-27 12:30:37 -08:00
|
|
|
result = _parser_consume_type(state, TOKEN_KW_WHILE);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-27 12:30:37 -08:00
|
|
|
result = _parser_consume_char(state, '(');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, condition,
|
|
|
|
&(*store_into)->children);
|
2018-02-27 12:30:37 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-27 12:30:37 -08:00
|
|
|
result = _parser_consume_char(state, ')');
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-24 20:08:17 -08:00
|
|
|
libab_result _parse_call(struct parser_state* state, libab_tree** store_into) {
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-02-24 20:08:17 -08:00
|
|
|
libab_tree* temp;
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_char(state, '(')) {
|
2018-02-25 14:06:15 -08:00
|
|
|
result = _parser_construct_node_vec(state->current_match, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_CALL;
|
2018-02-24 20:08:17 -08:00
|
|
|
}
|
|
|
|
_parser_state_step(state);
|
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
while (result == LIBAB_SUCCESS && !_parser_eof(state) &&
|
|
|
|
!_parser_is_char(state, ')')) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, temp,
|
|
|
|
&(*store_into)->children);
|
2018-02-24 20:08:17 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS &&
|
|
|
|
!(_parser_is_char(state, ')') || _parser_is_char(state, ','))) {
|
2018-02-24 20:08:17 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_char(state, ',')) {
|
2018-02-24 20:08:17 -08:00
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-24 20:08:17 -08:00
|
|
|
result = _parser_consume_char(state, ')');
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
if (*store_into)
|
|
|
|
libab_tree_free_recursive(*store_into);
|
2018-02-24 20:08:17 -08:00
|
|
|
*store_into = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-25 14:06:15 -08:00
|
|
|
libab_result _parser_append_call(struct parser_state* state, ll* append_to) {
|
|
|
|
libab_result result;
|
|
|
|
libab_tree* into;
|
|
|
|
result = _parse_call(state, &into);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-25 14:06:15 -08:00
|
|
|
result = libab_convert_ds_result(ll_append(append_to, into));
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-02-25 14:06:15 -08:00
|
|
|
libab_tree_free_recursive(into);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-17 20:16:50 -08:00
|
|
|
libab_result _parse_atom(struct parser_state* state, libab_tree** store_into) {
|
2018-02-21 19:06:00 -08:00
|
|
|
libab_result result;
|
2018-04-21 14:09:01 -07:00
|
|
|
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) ? TREE_NUM : TREE_ID;
|
2018-02-17 20:16:50 -08:00
|
|
|
}
|
|
|
|
_parser_state_step(state);
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_type(state, TOKEN_KW_IF)) {
|
2018-02-20 16:38:02 -08:00
|
|
|
result = _parse_if(state, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_type(state, TOKEN_KW_WHILE)) {
|
2018-02-27 11:57:45 -08:00
|
|
|
result = _parse_while(state, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_type(state, TOKEN_KW_DO)) {
|
2018-02-27 12:30:37 -08:00
|
|
|
result = _parse_dowhile(state, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_char(state, '{')) {
|
2018-03-08 21:10:05 -08:00
|
|
|
result = _parse_braced_block(state, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_type(state, TOKEN_KW_FUN)) {
|
2018-03-08 21:10:05 -08:00
|
|
|
result = _parse_fun(state, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_is_type(state, TOKEN_KW_RETURN)) {
|
2018-03-08 21:31:24 -08:00
|
|
|
result = _parse_return(state, store_into);
|
2018-02-17 20:16:50 -08:00
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
libab_result _parser_append_atom(struct parser_state* state, ll* append_to) {
|
2018-02-21 19:06:00 -08:00
|
|
|
libab_result result;
|
2018-02-17 20:16:50 -08:00
|
|
|
libab_tree* tree;
|
|
|
|
result = _parse_atom(state, &tree);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-17 20:16:50 -08:00
|
|
|
result = libab_convert_ds_result(ll_append(append_to, tree));
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-02-17 20:16:50 -08:00
|
|
|
libab_tree_free_recursive(tree);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_construct_op(struct parser_state* state,
|
|
|
|
libab_lexer_match* match, libab_tree** into) {
|
2018-02-24 20:07:44 -08:00
|
|
|
libab_result result = _parser_construct_node_both(state, match, into);
|
2018-02-17 16:01:04 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
if (match->type == TOKEN_OP_INFIX) {
|
2018-03-16 23:09:41 -07:00
|
|
|
(*into)->variant = TREE_OP;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (match->type == TOKEN_OP_RESERVED) {
|
2018-03-16 23:09:41 -07:00
|
|
|
(*into)->variant = TREE_RESERVED_OP;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (match->type == TOKEN_OP_PREFIX) {
|
2018-03-17 18:25:23 -07:00
|
|
|
(*into)->variant = TREE_PREFIX_OP;
|
2018-03-16 23:09:41 -07:00
|
|
|
} else {
|
2018-03-17 18:25:23 -07:00
|
|
|
(*into)->variant = TREE_POSTFIX_OP;
|
2018-03-16 23:09:41 -07:00
|
|
|
}
|
2018-02-15 23:12:47 -08:00
|
|
|
}
|
2018-02-24 20:07:44 -08:00
|
|
|
|
2018-02-15 23:12:47 -08:00
|
|
|
return result;
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_append_op_node(struct parser_state* state,
|
|
|
|
libab_lexer_match* match, ll* append_to) {
|
2018-02-21 19:06:00 -08:00
|
|
|
libab_result result;
|
2018-02-17 14:04:59 -08:00
|
|
|
libab_tree* new_tree = NULL;
|
2018-02-17 21:33:33 -08:00
|
|
|
result = _parser_construct_op(state, match, &new_tree);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-17 14:04:59 -08:00
|
|
|
result = libab_convert_ds_result(ll_append(append_to, new_tree));
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
2018-02-17 14:04:59 -08:00
|
|
|
libab_tree_free(new_tree);
|
|
|
|
free(new_tree);
|
|
|
|
}
|
2018-02-21 18:55:05 -08:00
|
|
|
}
|
2018-02-17 14:04:59 -08:00
|
|
|
return result;
|
|
|
|
}
|
2018-02-17 14:40:30 -08:00
|
|
|
|
2018-03-18 19:21:09 -07:00
|
|
|
/* Expression-specific utility functions */
|
2018-02-17 20:16:50 -08:00
|
|
|
|
|
|
|
int _parser_match_is_op(libab_lexer_match* match) {
|
2018-04-21 14:09:01 -07:00
|
|
|
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;
|
2018-02-17 20:16:50 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_pop_brackets(struct parser_state* state, ll* pop_from,
|
|
|
|
ll* push_to, char bracket, int* success) {
|
2018-02-17 14:40:30 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
libab_lexer_match* remaining_match;
|
2018-04-21 14:09:01 -07:00
|
|
|
while (result == LIBAB_SUCCESS && pop_from->tail &&
|
|
|
|
_parser_match_is_op(pop_from->tail->data)) {
|
2018-02-17 14:40:30 -08:00
|
|
|
libab_lexer_match* new_match = ll_poptail(pop_from);
|
|
|
|
result = _parser_append_op_node(state, new_match, push_to);
|
|
|
|
}
|
|
|
|
remaining_match = (pop_from->tail) ? pop_from->tail->data : NULL;
|
2018-04-21 14:09:01 -07:00
|
|
|
*success = remaining_match && (remaining_match->type == TOKEN_CHAR) &&
|
|
|
|
(state->string[remaining_match->from] == bracket);
|
2018-02-17 14:40:30 -08:00
|
|
|
return result;
|
|
|
|
}
|
2018-02-17 14:40:43 -08:00
|
|
|
|
|
|
|
enum parser_expression_type {
|
|
|
|
EXPR_NONE,
|
|
|
|
EXPR_ATOM,
|
|
|
|
EXPR_OPEN_PARENTH,
|
|
|
|
EXPR_CLOSE_PARENTH,
|
|
|
|
EXPR_OP_PREFIX,
|
|
|
|
EXPR_OP_POSTFIX,
|
|
|
|
EXPR_OP_INFIX
|
|
|
|
};
|
|
|
|
|
|
|
|
int _parser_can_prefix_follow(enum parser_expression_type type) {
|
2018-04-21 14:09:01 -07:00
|
|
|
return type == EXPR_OPEN_PARENTH || type == EXPR_OP_PREFIX ||
|
|
|
|
type == EXPR_OP_INFIX || type == EXPR_NONE;
|
2018-02-17 14:40:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
int _parser_can_postfix_follow(enum parser_expression_type type) {
|
2018-04-21 14:09:01 -07:00
|
|
|
return type == EXPR_CLOSE_PARENTH || type == EXPR_ATOM ||
|
|
|
|
type == EXPR_OP_POSTFIX;
|
2018-02-17 14:40:43 -08:00
|
|
|
}
|
|
|
|
|
2018-02-27 11:45:51 -08:00
|
|
|
int _parser_can_atom_follow(enum parser_expression_type type) {
|
2018-04-21 14:09:01 -07:00
|
|
|
return !(type == EXPR_CLOSE_PARENTH || type == EXPR_OP_POSTFIX ||
|
|
|
|
type == EXPR_ATOM);
|
2018-02-27 11:45:51 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
void _parser_find_operator_infix(struct parser_state* state,
|
|
|
|
libab_lexer_match* match,
|
|
|
|
struct operator_data* data) {
|
2018-02-17 16:01:04 -08:00
|
|
|
char op_buffer[8];
|
2018-03-17 17:39:44 -07:00
|
|
|
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (match->type != TOKEN_OP_RESERVED) {
|
|
|
|
libab_operator* operator= libab_table_search_operator(
|
|
|
|
state->base_table, op_buffer, OPERATOR_INFIX);
|
2018-03-16 23:09:41 -07:00
|
|
|
data->associativity = operator->associativity;
|
|
|
|
data->precedence = operator->precedence;
|
|
|
|
} else {
|
2018-04-21 14:09:01 -07:00
|
|
|
const libab_reserved_operator* operator=
|
|
|
|
libab_find_reserved_operator(op_buffer);
|
2018-03-16 23:09:41 -07:00
|
|
|
data->associativity = operator->associativity;
|
|
|
|
data->precedence = operator->precedence;
|
|
|
|
}
|
2018-02-17 16:01:04 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parser_expression_tree(struct parser_state* state, ll* source,
|
|
|
|
libab_tree** into) {
|
2018-02-17 19:08:35 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
libab_tree* top = ll_poptail(source);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (top == NULL) {
|
2018-02-25 14:06:15 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (top->variant == TREE_OP || top->variant == TREE_RESERVED_OP) {
|
2018-02-17 19:08:35 -08:00
|
|
|
libab_tree* left = NULL;
|
|
|
|
libab_tree* right = NULL;
|
|
|
|
|
|
|
|
result = _parser_expression_tree(state, source, &right);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-17 19:08:35 -08:00
|
|
|
result = _parser_expression_tree(state, source, &left);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-17 19:08:35 -08:00
|
|
|
result = libab_convert_ds_result(vec_add(&top->children, left));
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-17 19:08:35 -08:00
|
|
|
result = libab_convert_ds_result(vec_add(&top->children, right));
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
if (left)
|
|
|
|
libab_tree_free_recursive(left);
|
|
|
|
if (right)
|
|
|
|
libab_tree_free_recursive(right);
|
2018-02-17 19:08:35 -08:00
|
|
|
libab_tree_free(top);
|
|
|
|
free(top);
|
|
|
|
top = NULL;
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (top->variant == TREE_PREFIX_OP ||
|
|
|
|
top->variant == TREE_POSTFIX_OP || top->variant == TREE_CALL) {
|
2018-02-17 19:08:35 -08:00
|
|
|
libab_tree* child = NULL;
|
|
|
|
|
|
|
|
result = _parser_expression_tree(state, source, &child);
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-17 19:08:35 -08:00
|
|
|
result = libab_convert_ds_result(vec_add(&top->children, child));
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
if (child)
|
|
|
|
libab_tree_free_recursive(child);
|
|
|
|
if (top->variant == TREE_PREFIX_OP ||
|
|
|
|
top->variant == TREE_POSTFIX_OP) {
|
2018-02-25 14:06:15 -08:00
|
|
|
libab_tree_free(top);
|
|
|
|
free(top);
|
|
|
|
} else {
|
|
|
|
libab_tree_free_recursive(top);
|
|
|
|
}
|
2018-02-17 19:08:35 -08:00
|
|
|
top = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*into = top;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
int _parser_match_is_postfix_op(struct parser_state* state,
|
|
|
|
libab_lexer_match* match) {
|
2018-03-17 18:32:49 -07:00
|
|
|
int is_postfix = 0;
|
2018-03-17 20:56:25 -07:00
|
|
|
libab_operator* operator;
|
|
|
|
char op_buffer[8];
|
|
|
|
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
2018-04-21 14:09:01 -07:00
|
|
|
operator= libab_table_search_operator(state->base_table, op_buffer,
|
|
|
|
OPERATOR_POSTFIX);
|
|
|
|
if (operator)
|
|
|
|
is_postfix = 1;
|
2018-03-17 18:32:49 -07:00
|
|
|
return is_postfix;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
int _parser_match_is_prefix_op(struct parser_state* state,
|
|
|
|
libab_lexer_match* match) {
|
2018-03-17 18:32:49 -07:00
|
|
|
int is_prefix = 0;
|
2018-03-17 20:56:25 -07:00
|
|
|
libab_operator* operator;
|
|
|
|
char op_buffer[8];
|
|
|
|
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
2018-04-21 14:09:01 -07:00
|
|
|
operator= libab_table_search_operator(state->base_table, op_buffer,
|
|
|
|
OPERATOR_PREFIX);
|
|
|
|
if (operator)
|
|
|
|
is_prefix = 1;
|
2018-03-17 18:32:49 -07:00
|
|
|
return is_prefix;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
int _parser_match_is_infix_op(struct parser_state* state,
|
|
|
|
libab_lexer_match* match) {
|
2018-03-17 17:39:44 -07:00
|
|
|
int is_infix = 0;
|
2018-04-21 14:09:01 -07:00
|
|
|
if (match->type == TOKEN_OP_RESERVED) {
|
2018-03-17 17:39:44 -07:00
|
|
|
is_infix = 1;
|
|
|
|
} else {
|
|
|
|
libab_operator* operator;
|
|
|
|
char op_buffer[8];
|
|
|
|
_parser_extract_token_buffer(state, op_buffer, 8, match);
|
2018-04-21 14:09:01 -07:00
|
|
|
operator= libab_table_search_operator(state->base_table, op_buffer,
|
|
|
|
OPERATOR_INFIX);
|
|
|
|
if (operator)
|
|
|
|
is_infix = 1;
|
2018-03-17 17:39:44 -07:00
|
|
|
}
|
|
|
|
return is_infix;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_expression(struct parser_state* state,
|
|
|
|
libab_tree** store_into) {
|
2018-02-10 23:06:37 -08:00
|
|
|
libab_result result = LIBAB_SUCCESS;
|
2018-03-16 23:09:41 -07:00
|
|
|
struct operator_data operator;
|
|
|
|
struct operator_data other_operator;
|
2018-02-17 14:40:43 -08:00
|
|
|
ll out_stack;
|
|
|
|
ll op_stack;
|
|
|
|
int pop_success = 0;
|
|
|
|
enum parser_expression_type last_type = EXPR_NONE;
|
|
|
|
|
|
|
|
ll_init(&out_stack);
|
|
|
|
ll_init(&op_stack);
|
2018-02-21 18:35:00 -08:00
|
|
|
*store_into = NULL;
|
2018-02-17 14:40:43 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
while (result == LIBAB_SUCCESS && !_parser_eof(state)) {
|
2018-02-17 14:40:43 -08:00
|
|
|
enum parser_expression_type new_type = EXPR_NONE;
|
|
|
|
libab_lexer_match* new_token = state->current_match;
|
2018-02-18 21:05:06 -08:00
|
|
|
char current_char = state->string[new_token->from];
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_is_type(state, TOKEN_CHAR) && current_char != '{') {
|
|
|
|
if (current_char == '(' && _parser_can_postfix_follow(last_type)) {
|
2018-02-25 14:06:15 -08:00
|
|
|
result = _parser_append_call(state, &out_stack);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS)
|
|
|
|
break;
|
2018-02-25 14:06:15 -08:00
|
|
|
new_type = EXPR_OP_POSTFIX;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (current_char == '(') {
|
|
|
|
result =
|
|
|
|
libab_convert_ds_result(ll_append(&op_stack, new_token));
|
|
|
|
if (result != LIBAB_SUCCESS)
|
|
|
|
break;
|
2018-02-17 14:40:43 -08:00
|
|
|
_parser_state_step(state);
|
|
|
|
new_type = EXPR_OPEN_PARENTH;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (current_char == ')') {
|
|
|
|
result = _parser_pop_brackets(state, &op_stack, &out_stack, '(',
|
|
|
|
&pop_success);
|
|
|
|
if (result != LIBAB_SUCCESS || !pop_success)
|
|
|
|
break;
|
2018-02-17 16:01:04 -08:00
|
|
|
ll_poptail(&op_stack);
|
2018-02-17 14:40:43 -08:00
|
|
|
_parser_state_step(state);
|
|
|
|
new_type = EXPR_CLOSE_PARENTH;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_match_is_prefix_op(state, new_token) &&
|
|
|
|
_parser_can_prefix_follow(last_type)) {
|
2018-03-17 18:32:49 -07:00
|
|
|
new_token->type = TOKEN_OP_PREFIX;
|
2018-02-17 14:40:43 -08:00
|
|
|
result = libab_convert_ds_result(ll_append(&op_stack, new_token));
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS)
|
|
|
|
break;
|
2018-02-17 14:40:43 -08:00
|
|
|
_parser_state_step(state);
|
|
|
|
new_type = EXPR_OP_PREFIX;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_match_is_postfix_op(state, new_token) &&
|
|
|
|
_parser_can_postfix_follow(last_type)) {
|
2018-03-17 18:32:49 -07:00
|
|
|
new_token->type = TOKEN_OP_POSTFIX;
|
2018-02-17 14:40:43 -08:00
|
|
|
result = _parser_append_op_node(state, new_token, &out_stack);
|
2018-02-21 19:16:42 -08:00
|
|
|
_parser_state_step(state);
|
|
|
|
new_type = EXPR_OP_POSTFIX;
|
2018-04-21 14:09:01 -07:00
|
|
|
} else if (_parser_match_is_infix_op(state, new_token)) {
|
|
|
|
if (new_token->type == TOKEN_OP)
|
2018-03-17 20:56:25 -07:00
|
|
|
new_token->type = TOKEN_OP_INFIX;
|
2018-03-17 17:39:44 -07:00
|
|
|
_parser_find_operator_infix(state, new_token, &operator);
|
2018-02-17 16:01:04 -08:00
|
|
|
_parser_state_step(state);
|
2018-02-17 14:40:43 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
while (result == LIBAB_SUCCESS && op_stack.tail &&
|
|
|
|
_parser_match_is_op(op_stack.tail->data)) {
|
|
|
|
_parser_find_operator_infix(state, op_stack.tail->data,
|
|
|
|
&other_operator);
|
|
|
|
|
|
|
|
if (((libab_lexer_match*)op_stack.tail->data)->type ==
|
|
|
|
TOKEN_OP_PREFIX ||
|
|
|
|
(operator.associativity == - 1 &&
|
|
|
|
operator.precedence <= other_operator.precedence) ||
|
|
|
|
(operator.associativity == 1 &&
|
|
|
|
operator.precedence<other_operator.precedence)) {
|
2018-02-17 16:01:04 -08:00
|
|
|
libab_lexer_match* match = ll_poptail(&op_stack);
|
|
|
|
result = _parser_append_op_node(state, match, &out_stack);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
result =
|
|
|
|
libab_convert_ds_result(ll_append(&op_stack, new_token));
|
2018-02-17 16:01:04 -08:00
|
|
|
}
|
|
|
|
new_type = EXPR_OP_INFIX;
|
|
|
|
} else {
|
2018-04-21 14:09:01 -07:00
|
|
|
if (!_parser_can_atom_follow(last_type))
|
|
|
|
break;
|
2018-02-17 16:01:04 -08:00
|
|
|
result = _parser_append_atom(state, &out_stack);
|
|
|
|
new_type = EXPR_ATOM;
|
2018-02-17 14:40:43 -08:00
|
|
|
}
|
|
|
|
last_type = new_type;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
while (result == LIBAB_SUCCESS && op_stack.tail) {
|
2018-02-17 19:08:35 -08:00
|
|
|
libab_lexer_match* match = ll_poptail(&op_stack);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (_parser_match_is_op(match)) {
|
2018-02-17 19:08:35 -08:00
|
|
|
result = _parser_append_op_node(state, match, &out_stack);
|
|
|
|
} else {
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-02-17 19:08:35 -08:00
|
|
|
result = _parser_expression_tree(state, &out_stack, store_into);
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS && out_stack.tail) {
|
2018-02-17 19:20:10 -08:00
|
|
|
libab_tree_free_recursive(*store_into);
|
2018-02-17 19:08:35 -08:00
|
|
|
*store_into = NULL;
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS && *store_into == NULL) {
|
2018-02-21 18:55:05 -08:00
|
|
|
result = LIBAB_UNEXPECTED;
|
2018-02-21 18:35:00 -08:00
|
|
|
}
|
|
|
|
|
2018-06-12 02:09:51 -07:00
|
|
|
ll_foreach(&op_stack, NULL, compare_always, _parser_foreach_free_tree);
|
2018-02-17 19:08:35 -08:00
|
|
|
ll_foreach(&out_stack, NULL, compare_always, _parser_foreach_free_tree);
|
2018-06-12 02:09:51 -07:00
|
|
|
ll_free(&op_stack);
|
2018-02-18 21:05:06 -08:00
|
|
|
ll_free(&out_stack);
|
2018-02-10 23:06:37 -08:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
libab_result _parse_block(struct parser_state* state, libab_tree** store_into,
|
|
|
|
int expect_braces) {
|
2018-02-21 19:06:00 -08:00
|
|
|
libab_result result;
|
2018-02-21 18:35:00 -08:00
|
|
|
libab_tree* temp = NULL;
|
2018-02-21 19:06:00 -08:00
|
|
|
result = _parser_construct_node_vec(state->current_match, store_into);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_BLOCK;
|
2018-02-17 19:39:12 -08:00
|
|
|
}
|
2018-02-10 22:40:34 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (expect_braces && result == LIBAB_SUCCESS)
|
|
|
|
result = _parser_consume_char(state, '{');
|
2018-02-10 22:40:34 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
while (result == LIBAB_SUCCESS && !_parser_eof(state) &&
|
|
|
|
!(expect_braces && _parser_is_char(state, '}'))) {
|
|
|
|
PARSE_CHILD(result, state, _parse_expression, temp,
|
|
|
|
&(*store_into)->children);
|
|
|
|
if (_parser_is_char(state, ';')) {
|
2018-02-18 21:05:06 -08:00
|
|
|
temp = NULL;
|
|
|
|
_parser_state_step(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS && temp == NULL) {
|
2018-02-27 11:29:59 -08:00
|
|
|
PARSE_CHILD(result, state, _parse_void, temp, &(*store_into)->children);
|
2018-02-10 22:40:34 -08:00
|
|
|
}
|
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (expect_braces && result == LIBAB_SUCCESS)
|
|
|
|
result = _parser_consume_char(state, '}');
|
2018-02-17 19:39:12 -08:00
|
|
|
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result != LIBAB_SUCCESS && *store_into) {
|
2018-02-17 19:39:12 -08:00
|
|
|
libab_tree_free_recursive(*store_into);
|
2018-02-21 18:35:00 -08:00
|
|
|
*store_into = NULL;
|
2018-02-17 19:39:12 -08:00
|
|
|
}
|
|
|
|
|
2018-02-10 22:40:34 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-05-11 20:36:27 -07:00
|
|
|
void libab_parser_init(libab_parser* parser, struct libab_s* ab) {
|
|
|
|
parser->ab = ab;
|
2018-02-11 22:23:02 -08:00
|
|
|
}
|
|
|
|
libab_result libab_parser_parse(libab_parser* parser, ll* tokens,
|
2018-04-21 14:09:01 -07:00
|
|
|
const char* string, libab_tree** store_into) {
|
2018-02-21 19:06:00 -08:00
|
|
|
libab_result result;
|
2018-02-10 22:17:08 -08:00
|
|
|
struct parser_state state;
|
2018-05-17 14:53:48 -07:00
|
|
|
_parser_state_init(&state, tokens, string,
|
|
|
|
libab_ref_get(&parser->ab->table));
|
2018-02-10 22:17:08 -08:00
|
|
|
|
2018-02-10 22:40:34 -08:00
|
|
|
result = _parse_block(&state, store_into, 0);
|
2018-04-21 14:09:01 -07:00
|
|
|
if (result == LIBAB_SUCCESS) {
|
2018-03-08 21:13:25 -08:00
|
|
|
(*store_into)->variant = TREE_BASE;
|
2018-02-21 18:35:00 -08:00
|
|
|
}
|
2018-02-10 22:40:34 -08:00
|
|
|
|
2018-02-10 22:17:08 -08:00
|
|
|
return result;
|
|
|
|
}
|
2018-03-06 16:47:11 -08:00
|
|
|
libab_result libab_parser_parse_type(libab_parser* parser, ll* tokens,
|
2018-04-21 14:09:01 -07:00
|
|
|
const char* string,
|
|
|
|
libab_ref* store_into) {
|
2018-03-06 16:47:11 -08:00
|
|
|
struct parser_state state;
|
2018-05-17 14:53:48 -07:00
|
|
|
_parser_state_init(&state, tokens, string,
|
|
|
|
libab_ref_get(&parser->ab->table));
|
2018-03-06 16:47:11 -08:00
|
|
|
|
|
|
|
return _parse_type(&state, store_into);
|
|
|
|
}
|
2018-05-14 17:46:11 -07:00
|
|
|
void libab_parser_free(libab_parser* parser) {}
|