#include "lex-internal.h" static enum bshell_status hashtable_hyphen(struct bshell_lex_ctx *ctx) { fx_wchar c = peek_char(ctx); if (!fx_wchar_is_alnum(c)) { push_symbol(ctx, BSHELL_SYM_HYPHEN); handle_lex_state_transition(ctx, BSHELL_SYM_HYPHEN); return BSHELL_SUCCESS; } struct bshell_lex_token *tok = NULL; enum bshell_status status = read_word( ctx, READ_NO_SET_TOKEN_START | READ_APPEND_HYPHEN, &tok); if (status != BSHELL_SUCCESS) { return status; } unsigned int token_type = BSHELL_TOK_WORD; if (convert_word_to_number(tok)) { token_type = tok->tok_type; /* because of APPEND_HYPHEN (which is needed to ensure operator * tokens are detected properly), the resulting number will be * negative. * this token will be preceded by a HYPHEN token, so the number * must be positive */ fx_value neg = FX_INT(-1); fx_value_multiply(&tok->tok_number, &neg, &tok->tok_number); push_symbol(ctx, BSHELL_SYM_HYPHEN); } else if (convert_word_to_operator(ctx, tok)) { token_type = tok->tok_operator; } handle_lex_state_transition(ctx, token_type); enqueue_token(ctx, tok); return BSHELL_SUCCESS; } static enum bshell_status hashtable_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_SQUOTE: status = read_literal_string(ctx, &tok); if (status != BSHELL_SUCCESS) { return status; } enqueue_token(ctx, tok); return BSHELL_SUCCESS; case BSHELL_SYM_HYPHEN: return hashtable_hyphen(ctx); case BSHELL_SYM_HASH: return read_line_comment(ctx); 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; } push_symbol(ctx, sym->id); return BSHELL_SUCCESS; } static enum bshell_status hashtable_word(struct bshell_lex_ctx *ctx) { struct bshell_lex_token *word = NULL; enum bshell_status status = read_word(ctx, 0, &word); if (status != BSHELL_SUCCESS) { return status; } convert_word_to_number(word); handle_lex_state_transition(ctx, word->tok_type); enqueue_token(ctx, word); return BSHELL_SUCCESS; } static enum bshell_status hashtable_pump_token(struct bshell_lex_ctx *ctx) { fx_wchar c = peek_char(ctx); bool newline = false; set_token_start(ctx); while (fx_wchar_is_space(c)) { if (c == '\n') { newline = true; } set_token_end(ctx); advance_char_noread(ctx); c = peek_char_noread(ctx); } #if 1 if (newline) { struct bshell_lex_token *tok = bshell_lex_token_create(BSHELL_TOK_LINEFEED); enqueue_token(ctx, tok); return BSHELL_SUCCESS; } #endif if (char_can_begin_symbol(ctx, c)) { return hashtable_symbol(ctx); } return hashtable_word(ctx); } static const struct bshell_lex_state_link links[] = { LINK_PUSH_WITH_TERM( BSHELL_SYM_EQUAL, BSHELL_LEX_STATE_STATEMENT, 0, BSHELL_SYM_RIGHT_BRACE, BSHELL_SYM_SEMICOLON, BSHELL_TOK_LINEFEED), LINK_PUSH_WITH_TERM( BSHELL_TOK_LINEFEED, BSHELL_LEX_STATE_STATEMENT, 0, BSHELL_SYM_SEMICOLON, BSHELL_TOK_LINEFEED), LINK_PUSH(BSHELL_SYM_DQUOTE, BSHELL_LEX_STATE_STRING, 0), LINK_PUSH( BSHELL_SYM_LEFT_PAREN, BSHELL_LEX_STATE_STATEMENT, STATEMENT_F_DISABLE_KEYWORDS), LINK_PUSH(BSHELL_SYM_DOLLAR_LEFT_PAREN, BSHELL_LEX_STATE_STATEMENT, 0), LINK_POP2(BSHELL_SYM_RIGHT_BRACE, LINK_ALLOW_RECURSION), LINK_END, }; static const unsigned int symbols[] = { BSHELL_SYM_EQUAL, BSHELL_SYM_DQUOTE, BSHELL_SYM_SQUOTE, BSHELL_SYM_SEMICOLON, BSHELL_SYM_RIGHT_BRACE, BSHELL_SYM_DOLLAR_LEFT_PAREN, BSHELL_SYM_LEFT_PAREN, BSHELL_SYM_HASH, BSHELL_SYM_NONE, }; const struct bshell_lex_state_type lex_hashtable_state = { .s_id = BSHELL_LEX_STATE_HASHTABLE, .s_pump_token = hashtable_pump_token, .s_links = links, .s_symbols = symbols, };