diff --git a/bshell/parse/parse.c b/bshell/parse/parse.c index d760f50..9af91b9 100644 --- a/bshell/parse/parse.c +++ b/bshell/parse/parse.c @@ -24,7 +24,7 @@ void parse_ctx_cleanup(struct parse_ctx *ctx) struct ast_node *parse_ctx_read_node(struct parse_ctx *ctx) { struct ast_node *result = NULL; - bool ok = parse_expr(ctx, &result); + bool ok = parse_statement(ctx, &result); return ok ? result : NULL; } diff --git a/bshell/parse/syntax.h b/bshell/parse/syntax.h index 6e40947..33cd0c5 100644 --- a/bshell/parse/syntax.h +++ b/bshell/parse/syntax.h @@ -16,22 +16,20 @@ extern struct lex_token *peek_token(struct parse_ctx *ctx); extern enum token_type peek_token_type(struct parse_ctx *ctx); extern enum token_keyword peek_unknown_keyword(struct parse_ctx *ctx); extern enum token_symbol peek_unknown_symbol(struct parse_ctx *ctx); -extern bool peek_int(struct parse_ctx *ctx); extern struct lex_token *claim_token(struct parse_ctx *ctx); -extern struct lex_token *claim_glob_word(struct parse_ctx *ctx); extern void discard_token(struct parse_ctx *ctx); extern bool peek_linefeed(struct parse_ctx *ctx); extern bool peek_symbol(struct parse_ctx *ctx, enum token_symbol sym); -extern struct lex_token *peek_glob_word(struct parse_ctx *ctx); +extern bool peek_word(struct parse_ctx *ctx, struct lex_token **out); +extern bool peek_int(struct parse_ctx *ctx); extern bool parse_linefeed(struct parse_ctx *ctx); extern bool parse_symbol(struct parse_ctx *ctx, enum token_symbol sym); extern bool parse_keyword(struct parse_ctx *ctx, enum token_keyword kw); extern bool parse_int(struct parse_ctx *ctx, long long *out); extern bool parse_flag(struct parse_ctx *ctx, struct lex_token **out); -extern struct lex_token *parse_glob_word(struct parse_ctx *ctx); extern bool peek_arith_expr(struct parse_ctx *ctx); extern bool parse_arith_expr(struct parse_ctx *ctx, struct ast_node **out); @@ -40,7 +38,7 @@ extern bool parse_operand( enum parse_operand_flags flags, struct ast_node **out); -extern bool parse_expr(struct parse_ctx *ctx, struct ast_node **out); +extern bool parse_statement(struct parse_ctx *ctx, struct ast_node **out); extern bool peek_command(struct parse_ctx *ctx); extern bool parse_command(struct parse_ctx *ctx, struct ast_node **out); diff --git a/bshell/parse/syntax/command.c b/bshell/parse/syntax/command.c index b473871..4174b97 100644 --- a/bshell/parse/syntax/command.c +++ b/bshell/parse/syntax/command.c @@ -4,6 +4,10 @@ static bool parse_cmdcall_arg(struct parse_ctx *ctx, struct ast_node **out) { + if (ctx->p_status != BSHELL_SUCCESS) { + return false; + } + struct lex_token *tok = peek_token(ctx); if (!tok) { return false; @@ -80,19 +84,7 @@ static bool parse_cmdcall_arg(struct parse_ctx *ctx, struct ast_node **out) return true; } - default: { - struct word_ast_node *n - = (struct word_ast_node *)ast_node_create(AST_WORD); - if (!n) { - ctx->p_status = BSHELL_ERR_NO_MEMORY; - return false; - } - - n->n_value = claim_glob_word(ctx); - *out = (struct ast_node *)n; - return true; - } - + default: return false; } @@ -105,6 +97,10 @@ static bool parse_redirect_to_fd( bool append, struct ast_node **out) { + if (ctx->p_status != BSHELL_SUCCESS) { + return false; + } + struct redirection_ast_node *redirect = (struct redirection_ast_node *)ast_node_create( AST_REDIRECTION); @@ -117,18 +113,34 @@ static bool parse_redirect_to_fd( return false; } - long long out_fd = 0; - if (!parse_int(ctx, &out_fd)) { - ctx->p_status = BSHELL_ERR_BAD_SYNTAX; - ast_node_destroy((struct ast_node *)redirect); + struct lex_token *out_tok = NULL; + struct ast_node *out_expr = NULL; + long long out_fd = -1; + + if (peek_word(ctx, &out_tok)) { + const char *s = out_tok->tok_str; + char *ep; + out_fd = strtoll(s, &ep, 10); + if (*ep == '\0') { + discard_token(ctx); + out_tok = NULL; + } else { + out_fd = -1; + } + } else if (!parse_cmdcall_arg(ctx, &out_expr)) { return false; } - redirect->n_out_is_fd = true; - redirect->n_out_is_expr = false; + redirect->n_out_is_fd = (out_fd >= 0) || out_expr; + redirect->n_out_is_expr = out_expr != NULL; redirect->n_out = (unsigned int)out_fd; - *out = (struct ast_node *)redirect; + redirect->n_out_path_expr = out_expr; + if (out_tok) { + redirect->n_out_tok = claim_token(ctx); + redirect->n_out_path = out_tok->tok_str; + } + *out = (struct ast_node *)redirect; return true; } @@ -139,6 +151,10 @@ static bool parse_redirect_to_file_squashed( const char *str, struct ast_node **out) { + if (ctx->p_status != BSHELL_SUCCESS) { + return false; + } + struct lex_token *tok = peek_token(ctx); if (*str == '\0') { return false; @@ -166,6 +182,10 @@ static bool parse_redirect_to_file_separate( bool append, struct ast_node **out) { + if (ctx->p_status != BSHELL_SUCCESS) { + return false; + } + struct ast_node *out_path = NULL; if (!parse_cmdcall_arg(ctx, &out_path)) { ctx->p_status = BSHELL_ERR_BAD_SYNTAX; diff --git a/bshell/parse/syntax/generic.c b/bshell/parse/syntax/generic.c index 67dc413..2eda2ef 100644 --- a/bshell/parse/syntax/generic.c +++ b/bshell/parse/syntax/generic.c @@ -8,11 +8,6 @@ struct lex_token *claim_token(struct parse_ctx *ctx) return lex_ctx_claim(ctx->p_src); } -struct lex_token *claim_glob_word(struct parse_ctx *ctx) -{ - return lex_ctx_claim_word(ctx->p_src); -} - void discard_token(struct parse_ctx *ctx) { return lex_ctx_discard(ctx->p_src); @@ -43,6 +38,17 @@ enum token_keyword peek_unknown_keyword(struct parse_ctx *ctx) : KW_NONE; } +bool peek_word(struct parse_ctx *ctx, struct lex_token **out) +{ + struct lex_token *tok = peek_token(ctx); + if (tok && tok->tok_type == TOK_WORD) { + *out = tok; + return true; + } + + return false; +} + bool peek_linefeed(struct parse_ctx *ctx) { struct lex_token *tok = peek_token(ctx); diff --git a/bshell/parse/syntax/expr.c b/bshell/parse/syntax/statement.c similarity index 74% rename from bshell/parse/syntax/expr.c rename to bshell/parse/syntax/statement.c index 1d48dd6..c28ef8c 100644 --- a/bshell/parse/syntax/expr.c +++ b/bshell/parse/syntax/statement.c @@ -1,11 +1,12 @@ #include "../syntax.h" -bool parse_expr(struct parse_ctx *ctx, struct ast_node **out) +bool parse_statement(struct parse_ctx *ctx, struct ast_node **out) { bool ok = false; if (peek_arith_expr(ctx)) { ok = parse_arith_expr(ctx, out); } + if (!ok && peek_command(ctx)) { ok = parse_command(ctx, out); }