Finish the "construct tree" part of Shunting Yard.

This commit is contained in:
Danila Fedorin 2018-02-17 19:08:35 -08:00
parent 68b4fb5807
commit a52735f0b3
2 changed files with 88 additions and 2 deletions

View File

@ -195,6 +195,69 @@ libab_result _parser_append_atom(struct parser_state* state, ll* append_to) {
return result; return result;
} }
libab_result _parser_expression_tree(struct parser_state* state, ll* source, libab_tree** into) {
libab_result result = LIBAB_SUCCESS;
libab_tree* top = ll_poptail(source);
if(top && top->variant == OP) {
libab_tree* left = NULL;
libab_tree* right = NULL;
result = _parser_expression_tree(state, source, &right);
if(result == LIBAB_SUCCESS) {
result = _parser_expression_tree(state, source, &left);
}
if(result == LIBAB_SUCCESS && (left == NULL || right == NULL)) {
result = LIBAB_UNEXPECTED;
}
if(result == LIBAB_SUCCESS) {
result = libab_convert_ds_result(vec_add(&top->children, left));
}
if(result == LIBAB_SUCCESS) {
result = libab_convert_ds_result(vec_add(&top->children, right));
}
if(result != LIBAB_SUCCESS) {
if(left) libab_tree_free(left);
if(right) libab_tree_free(right);
libab_tree_free(top);
free(left);
free(right);
free(top);
top = NULL;
}
} else if(top && top->variant == UNARY_OP) {
libab_tree* child = NULL;
result = _parser_expression_tree(state, source, &child);
if(result == LIBAB_SUCCESS && child == NULL) {
result = LIBAB_UNEXPECTED;
}
if(result == LIBAB_SUCCESS) {
result = libab_convert_ds_result(vec_add(&top->children, child));
}
if(result != LIBAB_SUCCESS) {
if(child) libab_tree_free(child);
libab_tree_free(top);
free(child);
free(top);
top = NULL;
}
}
*into = top;
return result;
}
int _parser_foreach_free_tree(void* data, va_list args) {
libab_tree_free(data);
free(data);
return 0;
}
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;
@ -262,6 +325,29 @@ libab_result _parse_expression(struct parser_state* state, libab_tree** store_in
last_type = new_type; last_type = new_type;
} }
while(result == LIBAB_SUCCESS && op_stack.tail) {
libab_lexer_match* match = ll_poptail(&op_stack);
if(_parser_match_is_op(match)) {
result = _parser_append_op_node(state, match, &out_stack);
} else {
result = LIBAB_UNEXPECTED;
}
}
if(result == LIBAB_SUCCESS) {
result = _parser_expression_tree(state, &out_stack, store_into);
}
if(result == LIBAB_SUCCESS && out_stack.tail) {
libab_tree_free(*store_into);
free(*store_into);
*store_into = NULL;
result = LIBAB_UNEXPECTED;
}
ll_free(&op_stack);
ll_foreach(&out_stack, NULL, compare_always, _parser_foreach_free_tree);
return result; return result;
} }

View File

@ -2,7 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "util.h" #include "util.h"
void table_init(libab_table* table) { void libab_table_init(libab_table* table) {
ht_init(&table->table); ht_init(&table->table);
table->parent = NULL; table->parent = NULL;
} }
@ -33,6 +33,6 @@ libab_function* libab_table_search_function(libab_table* table, const char* stri
libab_result libab_table_put(libab_table* table, const char* string, libab_table_entry* entry) { libab_result libab_table_put(libab_table* table, const char* string, libab_table_entry* entry) {
return libab_convert_ds_result(ht_put(&table->table, string, entry)); return libab_convert_ds_result(ht_put(&table->table, string, entry));
} }
void table_free(libab_table* table) { void libab_table_free(libab_table* table) {
ht_free(&table->table); ht_free(&table->table);
} }