Add function node parsing.

This commit is contained in:
Danila Fedorin 2018-03-08 21:10:05 -08:00
parent 2487cdebe0
commit 2d26e45e90
6 changed files with 123 additions and 7 deletions

View File

@ -63,6 +63,7 @@ enum libab_lexer_token_e {
TOKEN_KW_WHILE, TOKEN_KW_WHILE,
TOKEN_KW_DO, TOKEN_KW_DO,
TOKEN_KW_ARROW, TOKEN_KW_ARROW,
TOKEN_KW_FUN,
TOKEN_LAST TOKEN_LAST
}; };

View File

@ -2,6 +2,7 @@
#define LIBABACUS_TREE_H #define LIBABACUS_TREE_H
#include "result.h" #include "result.h"
#include "parsetype.h"
#include "vec.h" #include "vec.h"
/** /**
@ -19,13 +20,19 @@ enum libab_tree_variant_e {
IF, IF,
WHILE, WHILE,
DOWHILE, DOWHILE,
CALL CALL,
FUN,
FUN_PARAM
}; };
/** /**
* A tree node that has been parsed from the input tokens. * A tree node that has been parsed from the input tokens.
*/ */
struct libab_tree_s { struct libab_tree_s {
/**
* The parse type of this node, if applicable.
*/
libab_parsetype* parse_type;
/** /**
* The variant of tree node. * The variant of tree node.
*/ */
@ -81,6 +88,13 @@ void libab_tree_free(libab_tree* tree);
* @return true if the tree node variant contains a string. * @return true if the tree node variant contains a string.
*/ */
int libab_tree_has_string(libab_tree_variant var); int libab_tree_has_string(libab_tree_variant var);
/**
* Determines if the given tree node variant
* should contain a parse type.
* @param var the variant of the tree node.
* @return true if the tree node variant contains a type.
*/
int libab_tree_has_type(libab_tree_variant var);
/** /**
* Determines if the given tree node variant * Determines if the given tree node variant
* should contain a vector. * should contain a vector.

View File

@ -15,7 +15,9 @@ const char* _debug_node_name(libab_tree_variant var) {
"if", "if",
"while", "while",
"dowhile", "dowhile",
"call" "call",
"fun",
"fun_param"
}; };
return names[var]; return names[var];
} }

View File

@ -15,7 +15,8 @@ libab_result libab_lexer_init(libab_lexer* lexer) {
"else", "else",
"while", "while",
"do", "do",
"->" "->",
"fun"
}; };
libab_lexer_token tokens[] = { libab_lexer_token tokens[] = {
TOKEN_CHAR, TOKEN_CHAR,
@ -25,7 +26,8 @@ libab_result libab_lexer_init(libab_lexer* lexer) {
TOKEN_KW_ELSE, TOKEN_KW_ELSE,
TOKEN_KW_WHILE, TOKEN_KW_WHILE,
TOKEN_KW_DO, TOKEN_KW_DO,
TOKEN_KW_ARROW TOKEN_KW_ARROW,
TOKEN_KW_FUN
}; };
const size_t count = sizeof(tokens)/sizeof(libab_lexer_token); const size_t count = sizeof(tokens)/sizeof(libab_lexer_token);

View File

@ -101,6 +101,10 @@ libab_result _parse_block(struct parser_state*, libab_tree**, int);
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 _parse_type(struct parser_state* state, libab_parsetype** into); libab_result _parse_type(struct parser_state* state, libab_parsetype** into);
libab_result _parse_braced_block(struct parser_state* state, libab_tree** store_into) {
return _parse_block(state, store_into, 1);
}
libab_result _parser_allocate_type(libab_parsetype** into, const char* source, size_t from, size_t to) { libab_result _parser_allocate_type(libab_parsetype** into, const char* source, size_t from, size_t to) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
if((*into = malloc(sizeof(**into)))) { if((*into = malloc(sizeof(**into)))) {
@ -381,6 +385,88 @@ libab_result _parse_if(struct parser_state* state, libab_tree** store_into) {
return result; return result;
} }
libab_result _parse_fun_param(struct parser_state* state, libab_tree** store_into) {
libab_result result = LIBAB_SUCCESS;
if(_parser_is_type(state, TOKEN_ID)) {
result = _parser_construct_node_string(state, state->current_match, store_into);
} else {
result = LIBAB_UNEXPECTED;
}
if(result == LIBAB_SUCCESS) {
_parser_state_step(state);
(*store_into)->variant = FUN_PARAM;
(*store_into)->parse_type = NULL;
result = _parser_consume_char(state, ':');
}
if(result == LIBAB_SUCCESS) {
result = _parse_type(state, &(*store_into)->parse_type);
}
if(result != LIBAB_SUCCESS && *store_into) {
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);
if(result == LIBAB_SUCCESS) {
if(_parser_is_type(state, TOKEN_ID)) {
result = _parser_construct_node_both(state, state->current_match, store_into);
} else {
result = LIBAB_UNEXPECTED;
}
}
if(result == LIBAB_SUCCESS) {
_parser_state_step(state);
(*store_into)->parse_type = NULL;
(*store_into)->variant = FUN;
result = _parser_consume_char(state, '(');
}
while(result == LIBAB_SUCCESS && !_parser_eof(state) && !_parser_is_char(state, ')')) {
PARSE_CHILD(result, state, _parse_fun_param, temp, &(*store_into)->children);
is_parenth = _parser_is_char(state, ')');
is_comma = _parser_is_char(state, ',');
if(result == LIBAB_SUCCESS && !(is_parenth || is_comma)) {
result = LIBAB_UNEXPECTED;
} else if(result == LIBAB_SUCCESS && is_comma) {
_parser_state_step(state);
if(_parser_is_char(state, ')')) {
result = LIBAB_UNEXPECTED;
}
}
}
if(result == LIBAB_SUCCESS) {
result = _parser_consume_char(state, ')');
}
if(result == LIBAB_SUCCESS) {
result = _parser_consume_char(state, ':');
}
if(result == LIBAB_SUCCESS) {
result = _parse_type(state, &(*store_into)->parse_type);
}
if(result == LIBAB_SUCCESS) {
PARSE_CHILD(result, state, _parse_braced_block, temp, &(*store_into)->children);
}
if(result != LIBAB_SUCCESS && *store_into) {
libab_tree_free_recursive(*store_into);
*store_into = NULL;
}
return result;
}
libab_result _parse_while(struct parser_state* state, libab_tree** store_into) { libab_result _parse_while(struct parser_state* state, libab_tree** store_into) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
libab_tree* condition = NULL; libab_tree* condition = NULL;
@ -521,7 +607,9 @@ libab_result _parse_atom(struct parser_state* state, libab_tree** store_into) {
} else if(_parser_is_type(state, TOKEN_KW_DO)) { } else if(_parser_is_type(state, TOKEN_KW_DO)) {
result = _parse_dowhile(state, store_into); result = _parse_dowhile(state, store_into);
} else if(_parser_is_char(state, '{')) { } else if(_parser_is_char(state, '{')) {
result = _parse_block(state, store_into, 1); result = _parse_braced_block(state, store_into);
} else if(_parser_is_type(state, TOKEN_KW_FUN)) {
result = _parse_fun(state, store_into);
} else { } else {
result = LIBAB_UNEXPECTED; result = LIBAB_UNEXPECTED;
} }

View File

@ -5,21 +5,30 @@ int libab_tree_has_vector(libab_tree_variant variant) {
return variant == BASE || variant == OP || return variant == BASE || variant == OP ||
variant == UNARY_OP || variant == BLOCK || variant == UNARY_OP || variant == BLOCK ||
variant == IF || variant == CALL || variant == WHILE || variant == IF || variant == CALL || variant == WHILE ||
variant == DOWHILE; variant == DOWHILE || variant == FUN;
} }
int libab_tree_has_string(libab_tree_variant variant) { int libab_tree_has_string(libab_tree_variant variant) {
return variant == ID || variant == NUM || return variant == ID || variant == NUM ||
variant == OP || variant == UNARY_OP; variant == OP || variant == UNARY_OP ||
variant == FUN || variant == FUN_PARAM;
}
int libab_tree_has_type(libab_tree_variant variant) {
return variant == FUN_PARAM || variant == FUN;
} }
void libab_tree_free(libab_tree* tree) { void libab_tree_free(libab_tree* tree) {
int free_string = 0; int free_string = 0;
int free_vector = 0; int free_vector = 0;
int free_type = 0;
free_vector = libab_tree_has_vector(tree->variant); free_vector = libab_tree_has_vector(tree->variant);
free_string = libab_tree_has_string(tree->variant); free_string = libab_tree_has_string(tree->variant);
free_type = libab_tree_has_type(tree->variant);
if(free_string) free(tree->string_value); if(free_string) free(tree->string_value);
if(free_vector) vec_free(&tree->children); if(free_vector) vec_free(&tree->children);
if(free_type && tree->parse_type)
libab_parsetype_free_recursive(tree->parse_type);
} }
int _tree_foreach_free(void* data, va_list args) { int _tree_foreach_free(void* data, va_list args) {