bshell: re-organise build into three separate components

bshell: the front-end binary
bshell.runtime: contains the parser, compiler, and classes needed to run bshell scripts
bshell.core: contains the builtin commandlets and aliases
This commit is contained in:
2026-05-25 10:33:29 +01:00
parent 58c76a1f57
commit edfb3e24a3
165 changed files with 5173 additions and 4995 deletions
+100
View File
@@ -0,0 +1,100 @@
#include "../syntax.h"
bool peek_statement(struct bshell_parse_ctx *ctx)
{
if (peek_keyword_expr(ctx)) {
return true;
}
if (peek_arith_expr(ctx)) {
return true;
}
if (peek_command(ctx)) {
return true;
}
return false;
}
bool parse_statement(struct bshell_parse_ctx *ctx, struct bshell_ast_node **out)
{
if (!peek_token(ctx)) {
/* error, or EOF */
return false;
}
bool unknown = true;
bool ok = false;
if (peek_keyword_expr(ctx)) {
unknown = false;
ok = parse_keyword_expr(ctx, out);
}
if (!ok && peek_arith_expr(ctx)) {
unknown = false;
ok = parse_arith_expr(ctx, BSHELL_PRECEDENCE_MINIMUM, out);
}
if (!ok && peek_command(ctx)) {
unknown = false;
ok = parse_command(ctx, out);
}
if (!ok && unknown) {
report_error(
ctx,
"encountered unknown token while parsing statement");
return false;
}
return ok;
}
static struct bshell_ast_node *convert_single_statement(
struct bshell_stmt_list_ast_node *list)
{
fx_queue_entry *first_entry = fx_queue_first(&list->n_statements);
if (!first_entry || fx_queue_next(first_entry)) {
return (struct bshell_ast_node *)list;
}
fx_queue_delete(&list->n_statements, first_entry);
struct bshell_ast_node *first
= fx_unbox(struct bshell_ast_node, first_entry, n_entry);
bshell_ast_node_destroy((struct bshell_ast_node *)list);
return first;
}
bool parse_statement_list(struct bshell_parse_ctx *ctx, struct bshell_ast_node **out)
{
struct bshell_stmt_list_ast_node *stmt_list
= (struct bshell_stmt_list_ast_node *)bshell_ast_node_create(
BSHELL_AST_STMT_LIST);
bool ok = true;
while (ok) {
parse_linefeed(ctx);
struct bshell_ast_node *stmt = NULL;
if (!parse_statement(ctx, &stmt)) {
ok = false;
break;
}
fx_queue_push_back(&stmt_list->n_statements, &stmt->n_entry);
if (!parse_symbol(ctx, BSHELL_SYM_SEMICOLON)) {
break;
}
}
if (!ok) {
bshell_ast_node_destroy((struct bshell_ast_node *)stmt_list);
return false;
}
*out = convert_single_statement(stmt_list);
return true;
}