finish expr parse function; cleanup allocs and error handling
This commit is contained in:
parent
4c17bf96bf
commit
f5db5076db
1 changed files with 64 additions and 28 deletions
92
lapis.c
92
lapis.c
|
@ -64,6 +64,13 @@ void lapis_node_print(const lapis_node_t *nodes, size_t idx) {
|
|||
if ( nodes[idx].value.type == LAPIS_TTYPE_OPER ) putchar(')');
|
||||
}
|
||||
|
||||
size_t lapis_node_count(const lapis_node_t *nodes, size_t idx) {
|
||||
size_t count = 1;
|
||||
if ( nodes[idx].lhs_idx != SIZE_MAX ) count += lapis_node_count(nodes, nodes[idx].lhs_idx);
|
||||
if ( nodes[idx].rhs_idx != SIZE_MAX ) count += lapis_node_count(nodes, nodes[idx].rhs_idx);
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Free a token's internal buffer if it has one
|
||||
void lapis_token_free(lapis_token_t *token) {
|
||||
if ( token->type == LAPIS_TTYPE_IDENT || token->type == LAPIS_TTYPE_OPER ) {
|
||||
|
@ -239,21 +246,31 @@ ERROR:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void lapis_parse(FILE *f) {
|
||||
lapis_node_t *lapis_parse_expr(size_t *nnodes, FILE *f) {
|
||||
|
||||
lapis_token_t *tokens = NULL;
|
||||
int64_t *oper_priorities = NULL;
|
||||
uint8_t *oper_arg_form = NULL;
|
||||
lapis_node_t *nodes = NULL;
|
||||
|
||||
size_t ntokens=0;
|
||||
lapis_token_t *tokens = lapis_parse_tokens(&ntokens, stdin);
|
||||
if ( tokens == NULL ) return;
|
||||
tokens = lapis_parse_tokens(&ntokens, stdin);
|
||||
if ( tokens == NULL ) goto ERROR;
|
||||
|
||||
int64_t *oper_priorities = malloc( ntokens * sizeof(int64_t) );
|
||||
if ( oper_priorities == NULL ) return;
|
||||
oper_priorities = malloc( ntokens * sizeof(int64_t) );
|
||||
if ( oper_priorities == NULL ) goto ERROR;
|
||||
|
||||
// 0 - no args, 1 - lhs, 2 - rhs, 3 - both
|
||||
uint8_t *oper_arg_form = malloc( ntokens * sizeof(uint8_t) );
|
||||
if ( oper_arg_form == NULL ) return;
|
||||
oper_arg_form = malloc( ntokens * sizeof(uint8_t) );
|
||||
if ( oper_arg_form == NULL ) goto ERROR;
|
||||
|
||||
memset(oper_arg_form, 0, ntokens);
|
||||
|
||||
size_t num_nodes = 0;
|
||||
|
||||
#define ADD_NODE(NODE) \
|
||||
(num_nodes++, nodes = realloc(nodes, num_nodes * sizeof(lapis_node_t)), nodes[num_nodes-1] = NODE)
|
||||
|
||||
int64_t paren_level = 0;
|
||||
|
||||
for (size_t n=0; n < ntokens; n++) {
|
||||
|
@ -271,7 +288,7 @@ void lapis_parse(FILE *f) {
|
|||
fputs("ERROR: unknown priority for operator '", stderr);
|
||||
fwrite(tokens[n].str, 1, tokens[n].len, stderr);
|
||||
fputs("'\n", stderr);
|
||||
return;
|
||||
goto ERROR;
|
||||
case 1ul*',':
|
||||
oper_priorities[n] = 1;
|
||||
oper_arg_form[n] = 3;
|
||||
|
@ -365,7 +382,7 @@ void lapis_parse(FILE *f) {
|
|||
case 1ul*')':
|
||||
if ( paren_level == 0 ) {
|
||||
fprintf(stderr, "ERROR(%d): unexpected ')'\n", __LINE__);
|
||||
return;
|
||||
goto ERROR;
|
||||
}
|
||||
// clear the ')' as being an operator
|
||||
oper_priorities[n] = -1;
|
||||
|
@ -377,12 +394,6 @@ void lapis_parse(FILE *f) {
|
|||
if ( oper_priorities[n] != -1 ) oper_priorities[n] += paren_level * 16;
|
||||
}
|
||||
|
||||
size_t nnodes = 0;
|
||||
lapis_node_t *nodes = NULL;
|
||||
|
||||
#define ADD_NODE(NODE) \
|
||||
(nnodes++, nodes = realloc(nodes, nnodes * sizeof(lapis_node_t)), nodes[nnodes-1] = NODE)
|
||||
|
||||
while (1) {
|
||||
|
||||
// seek the next highest priority operator
|
||||
|
@ -422,14 +433,14 @@ void lapis_parse(FILE *f) {
|
|||
|
||||
if ( n == max_prior_idx || tokens[n].type == LAPIS_TTYPE_NONE ) {
|
||||
printf("ERROR: bad logic line #%d\n", __LINE__);
|
||||
return;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
if ( tokens[n].type == LAPIS_TTYPE_OPER ) {
|
||||
|
||||
if ( oper_priorities[n] >= -1 ) {
|
||||
printf("ERROR: bad logic line #%d\n", __LINE__);
|
||||
return;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
// This is very weird, BUT as a vile hack I encode the node index
|
||||
|
@ -441,7 +452,7 @@ void lapis_parse(FILE *f) {
|
|||
|
||||
if ( node_idx < 0 ) {
|
||||
printf("ERROR: bad logic line #%d\n", __LINE__);
|
||||
return;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
node.lhs_idx = node_idx;
|
||||
|
@ -458,7 +469,7 @@ void lapis_parse(FILE *f) {
|
|||
};
|
||||
|
||||
ADD_NODE( tmpnode );
|
||||
node.lhs_idx = nnodes-1;
|
||||
node.lhs_idx = num_nodes-1;
|
||||
}
|
||||
|
||||
// clear token type to prevent reuse
|
||||
|
@ -475,14 +486,14 @@ void lapis_parse(FILE *f) {
|
|||
|
||||
if ( n == max_prior_idx || tokens[n].type == LAPIS_TTYPE_NONE ) {
|
||||
printf("ERROR: bad logic line #%d\n", __LINE__);
|
||||
return;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
if ( tokens[n].type == LAPIS_TTYPE_OPER ) {
|
||||
|
||||
if ( oper_priorities[n] >= -1 ) {
|
||||
printf("ERROR: bad logic line #%d\n", __LINE__);
|
||||
return;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
// This is very weird, BUT as a vile hack I encode the node index
|
||||
|
@ -494,7 +505,7 @@ void lapis_parse(FILE *f) {
|
|||
|
||||
if ( node_idx < 0 ) {
|
||||
printf("ERROR: bad logic line #%d\n", __LINE__);
|
||||
return;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
node.rhs_idx = node_idx;
|
||||
|
@ -511,7 +522,7 @@ void lapis_parse(FILE *f) {
|
|||
};
|
||||
|
||||
ADD_NODE( tmpnode );
|
||||
node.rhs_idx = nnodes-1;
|
||||
node.rhs_idx = num_nodes-1;
|
||||
}
|
||||
|
||||
// clear token type to prevent reuse
|
||||
|
@ -519,7 +530,7 @@ void lapis_parse(FILE *f) {
|
|||
}
|
||||
|
||||
ADD_NODE( node );
|
||||
int64_t idx = nnodes - 1;
|
||||
int64_t idx = num_nodes - 1;
|
||||
|
||||
printf("add oper token %lu w/ priority %ld as node %ld\n",
|
||||
max_prior_idx, oper_priorities[max_prior_idx], idx);
|
||||
|
@ -533,10 +544,26 @@ void lapis_parse(FILE *f) {
|
|||
if ( update_rhs_idx != SIZE_MAX ) oper_priorities[update_rhs_idx] = -idx - 2;
|
||||
}
|
||||
|
||||
//TODO cleanup allocs, error handling, ';' or w/e to **separate expressions**
|
||||
if ( lapis_node_count(nodes, num_nodes-1) != num_nodes ) {
|
||||
// NOTE: this likely indicates a priority conflict of some kind between operators
|
||||
fprintf(stderr, "ERROR[%d]: Unknown syntax error! Orphan nodes detected!\n", __LINE__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
lapis_node_print(nodes, nnodes-1);
|
||||
putchar('\n');
|
||||
if ( tokens != NULL ) free( tokens );
|
||||
if ( oper_priorities != NULL ) free( oper_priorities );
|
||||
if ( oper_arg_form != NULL ) free( oper_arg_form );
|
||||
|
||||
*nnodes = num_nodes;
|
||||
return nodes;
|
||||
ERROR:
|
||||
if ( tokens != NULL ) free( tokens );
|
||||
if ( oper_priorities != NULL ) free( oper_priorities );
|
||||
if ( oper_arg_form != NULL ) free( oper_arg_form );
|
||||
if ( nodes != NULL ) free( nodes );
|
||||
|
||||
*nnodes = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
@ -564,7 +591,16 @@ int main() {
|
|||
}
|
||||
}
|
||||
#else
|
||||
lapis_parse(stdin);
|
||||
while (1) {
|
||||
|
||||
size_t nnodes;
|
||||
lapis_node_t *nodes = lapis_parse_expr(&nnodes, stdin);
|
||||
|
||||
if ( nnodes == 0 ) break;
|
||||
|
||||
lapis_node_print(nodes, nnodes-1);
|
||||
putchar('\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue