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 "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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 "../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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user