Add function node parsing.
This commit is contained in:
parent
2487cdebe0
commit
2d26e45e90
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
90
src/parser.c
90
src/parser.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
13
src/tree.c
13
src/tree.c
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user