#include "lex-internal.h" static enum bshell_status string_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; } handle_lex_state_transition(ctx, sym->id); struct bshell_lex_token *tok = NULL; switch (sym->id) { case BSHELL_SYM_DQUOTE: return BSHELL_SUCCESS; case BSHELL_SYM_DOLLAR_LEFT_PAREN: return push_symbol(ctx, sym->id); 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; case BSHELL_SYM_DOLLAR_LEFT_BRACE: status = read_braced_var(ctx, BSHELL_TOK_VAR, &tok); if (status != BSHELL_SUCCESS) { return status; } enqueue_token(ctx, tok); return status; default: break; } return BSHELL_ERR_BAD_SYNTAX; } static enum bshell_status string_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 string */ ctx->lex_status = BSHELL_ERR_BAD_SYNTAX; } 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_STRING, fx_string_get_cstr(temp)); enqueue_token(ctx, tok); return BSHELL_SUCCESS; } static enum bshell_status string_begin(struct bshell_lex_ctx *ctx) { struct bshell_lex_token *tok = bshell_lex_token_create(BSHELL_TOK_STR_START); if (!tok) { return BSHELL_ERR_NO_MEMORY; } enqueue_token(ctx, tok); return BSHELL_SUCCESS; } static enum bshell_status string_end(struct bshell_lex_ctx *ctx) { struct bshell_lex_token *tok = bshell_lex_token_create(BSHELL_TOK_STR_END); if (!tok) { return BSHELL_ERR_NO_MEMORY; } enqueue_token(ctx, tok); return BSHELL_SUCCESS; } static enum bshell_status string_pump_token(struct bshell_lex_ctx *ctx) { fx_wchar c = peek_char(ctx); if (char_can_begin_symbol(ctx, c)) { return string_symbol(ctx); } return string_content(ctx); } static const struct bshell_lex_state_link links[] = { LINK_PUSH(BSHELL_SYM_DOLLAR_LEFT_PAREN, BSHELL_LEX_STATE_STATEMENT, 0), LINK_POP(BSHELL_SYM_DQUOTE), LINK_END, }; static const unsigned int symbols[] = { BSHELL_SYM_DOLLAR, BSHELL_SYM_DOLLAR_LEFT_PAREN, BSHELL_SYM_DOLLAR_LEFT_BRACE, BSHELL_SYM_DQUOTE, BSHELL_SYM_NONE, }; const struct bshell_lex_state_type lex_string_state = { .s_id = BSHELL_LEX_STATE_STRING, .s_begin = string_begin, .s_end = string_end, .s_pump_token = string_pump_token, .s_links = links, .s_symbols = symbols, };