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:
@@ -1,11 +1,22 @@
|
||||
#include "cond.h"
|
||||
#include "block.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)
|
||||
{
|
||||
struct cond_group_parser_state *state
|
||||
= (struct cond_group_parser_state *)sp;
|
||||
state->s_prev_node = (struct ivy_ast_node *)arg;
|
||||
}
|
||||
|
||||
struct token_parse_result parse_if(
|
||||
@@ -26,11 +37,11 @@ struct token_parse_result parse_if(
|
||||
|
||||
if (state->s_prev_node) {
|
||||
/* 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_prev_node = NULL;
|
||||
} else {
|
||||
state->s_type = COND_GROUP_IF_ELSE;
|
||||
state->s_inline = false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
enum ivy_status status;
|
||||
struct cond_group_parser_state *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);
|
||||
}
|
||||
|
||||
if (state->s_type != COND_GROUP_IF_ELSE) {
|
||||
if (state->s_inline) {
|
||||
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. */
|
||||
struct block_parser_state *block
|
||||
= (struct expr_parser_state *)parser_push_state(
|
||||
= (struct block_parser_state *)parser_push_state(
|
||||
ctx, IVY_AST_BLOCK, 0);
|
||||
/* 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;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
switch (state->s_type) {
|
||||
case COND_GROUP_IF_ELSE:
|
||||
if (!state->s_inline) {
|
||||
/* previous component was either an expression or a block, and is the if branch body. */
|
||||
if (!state->s_prev_node) {
|
||||
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. */
|
||||
break;
|
||||
case COND_GROUP_INLINE_IF_ELSE:
|
||||
} else {
|
||||
/* previous component was the if-condition. */
|
||||
if (!state->s_prev_node) {
|
||||
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);
|
||||
/* set the sub-expression depth to be non-zero so the expression parser doesn't consume the expression separator. */
|
||||
expr->s_subexpr_depth = 1;
|
||||
break;
|
||||
default:
|
||||
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
||||
}
|
||||
|
||||
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 *)state->s_base.s_node;
|
||||
|
||||
switch (state->s_type) {
|
||||
case COND_GROUP_INLINE_IF_ELSE:
|
||||
if (state->s_inline) {
|
||||
/* we have just reached the end of either the 'if' or the 'else' expression. */
|
||||
if (!state->s_cur_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;
|
||||
state->s_branches = B_QUEUE_INIT;
|
||||
return IVY_OK;
|
||||
case COND_GROUP_IF_ELSE:
|
||||
} else {
|
||||
/* we have just reached the 'end' keyword. */
|
||||
if (!state->s_cur_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;
|
||||
state->s_branches = B_QUEUE_INIT;
|
||||
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
|
||||
= 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. */
|
||||
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
|
||||
= parser_get_state(ctx, struct cond_group_parser_state);
|
||||
|
||||
if (state->s_type == COND_GROUP_INLINE_IF_ELSE) {
|
||||
/* inline if-else must be terminateed with punctuation. */
|
||||
if (state->s_inline) {
|
||||
/* inline if-else must be terminated with punctuation. */
|
||||
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../node.h"
|
||||
#include "expr.h"
|
||||
#include "../cond.h"
|
||||
|
||||
#include <blue/object/string.h>
|
||||
#include <ivy/lang/lex.h>
|
||||
@@ -35,13 +34,12 @@ struct token_parse_result stmt_parse_if(
|
||||
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,
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user