2026-05-10 19:14:24 +01:00
|
|
|
#include "lex-internal.h"
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
static enum bshell_status word_symbol(struct bshell_lex_ctx *ctx)
|
2026-05-10 19:14:24 +01:00
|
|
|
{
|
2026-05-25 10:33:29 +01:00
|
|
|
const struct bshell_lex_token_definition *sym = NULL;
|
2026-05-10 19:14:24 +01:00
|
|
|
enum bshell_status status = read_symbol(ctx, &sym);
|
|
|
|
|
|
|
|
|
|
if (status != BSHELL_SUCCESS) {
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
struct bshell_lex_token *tok = NULL;
|
2026-05-10 19:14:24 +01:00
|
|
|
|
|
|
|
|
switch (sym->id) {
|
2026-05-25 10:33:29 +01:00
|
|
|
case BSHELL_SYM_DOLLAR_LEFT_PAREN:
|
2026-05-10 19:14:24 +01:00
|
|
|
status = push_symbol(ctx, sym->id);
|
|
|
|
|
if (status != BSHELL_SUCCESS) {
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
lex_state_push(ctx, BSHELL_LEX_STATE_STATEMENT, 0);
|
2026-05-10 19:14:24 +01:00
|
|
|
return BSHELL_SUCCESS;
|
2026-05-25 10:33:29 +01:00
|
|
|
case BSHELL_SYM_RIGHT_PAREN:
|
2026-05-30 19:50:38 +01:00
|
|
|
lex_state_pop(ctx, false);
|
2026-05-10 19:14:24 +01:00
|
|
|
|
|
|
|
|
status = push_symbol(ctx, sym->id);
|
|
|
|
|
if (status != BSHELL_SUCCESS) {
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
return BSHELL_SUCCESS;
|
2026-05-25 10:33:29 +01:00
|
|
|
case BSHELL_SYM_DOLLAR:
|
|
|
|
|
status = read_var(ctx, BSHELL_TOK_VAR, &tok);
|
2026-05-10 19:14:24 +01:00
|
|
|
if (status != BSHELL_SUCCESS) {
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enqueue_token(ctx, tok);
|
|
|
|
|
return status;
|
2026-05-25 10:33:29 +01:00
|
|
|
case BSHELL_SYM_AT:
|
|
|
|
|
status = read_var(ctx, BSHELL_TOK_VAR_SPLAT, &tok);
|
2026-05-10 19:14:24 +01:00
|
|
|
if (status != BSHELL_SUCCESS) {
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enqueue_token(ctx, tok);
|
|
|
|
|
return status;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BSHELL_ERR_BAD_SYNTAX;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
static enum bshell_status word_content(struct bshell_lex_ctx *ctx)
|
2026-05-10 19:14:24 +01:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
struct bshell_lex_token *tok = bshell_lex_token_create_with_string(
|
|
|
|
|
BSHELL_TOK_WORD,
|
2026-05-10 19:14:24 +01:00
|
|
|
fx_string_get_cstr(temp));
|
|
|
|
|
enqueue_token(ctx, tok);
|
|
|
|
|
|
|
|
|
|
return BSHELL_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
static enum bshell_status word_begin(struct bshell_lex_ctx *ctx)
|
2026-05-10 19:14:24 +01:00
|
|
|
{
|
2026-05-30 19:50:38 +01:00
|
|
|
struct bshell_lex_token *tok
|
|
|
|
|
= bshell_lex_token_create(BSHELL_TOK_WORD_START);
|
2026-05-10 19:14:24 +01:00
|
|
|
if (!tok) {
|
|
|
|
|
return BSHELL_ERR_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enqueue_token_with_coordinates(
|
|
|
|
|
ctx,
|
|
|
|
|
tok,
|
|
|
|
|
&ctx->lex_start,
|
|
|
|
|
&ctx->lex_start);
|
|
|
|
|
return BSHELL_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
static enum bshell_status word_end(struct bshell_lex_ctx *ctx)
|
2026-05-10 19:14:24 +01:00
|
|
|
{
|
2026-05-30 19:50:38 +01:00
|
|
|
struct bshell_lex_token *tok
|
|
|
|
|
= bshell_lex_token_create(BSHELL_TOK_WORD_END);
|
2026-05-10 19:14:24 +01:00
|
|
|
if (!tok) {
|
|
|
|
|
return BSHELL_ERR_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enqueue_token_with_coordinates(ctx, tok, &ctx->lex_end, &ctx->lex_end);
|
|
|
|
|
return BSHELL_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
static enum bshell_status word_pump_token(struct bshell_lex_ctx *ctx)
|
2026-05-10 19:14:24 +01:00
|
|
|
{
|
|
|
|
|
fx_wchar c = peek_char(ctx);
|
|
|
|
|
|
|
|
|
|
if (fx_wchar_is_space(c)) {
|
2026-05-30 19:50:38 +01:00
|
|
|
lex_state_pop(ctx, false);
|
2026-05-10 19:14:24 +01:00
|
|
|
return BSHELL_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
if (char_has_flags(ctx, c, BSHELL_LEX_TOKEN_TERMINATES_WORD)) {
|
2026-05-30 19:50:38 +01:00
|
|
|
lex_state_pop(ctx, false);
|
2026-05-10 19:14:24 +01:00
|
|
|
return BSHELL_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (char_can_begin_symbol(ctx, c)) {
|
|
|
|
|
return word_symbol(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return word_content(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-11 23:57:35 +01:00
|
|
|
static const unsigned int symbols[] = {
|
2026-05-25 10:33:29 +01:00
|
|
|
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,
|
2026-05-11 23:02:02 +01:00
|
|
|
};
|
|
|
|
|
|
2026-05-25 10:33:29 +01:00
|
|
|
const struct bshell_lex_state_type lex_word_state = {
|
|
|
|
|
.s_id = BSHELL_LEX_STATE_WORD,
|
2026-05-10 19:14:24 +01:00
|
|
|
.s_begin = word_begin,
|
|
|
|
|
.s_end = word_end,
|
|
|
|
|
.s_pump_token = word_pump_token,
|
2026-05-11 23:57:35 +01:00
|
|
|
.s_symbols = symbols,
|
2026-05-10 19:14:24 +01:00
|
|
|
};
|