lang: implement elif keyword for more complex if-statements
This commit is contained in:
@@ -160,6 +160,7 @@ struct ast_node_type block_node_ops = {
|
|||||||
KW_PARSER(VAR, parse_var),
|
KW_PARSER(VAR, parse_var),
|
||||||
KW_PARSER(END, parse_end),
|
KW_PARSER(END, parse_end),
|
||||||
KW_PARSER(ELSE, parse_else),
|
KW_PARSER(ELSE, parse_else),
|
||||||
|
KW_PARSER(ELIF, parse_else), /* same behaviour as ELSE */
|
||||||
KW_PARSER_FALLBACK(parse_keyword),
|
KW_PARSER_FALLBACK(parse_keyword),
|
||||||
},
|
},
|
||||||
.n_symbol_parsers = {
|
.n_symbol_parsers = {
|
||||||
|
|||||||
@@ -20,6 +20,24 @@ static void init_state(struct ivy_parser *ctx, struct parser_state *sp, uintptr_
|
|||||||
state->s_prev_node = (struct ivy_ast_node *)arg;
|
state->s_prev_node = (struct ivy_ast_node *)arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum ivy_status flush_current_branch(struct cond_group_parser_state *state)
|
||||||
|
{
|
||||||
|
if (!state->s_cur_branch) {
|
||||||
|
return IVY_ERR_INTERNAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
b_queue_push_back(&state->s_branches, &state->s_cur_branch->n_base.n_entry);
|
||||||
|
|
||||||
|
state->s_cur_branch
|
||||||
|
= (struct ivy_ast_cond_node *)ast_node_create(IVY_AST_COND);
|
||||||
|
|
||||||
|
if (!state->s_cur_branch) {
|
||||||
|
return IVY_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IVY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
struct token_parse_result parse_if(struct ivy_parser *ctx, struct ivy_token *tok)
|
struct token_parse_result parse_if(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||||
{
|
{
|
||||||
struct cond_group_parser_state *state
|
struct cond_group_parser_state *state
|
||||||
@@ -54,22 +72,45 @@ struct token_parse_result parse_if(struct ivy_parser *ctx, struct ivy_token *tok
|
|||||||
return PARSE_RESULT(IVY_OK, 0);
|
return PARSE_RESULT(IVY_OK, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ivy_status flush_current_branch(struct cond_group_parser_state *state)
|
struct token_parse_result parse_elif(struct ivy_parser *ctx, struct ivy_token *tok)
|
||||||
{
|
{
|
||||||
|
struct cond_group_parser_state *state
|
||||||
|
= parser_get_state(ctx, struct cond_group_parser_state);
|
||||||
|
|
||||||
if (!state->s_cur_branch) {
|
if (!state->s_cur_branch) {
|
||||||
return IVY_ERR_INTERNAL_FAILURE;
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
b_queue_push_back(&state->s_branches, &state->s_cur_branch->n_base.n_entry);
|
if (state->s_inline) {
|
||||||
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->s_prev_token != IVY_KW_THEN) {
|
||||||
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
state->s_cur_branch->n_body = state->s_prev_node;
|
||||||
|
state->s_prev_node = NULL;
|
||||||
|
|
||||||
|
enum ivy_status status = flush_current_branch(state);
|
||||||
|
if (status != IVY_OK) {
|
||||||
|
return PARSE_RESULT(status, 0);
|
||||||
|
}
|
||||||
|
|
||||||
state->s_cur_branch
|
state->s_cur_branch
|
||||||
= (struct ivy_ast_cond_node *)ast_node_create(IVY_AST_COND);
|
= (struct ivy_ast_cond_node *)ast_node_create(IVY_AST_COND);
|
||||||
|
|
||||||
if (!state->s_cur_branch) {
|
if (!state->s_cur_branch) {
|
||||||
return IVY_ERR_NO_MEMORY;
|
return PARSE_RESULT(IVY_ERR_NO_MEMORY, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IVY_OK;
|
struct expr_parser_state *expr
|
||||||
|
= (struct expr_parser_state *)parser_push_state(
|
||||||
|
ctx, IVY_AST_EXPR, 0);
|
||||||
|
|
||||||
|
state->s_prev_token = IVY_KW_ELIF;
|
||||||
|
expr->s_subexpr_depth = 1;
|
||||||
|
|
||||||
|
return PARSE_RESULT(IVY_OK, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct token_parse_result parse_then(
|
static struct token_parse_result parse_then(
|
||||||
@@ -86,7 +127,7 @@ static struct token_parse_result parse_then(
|
|||||||
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->s_prev_token != IVY_KW_IF) {
|
if (state->s_prev_token != IVY_KW_IF && state->s_prev_token != IVY_KW_ELIF) {
|
||||||
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +144,8 @@ static struct token_parse_result parse_then(
|
|||||||
= (struct block_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_add_terminator(block, IVY_KW_ELIF);
|
||||||
|
block_add_terminator(block, IVY_KW_ELSE);
|
||||||
block_add_terminator(block, IVY_KW_END);
|
block_add_terminator(block, IVY_KW_END);
|
||||||
|
|
||||||
state->s_prev_token = IVY_KW_THEN;
|
state->s_prev_token = IVY_KW_THEN;
|
||||||
@@ -138,7 +181,7 @@ static struct token_parse_result parse_else(
|
|||||||
return PARSE_RESULT(status, 0);
|
return PARSE_RESULT(status, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* next component should either be an if keyword or a block. */
|
/* next component should be a block. */
|
||||||
} else {
|
} else {
|
||||||
/* previous component was the if-condition. */
|
/* previous component was the if-condition. */
|
||||||
if (!state->s_prev_node) {
|
if (!state->s_prev_node) {
|
||||||
@@ -332,6 +375,7 @@ struct ast_node_type cond_group_node_ops = {
|
|||||||
.n_keyword_parsers = {
|
.n_keyword_parsers = {
|
||||||
KW_PARSER(IF, parse_if),
|
KW_PARSER(IF, parse_if),
|
||||||
KW_PARSER(THEN, parse_then),
|
KW_PARSER(THEN, parse_then),
|
||||||
|
KW_PARSER(ELIF, parse_elif),
|
||||||
KW_PARSER(ELSE, parse_else),
|
KW_PARSER(ELSE, parse_else),
|
||||||
KW_PARSER(END, parse_end),
|
KW_PARSER(END, parse_end),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ struct ast_node_type expr_node_ops = {
|
|||||||
KW_PARSER(IF, stmt_parse_if),
|
KW_PARSER(IF, stmt_parse_if),
|
||||||
KW_PARSER(THEN, stmt_parse_end),
|
KW_PARSER(THEN, stmt_parse_end),
|
||||||
KW_PARSER(ELSE, stmt_parse_end),
|
KW_PARSER(ELSE, stmt_parse_end),
|
||||||
|
KW_PARSER(ELIF, stmt_parse_end),
|
||||||
KW_PARSER(CATCH, stmt_parse_end),
|
KW_PARSER(CATCH, stmt_parse_end),
|
||||||
KW_PARSER(FINALLY, stmt_parse_end),
|
KW_PARSER(FINALLY, stmt_parse_end),
|
||||||
KW_PARSER(END, stmt_parse_end),
|
KW_PARSER(END, stmt_parse_end),
|
||||||
|
|||||||
@@ -34,13 +34,14 @@ enum ivy_keyword {
|
|||||||
IVY_KW_THROW,
|
IVY_KW_THROW,
|
||||||
IVY_KW_CATCH,
|
IVY_KW_CATCH,
|
||||||
IVY_KW_FINALLY,
|
IVY_KW_FINALLY,
|
||||||
IVY_KW_IF,
|
|
||||||
IVY_KW_THEN,
|
|
||||||
IVY_KW_AND,
|
IVY_KW_AND,
|
||||||
IVY_KW_OR,
|
IVY_KW_OR,
|
||||||
IVY_KW_UNDERSTANDS,
|
IVY_KW_UNDERSTANDS,
|
||||||
IVY_KW_IS,
|
IVY_KW_IS,
|
||||||
IVY_KW_NOT,
|
IVY_KW_NOT,
|
||||||
|
IVY_KW_IF,
|
||||||
|
IVY_KW_THEN,
|
||||||
|
IVY_KW_ELIF,
|
||||||
IVY_KW_ELSE,
|
IVY_KW_ELSE,
|
||||||
IVY_KW_WHILE,
|
IVY_KW_WHILE,
|
||||||
IVY_KW_FOR,
|
IVY_KW_FOR,
|
||||||
|
|||||||
@@ -31,12 +31,13 @@ static struct lex_token_def keywords[] = {
|
|||||||
LEX_TOKEN_DEF(IVY_KW_FINALLY, "finally"),
|
LEX_TOKEN_DEF(IVY_KW_FINALLY, "finally"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_UNDERSTANDS, "understands"),
|
LEX_TOKEN_DEF(IVY_KW_UNDERSTANDS, "understands"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_IF, "if"),
|
LEX_TOKEN_DEF(IVY_KW_IF, "if"),
|
||||||
|
LEX_TOKEN_DEF(IVY_KW_ELIF, "elif"),
|
||||||
|
LEX_TOKEN_DEF(IVY_KW_ELSE, "else"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_THEN, "then"),
|
LEX_TOKEN_DEF(IVY_KW_THEN, "then"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_AND, "and"),
|
LEX_TOKEN_DEF(IVY_KW_AND, "and"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_OR, "or"),
|
LEX_TOKEN_DEF(IVY_KW_OR, "or"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_IS, "is"),
|
LEX_TOKEN_DEF(IVY_KW_IS, "is"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_NOT, "not"),
|
LEX_TOKEN_DEF(IVY_KW_NOT, "not"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_ELSE, "else"),
|
|
||||||
LEX_TOKEN_DEF(IVY_KW_WHILE, "while"),
|
LEX_TOKEN_DEF(IVY_KW_WHILE, "while"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_FOR, "for"),
|
LEX_TOKEN_DEF(IVY_KW_FOR, "for"),
|
||||||
LEX_TOKEN_DEF(IVY_KW_MATCH, "match"),
|
LEX_TOKEN_DEF(IVY_KW_MATCH, "match"),
|
||||||
@@ -1140,6 +1141,7 @@ const char *ivy_keyword_to_string(enum ivy_keyword keyword)
|
|||||||
ENUM_STR(IVY_KW_CATCH);
|
ENUM_STR(IVY_KW_CATCH);
|
||||||
ENUM_STR(IVY_KW_FINALLY);
|
ENUM_STR(IVY_KW_FINALLY);
|
||||||
ENUM_STR(IVY_KW_IF);
|
ENUM_STR(IVY_KW_IF);
|
||||||
|
ENUM_STR(IVY_KW_ELIF);
|
||||||
ENUM_STR(IVY_KW_THEN);
|
ENUM_STR(IVY_KW_THEN);
|
||||||
ENUM_STR(IVY_KW_AND);
|
ENUM_STR(IVY_KW_AND);
|
||||||
ENUM_STR(IVY_KW_OR);
|
ENUM_STR(IVY_KW_OR);
|
||||||
|
|||||||
Reference in New Issue
Block a user