Add the ability to parse types.
This ability is not integrated with the rest of the parser - in fact, the grammar for things like function declarations (where type declarations are necessary) is not yet determined.
This commit is contained in:
parent
45d955b8bd
commit
2487cdebe0
|
@ -62,6 +62,7 @@ enum libab_lexer_token_e {
|
||||||
TOKEN_KW_ELSE,
|
TOKEN_KW_ELSE,
|
||||||
TOKEN_KW_WHILE,
|
TOKEN_KW_WHILE,
|
||||||
TOKEN_KW_DO,
|
TOKEN_KW_DO,
|
||||||
|
TOKEN_KW_ARROW,
|
||||||
TOKEN_LAST
|
TOKEN_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
#include "ll.h"
|
#include "ll.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
#include "parsetype.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parser that is used by libabacus
|
* The parser that is used by libabacus
|
||||||
|
@ -31,6 +32,8 @@ void libab_parser_init(libab_parser* parser, libab_table* table);
|
||||||
*/
|
*/
|
||||||
libab_result libab_parser_parse(libab_parser* parser, ll* tokens,
|
libab_result libab_parser_parse(libab_parser* parser, ll* tokens,
|
||||||
const char* string, libab_tree** store_into);
|
const char* string, libab_tree** store_into);
|
||||||
|
libab_result libab_parser_parse_type(libab_parser* parser, ll* tokens,
|
||||||
|
const char* string, libab_parsetype** store_into);
|
||||||
/**
|
/**
|
||||||
* Releases the resources allocated by the parser.
|
* Releases the resources allocated by the parser.
|
||||||
* @param parser the parser to release.
|
* @param parser the parser to release.
|
||||||
|
|
|
@ -14,7 +14,8 @@ libab_result libab_lexer_init(libab_lexer* lexer) {
|
||||||
"if",
|
"if",
|
||||||
"else",
|
"else",
|
||||||
"while",
|
"while",
|
||||||
"do"
|
"do",
|
||||||
|
"->"
|
||||||
};
|
};
|
||||||
libab_lexer_token tokens[] = {
|
libab_lexer_token tokens[] = {
|
||||||
TOKEN_CHAR,
|
TOKEN_CHAR,
|
||||||
|
@ -23,7 +24,8 @@ libab_result libab_lexer_init(libab_lexer* lexer) {
|
||||||
TOKEN_KW_IF,
|
TOKEN_KW_IF,
|
||||||
TOKEN_KW_ELSE,
|
TOKEN_KW_ELSE,
|
||||||
TOKEN_KW_WHILE,
|
TOKEN_KW_WHILE,
|
||||||
TOKEN_KW_DO
|
TOKEN_KW_DO,
|
||||||
|
TOKEN_KW_ARROW
|
||||||
};
|
};
|
||||||
const size_t count = sizeof(tokens)/sizeof(libab_lexer_token);
|
const size_t count = sizeof(tokens)/sizeof(libab_lexer_token);
|
||||||
|
|
||||||
|
|
179
src/parser.c
179
src/parser.c
|
@ -31,15 +31,7 @@ int _parser_foreach_free_tree(void* data, va_list args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _parser_extract_token(struct parser_state* state, char** into, libab_lexer_match* match) {
|
libab_result _parser_extract_token(struct parser_state* state, char** into, libab_lexer_match* match) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
return libab_copy_string_range(into, state->string, match->from, match->to);
|
||||||
size_t string_size = match->to - match->from;
|
|
||||||
if((*into = malloc(string_size + 1))) {
|
|
||||||
strncpy(*into, state->string + match->from, string_size);
|
|
||||||
(*into)[string_size] = '\0';
|
|
||||||
} else {
|
|
||||||
result = LIBAB_MALLOC;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// State functions
|
// State functions
|
||||||
|
@ -107,6 +99,168 @@ libab_result _parser_consume_type(struct parser_state* state,
|
||||||
|
|
||||||
libab_result _parse_block(struct parser_state*, libab_tree**, int);
|
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 _parser_allocate_type(libab_parsetype** into, const char* source, size_t from, size_t to) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
if((*into = malloc(sizeof(**into)))) {
|
||||||
|
result = libab_copy_string_range(&(*into)->name, source, from, to);
|
||||||
|
} else {
|
||||||
|
result = LIBAB_MALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
free(*into);
|
||||||
|
*into = NULL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parser_append_type(struct parser_state* state, vec* into) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
libab_parsetype* temp = NULL;
|
||||||
|
result = _parse_type(state, &temp);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_convert_ds_result(vec_add(into, temp));
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
libab_parsetype_free_recursive(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parse_type_list(struct parser_state* state, vec* into, char end_char) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
int is_parenth, is_comma;
|
||||||
|
while(result == LIBAB_SUCCESS && !_parser_eof(state) && !_parser_is_char(state, end_char)) {
|
||||||
|
result = _parser_append_type(state, into);
|
||||||
|
is_parenth = _parser_is_char(state, end_char);
|
||||||
|
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, end_char)) {
|
||||||
|
result = LIBAB_UNEXPECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = _parser_consume_char(state, end_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parse_type_id(struct parser_state* state, libab_parsetype** into) {
|
||||||
|
libab_result result = _parser_allocate_type(into, state->string,
|
||||||
|
state->current_match->from, state->current_match->to);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
(*into)->variant = PT_STRING;
|
||||||
|
_parser_state_step(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS && _parser_is_char(state, '(')) {
|
||||||
|
result = libab_convert_ds_result(vec_init(&(*into)->children));
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
free((*into)->name);
|
||||||
|
free(*into);
|
||||||
|
*into = NULL;
|
||||||
|
} else {
|
||||||
|
(*into)->variant = PT_PARENT;
|
||||||
|
_parser_state_step(state);
|
||||||
|
result = _parse_type_list(state, &(*into)->children, ')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS && *into) {
|
||||||
|
libab_parsetype_free_recursive(*into);
|
||||||
|
*into = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parse_type_function(struct parser_state* state,
|
||||||
|
libab_parsetype** into) {
|
||||||
|
libab_result result = _parser_allocate_type(into, "function", 0, 8);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
(*into)->variant = PT_PARENT;
|
||||||
|
result = libab_convert_ds_result(vec_init(&(*into)->children));
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
free((*into)->name);
|
||||||
|
free(*into);
|
||||||
|
*into = NULL;
|
||||||
|
} else {
|
||||||
|
_parser_state_step(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = _parse_type_list(state, &(*into)->children, ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = _parser_consume_type(state, TOKEN_KW_ARROW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = _parser_append_type(state, &(*into)->children);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS && *into) {
|
||||||
|
libab_parsetype_free_recursive(*into);
|
||||||
|
*into = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parse_type_array(struct parser_state* state,
|
||||||
|
libab_parsetype** into) {
|
||||||
|
libab_result result = _parser_allocate_type(into, "array", 0, 5);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
(*into)->variant = PT_PARENT;
|
||||||
|
result = libab_convert_ds_result(vec_init(&(*into)->children));
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
free((*into)->name);
|
||||||
|
free(*into);
|
||||||
|
*into = NULL;
|
||||||
|
} else {
|
||||||
|
_parser_state_step(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = _parser_append_type(state, &(*into)->children);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = _parser_consume_char(state, ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS && *into) {
|
||||||
|
libab_parsetype_free_recursive(*into);
|
||||||
|
*into = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _parse_type(struct parser_state* state, libab_parsetype** into) {
|
||||||
|
libab_result result;
|
||||||
|
if(_parser_is_type(state, TOKEN_ID)) {
|
||||||
|
result = _parse_type_id(state, into);
|
||||||
|
} else if(_parser_is_char(state, '(')) {
|
||||||
|
result = _parse_type_function(state, into);
|
||||||
|
} else if(_parser_is_char(state, '[')) {
|
||||||
|
result = _parse_type_array(state, into);
|
||||||
|
} else {
|
||||||
|
*into = NULL;
|
||||||
|
result = LIBAB_UNEXPECTED;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
libab_result _parser_allocate_node(libab_lexer_match* match, libab_tree** into) {
|
libab_result _parser_allocate_node(libab_lexer_match* match, libab_tree** into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
@ -669,6 +823,13 @@ libab_result libab_parser_parse(libab_parser* parser, ll* tokens,
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
libab_result libab_parser_parse_type(libab_parser* parser, ll* tokens,
|
||||||
|
const char* string, libab_parsetype** store_into) {
|
||||||
|
struct parser_state state;
|
||||||
|
_parser_state_init(&state, tokens, string, parser->base_table);
|
||||||
|
|
||||||
|
return _parse_type(&state, store_into);
|
||||||
|
}
|
||||||
void libab_parser_free(libab_parser* parser) {
|
void libab_parser_free(libab_parser* parser) {
|
||||||
parser->base_table = NULL;
|
parser->base_table = NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user