102 lines
2.2 KiB
C
102 lines
2.2 KiB
C
|
|
#include "ctx.h"
|
||
|
|
|
||
|
|
#include <ivy/lang/ast.h>
|
||
|
|
|
||
|
|
static bool parse_dynamic_package(
|
||
|
|
struct ivy_parser *parser, struct ivy_ast_node *expr,
|
||
|
|
struct ivy_ast_node **out)
|
||
|
|
{
|
||
|
|
if (!parse_keyword(parser, IVY_KW_FOR)) {
|
||
|
|
parse_trace(
|
||
|
|
parser,
|
||
|
|
"expected `for` after package comprehension "
|
||
|
|
"expression");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct ivy_ast_pkg_dynamic_node *pkg = create_node(IVY_AST_PKG_DYNAMIC);
|
||
|
|
pkg->n_transform = expr;
|
||
|
|
|
||
|
|
if (!parse_expr(parser, EXPR_PARSE_STOP_KW_IN, &pkg->n_item)) {
|
||
|
|
parse_trace(parser, "invalid package comprehension item");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!parse_keyword(parser, IVY_KW_IN)) {
|
||
|
|
parse_trace(
|
||
|
|
parser,
|
||
|
|
"expected `in` after package comprehension item");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!parse_expr(parser, EXPR_PARSE_NORMAL, &pkg->n_item)) {
|
||
|
|
parse_trace(parser, "invalid package comprehension container");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!parse_symbol(parser, IVY_SYM_RIGHT_BRACE)) {
|
||
|
|
parse_trace(
|
||
|
|
parser,
|
||
|
|
"expected `}` after package comprehension container");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
*out = generic_node(pkg);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool parse_package(struct ivy_parser *parser, struct ivy_ast_node **out)
|
||
|
|
{
|
||
|
|
if (!parse_symbol(parser, IVY_SYM_LEFT_BRACE)) {
|
||
|
|
parse_trace(parser, "expected `{`");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct ivy_ast_node *item = NULL;
|
||
|
|
if (!parse_expr(
|
||
|
|
parser, EXPR_PARSE_STOP_COMMA | EXPR_PARSE_STOP_KW_CONTROL,
|
||
|
|
&item)) {
|
||
|
|
parse_trace(parser, "invalid package item");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (peek_keyword(parser, IVY_KW_FOR)) {
|
||
|
|
return parse_dynamic_package(parser, item, out);
|
||
|
|
}
|
||
|
|
|
||
|
|
struct ivy_ast_pkg_static_node *pkg = create_node(IVY_AST_PKG_STATIC);
|
||
|
|
if (item) {
|
||
|
|
fx_queue_push_back(&pkg->n_items, &item->n_entry);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ok = true;
|
||
|
|
while (ok) {
|
||
|
|
parse_linefeed(parser);
|
||
|
|
|
||
|
|
if (parse_symbol(parser, IVY_SYM_RIGHT_BRACE)) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!parse_symbol(parser, IVY_SYM_COMMA)) {
|
||
|
|
parse_trace(
|
||
|
|
parser,
|
||
|
|
"expected `,` or `}` after package item");
|
||
|
|
ok = false;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!parse_expr(
|
||
|
|
parser,
|
||
|
|
EXPR_PARSE_STOP_COMMA | EXPR_PARSE_STOP_KW_CONTROL,
|
||
|
|
&item)) {
|
||
|
|
parse_trace(parser, "invalid package item");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
fx_queue_push_back(&pkg->n_items, &item->n_entry);
|
||
|
|
}
|
||
|
|
|
||
|
|
*out = generic_node(pkg);
|
||
|
|
return true;
|
||
|
|
}
|