lang: ast: re-factor condition group parser

this parser now only handles if-else statements, and uses the state init callback argument to receive any pre-existing inline expressions
This commit is contained in:
2024-12-04 21:02:55 +00:00
parent a34b9c3710
commit 0bb4a4284c
3 changed files with 27 additions and 52 deletions

View File

@@ -1,11 +1,22 @@
#include "cond.h"
#include "block.h" #include "block.h"
#include "expr/expr.h" #include "expr/expr.h"
struct cond_group_parser_state {
struct parser_state s_base;
bool s_inline;
unsigned int s_prev_token;
struct ivy_ast_cond_node *s_cur_branch;
b_queue s_branches;
struct ivy_ast_node *s_prev_node;
};
static void init_state(struct ivy_parser *ctx, struct parser_state *sp, uintptr_t arg) static void init_state(struct ivy_parser *ctx, struct parser_state *sp, uintptr_t arg)
{ {
struct cond_group_parser_state *state struct cond_group_parser_state *state
= (struct cond_group_parser_state *)sp; = (struct cond_group_parser_state *)sp;
state->s_prev_node = (struct ivy_ast_node *)arg;
} }
struct token_parse_result parse_if( struct token_parse_result parse_if(
@@ -26,11 +37,11 @@ struct token_parse_result parse_if(
if (state->s_prev_node) { if (state->s_prev_node) {
/* this is an inline if-else */ /* this is an inline if-else */
state->s_type = COND_GROUP_INLINE_IF_ELSE; state->s_inline = true;
state->s_cur_branch->n_body = state->s_prev_node; state->s_cur_branch->n_body = state->s_prev_node;
state->s_prev_node = NULL; state->s_prev_node = NULL;
} else { } else {
state->s_type = COND_GROUP_IF_ELSE; state->s_inline = false;
} }
struct expr_parser_state *expr struct expr_parser_state *expr
@@ -63,7 +74,6 @@ static enum ivy_status flush_current_branch(struct cond_group_parser_state *stat
struct token_parse_result parse_then(struct ivy_parser *ctx, struct ivy_token *tok) struct token_parse_result parse_then(struct ivy_parser *ctx, struct ivy_token *tok)
{ {
enum ivy_status status;
struct cond_group_parser_state *state struct cond_group_parser_state *state
= parser_get_state(ctx, struct cond_group_parser_state); = parser_get_state(ctx, struct cond_group_parser_state);
@@ -71,7 +81,7 @@ struct token_parse_result parse_then(struct ivy_parser *ctx, struct ivy_token *t
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
} }
if (state->s_type != COND_GROUP_IF_ELSE) { if (state->s_inline) {
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
} }
@@ -89,7 +99,7 @@ struct token_parse_result parse_then(struct ivy_parser *ctx, struct ivy_token *t
/* next component will be a block. */ /* next component will be a block. */
struct block_parser_state *block struct block_parser_state *block
= (struct expr_parser_state *)parser_push_state( = (struct block_parser_state *)parser_push_state(
ctx, IVY_AST_BLOCK, 0); ctx, IVY_AST_BLOCK, 0);
/* set the sub-expression depth to be non-zero so the expression parser doesn't consume the expression separator. */ /* set the sub-expression depth to be non-zero so the expression parser doesn't consume the expression separator. */
block->s_terminator = IVY_KW_END; block->s_terminator = IVY_KW_END;
@@ -108,8 +118,7 @@ struct token_parse_result parse_else(struct ivy_parser *ctx, struct ivy_token *t
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
} }
switch (state->s_type) { if (!state->s_inline) {
case COND_GROUP_IF_ELSE:
/* previous component was either an expression or a block, and is the if branch body. */ /* previous component was either an expression or a block, and is the if branch body. */
if (!state->s_prev_node) { if (!state->s_prev_node) {
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
@@ -128,8 +137,7 @@ struct token_parse_result parse_else(struct ivy_parser *ctx, struct ivy_token *t
} }
/* next component should either be an if keyword or a block. */ /* next component should either be an if keyword or a block. */
break; } else {
case COND_GROUP_INLINE_IF_ELSE:
/* previous component was the if-condition. */ /* previous component was the if-condition. */
if (!state->s_prev_node) { if (!state->s_prev_node) {
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
@@ -153,9 +161,6 @@ struct token_parse_result parse_else(struct ivy_parser *ctx, struct ivy_token *t
ctx, IVY_AST_EXPR, 0); ctx, IVY_AST_EXPR, 0);
/* set the sub-expression depth to be non-zero so the expression parser doesn't consume the expression separator. */ /* set the sub-expression depth to be non-zero so the expression parser doesn't consume the expression separator. */
expr->s_subexpr_depth = 1; expr->s_subexpr_depth = 1;
break;
default:
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
} }
state->s_prev_token = IVY_KW_ELSE; state->s_prev_token = IVY_KW_ELSE;
@@ -182,8 +187,7 @@ static enum ivy_status finalise_cond_group(struct cond_group_parser_state* state
struct ivy_ast_cond_group_node *group struct ivy_ast_cond_group_node *group
= (struct ivy_ast_cond_group_node *)state->s_base.s_node; = (struct ivy_ast_cond_group_node *)state->s_base.s_node;
switch (state->s_type) { if (state->s_inline) {
case COND_GROUP_INLINE_IF_ELSE:
/* we have just reached the end of either the 'if' or the 'else' expression. */ /* we have just reached the end of either the 'if' or the 'else' expression. */
if (!state->s_cur_branch) { if (!state->s_cur_branch) {
/* not currently parsing a conditional branch. */ /* not currently parsing a conditional branch. */
@@ -209,7 +213,7 @@ static enum ivy_status finalise_cond_group(struct cond_group_parser_state* state
group->n_branches = state->s_branches; group->n_branches = state->s_branches;
state->s_branches = B_QUEUE_INIT; state->s_branches = B_QUEUE_INIT;
return IVY_OK; return IVY_OK;
case COND_GROUP_IF_ELSE: } else {
/* we have just reached the 'end' keyword. */ /* we have just reached the 'end' keyword. */
if (!state->s_cur_branch) { if (!state->s_cur_branch) {
/* not currently parsing a conditional branch. */ /* not currently parsing a conditional branch. */
@@ -228,8 +232,6 @@ static enum ivy_status finalise_cond_group(struct cond_group_parser_state* state
group->n_branches = state->s_branches; group->n_branches = state->s_branches;
state->s_branches = B_QUEUE_INIT; state->s_branches = B_QUEUE_INIT;
return IVY_OK; return IVY_OK;
default:
return IVY_ERR_NOT_SUPPORTED;
} }
} }
@@ -239,7 +241,7 @@ struct token_parse_result parse_punct_terminator(
struct cond_group_parser_state *state struct cond_group_parser_state *state
= parser_get_state(ctx, struct cond_group_parser_state); = parser_get_state(ctx, struct cond_group_parser_state);
if (state->s_type != COND_GROUP_INLINE_IF_ELSE) { if (!state->s_inline) {
/* only inline conditional can be ended with punctuation. */ /* only inline conditional can be ended with punctuation. */
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
} }
@@ -258,8 +260,8 @@ struct token_parse_result parse_end(struct ivy_parser *ctx, struct ivy_token *to
struct cond_group_parser_state *state struct cond_group_parser_state *state
= parser_get_state(ctx, struct cond_group_parser_state); = parser_get_state(ctx, struct cond_group_parser_state);
if (state->s_type == COND_GROUP_INLINE_IF_ELSE) { if (state->s_inline) {
/* inline if-else must be terminateed with punctuation. */ /* inline if-else must be terminated with punctuation. */
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
} }

View File

@@ -1,25 +0,0 @@
#ifndef _AST_COND_H_
#define _AST_COND_H_
#include "ctx.h"
#include "node.h"
enum cond_group_type {
COND_GROUP_NONE = 0,
COND_GROUP_IF_ELSE,
COND_GROUP_INLINE_IF_ELSE,
COND_GROUP_MATCH,
};
struct cond_group_parser_state {
struct parser_state s_base;
enum cond_group_type s_type;
unsigned int s_prev_token;
struct ivy_ast_cond_node *s_cur_branch;
b_queue s_branches;
struct ivy_ast_node *s_prev_node;
};
#endif

View File

@@ -1,6 +1,5 @@
#include "../node.h" #include "../node.h"
#include "expr.h" #include "expr.h"
#include "../cond.h"
#include <blue/object/string.h> #include <blue/object/string.h>
#include <ivy/lang/lex.h> #include <ivy/lang/lex.h>
@@ -35,13 +34,12 @@ struct token_parse_result stmt_parse_if(
parser_pop_state(ctx, 0); parser_pop_state(ctx, 0);
} }
struct cond_group_parser_state *cond
= (struct cond_group_parser_state *)parser_push_state(
ctx, IVY_AST_COND_GROUP, 0);
/* if expr is NULL, this is an if-then-else-end statement, /* if expr is NULL, this is an if-then-else-end statement,
* otherwise, this is an expr-if-else-expr. */ * otherwise, this is an expr-if-else-expr. */
cond->s_prev_node = expr; struct cond_group_parser_state *cond
= (struct cond_group_parser_state *)parser_push_state(
ctx, IVY_AST_COND_GROUP, (uintptr_t)expr);
return PARSE_RESULT(IVY_OK, PARSE_REPEAT_TOKEN); return PARSE_RESULT(IVY_OK, PARSE_REPEAT_TOKEN);
} }