#include "lex-internal.h" static enum bshell_status word_symbol(struct bshell_lex_ctx *ctx) { const struct bshell_lex_token_definition *sym = NULL; enum bshell_status status = read_symbol(ctx, &sym); if (status != BSHELL_SUCCESS) { return status; } struct bshell_lex_token *tok = NULL; switch (sym->id) { case BSHELL_SYM_DOLLAR_LEFT_PAREN: status = push_symbol(ctx, sym->id); if (status != BSHELL_SUCCESS) { return status; } lex_state_push(ctx, BSHELL_LEX_STATE_STATEMENT, 0); return BSHELL_SUCCESS; case BSHELL_SYM_RIGHT_PAREN: lex_state_pop(ctx); status = push_symbol(ctx, sym->id); if (status != BSHELL_SUCCESS) { return status; } return BSHELL_SUCCESS; case BSHELL_SYM_DOLLAR: status = read_var(ctx, BSHELL_TOK_VAR, &tok); if (status != BSHELL_SUCCESS) { return status; } enqueue_token(ctx, tok); return status; case BSHELL_SYM_AT: status = read_var(ctx, BSHELL_TOK_VAR_SPLAT, &tok); if (status != BSHELL_SUCCESS) { return status; } enqueue_token(ctx, tok); return status; default: break; } return BSHELL_ERR_BAD_SYNTAX; } static enum bshell_status word_content(struct bshell_lex_ctx *ctx) { fx_wchar c = FX_WCHAR_INVALID; fx_string *temp = lex_state_get_tempstr(ctx); set_token_start(ctx); fx_string_clear(temp); while (1) { c = peek_char(ctx); if (c == FX_WCHAR_INVALID) { /* EOF without end of word */ ctx->lex_status = BSHELL_ERR_BAD_SYNTAX; } if (fx_wchar_is_space(c)) { break; } if (char_can_begin_symbol(ctx, c)) { break; } fx_string_append_wc(temp, c); set_token_end(ctx); advance_char(ctx); } if (fx_string_get_size(temp, FX_STRLEN_NORMAL) == 0) { return BSHELL_SUCCESS; } struct bshell_lex_token *tok = bshell_lex_token_create_with_string( BSHELL_TOK_WORD, fx_string_get_cstr(temp)); enqueue_token(ctx, tok); return BSHELL_SUCCESS; } static enum bshell_status word_begin(struct bshell_lex_ctx *ctx) { struct bshell_lex_token *tok = bshell_lex_token_create(BSHELL_TOK_WORD_START); if (!tok) { return BSHELL_ERR_NO_MEMORY; } enqueue_token_with_coordinates( ctx, tok, &ctx->lex_start, &ctx->lex_start); return BSHELL_SUCCESS; } static enum bshell_status word_end(struct bshell_lex_ctx *ctx) { struct bshell_lex_token *tok = bshell_lex_token_create(BSHELL_TOK_WORD_END); if (!tok) { return BSHELL_ERR_NO_MEMORY; } enqueue_token_with_coordinates(ctx, tok, &ctx->lex_end, &ctx->lex_end); return BSHELL_SUCCESS; } static enum bshell_status word_pump_token(struct bshell_lex_ctx *ctx) { fx_wchar c = peek_char(ctx); if (fx_wchar_is_space(c)) { lex_state_pop(ctx); return BSHELL_SUCCESS; } if (char_has_flags(ctx, c, BSHELL_LEX_TOKEN_TERMINATES_WORD)) { lex_state_pop(ctx); return BSHELL_SUCCESS; } if (char_can_begin_symbol(ctx, c)) { return word_symbol(ctx); } return word_content(ctx); } static const unsigned int symbols[] = { BSHELL_SYM_AMPERSAND, BSHELL_SYM_HASH, BSHELL_SYM_DOLLAR, BSHELL_SYM_DOLLAR_LEFT_PAREN, BSHELL_SYM_DOLLAR_LEFT_BRACE, BSHELL_SYM_PIPE, BSHELL_SYM_COMMA, BSHELL_SYM_SEMICOLON, BSHELL_SYM_LEFT_BRACE, BSHELL_SYM_RIGHT_BRACE, BSHELL_SYM_LEFT_PAREN, BSHELL_SYM_RIGHT_PAREN, BSHELL_SYM_NONE, }; const struct bshell_lex_state_type lex_word_state = { .s_id = BSHELL_LEX_STATE_WORD, .s_begin = word_begin, .s_end = word_end, .s_pump_token = word_pump_token, .s_symbols = symbols, };