Files
bshell/bshell/parse/lex/word.c
T

151 lines
2.9 KiB
C
Raw Normal View History

#include "lex-internal.h"
static enum bshell_status word_symbol(struct lex_ctx *ctx)
{
const struct lex_token_def *sym = NULL;
enum bshell_status status = read_symbol(ctx, &sym);
if (status != BSHELL_SUCCESS) {
return status;
}
struct lex_token *tok = NULL;
switch (sym->id) {
case SYM_DOLLAR_LEFT_PAREN:
status = push_symbol(ctx, sym->id);
if (status != BSHELL_SUCCESS) {
return status;
}
lex_state_push(ctx, LEX_STATE_STATEMENT, 0);
return BSHELL_SUCCESS;
case SYM_RIGHT_PAREN:
lex_state_pop(ctx);
status = push_symbol(ctx, sym->id);
if (status != BSHELL_SUCCESS) {
return status;
}
return BSHELL_SUCCESS;
case SYM_DOLLAR:
status = read_var(ctx, TOK_VAR, &tok);
if (status != BSHELL_SUCCESS) {
return status;
}
enqueue_token(ctx, tok);
return status;
case SYM_AT:
status = read_var(ctx, 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 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 lex_token *tok = lex_token_create_with_string(
TOK_WORD,
fx_string_get_cstr(temp));
enqueue_token(ctx, tok);
return BSHELL_SUCCESS;
}
static enum bshell_status word_begin(struct lex_ctx *ctx)
{
struct lex_token *tok = lex_token_create(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 lex_ctx *ctx)
{
struct lex_token *tok = lex_token_create(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 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, 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 struct lex_state_link links[] = {
LINK_END,
};
const struct lex_state_type lex_word_state = {
.s_id = LEX_STATE_WORD,
.s_begin = word_begin,
.s_end = word_end,
.s_pump_token = word_pump_token,
.s_links = links,
};