163 lines
3.3 KiB
C
163 lines
3.3 KiB
C
#include "lex-internal.h"
|
|
|
|
static enum bshell_status statement_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_SQUOTE:
|
|
status = read_literal_string(ctx, &tok);
|
|
if (status != BSHELL_SUCCESS) {
|
|
return status;
|
|
}
|
|
enqueue_token(ctx, tok);
|
|
return BSHELL_SUCCESS;
|
|
|
|
case SYM_HASH:
|
|
return read_line_comment(ctx);
|
|
case SYM_DQUOTE:
|
|
if (!lex_state_push(ctx, LEX_STATE_STRING)) {
|
|
return BSHELL_ERR_NO_MEMORY;
|
|
}
|
|
|
|
return BSHELL_SUCCESS;
|
|
case SYM_DOLLAR:
|
|
if (!lex_state_push(ctx, LEX_STATE_ARITHMETIC)) {
|
|
return BSHELL_ERR_NO_MEMORY;
|
|
}
|
|
|
|
status = read_var(ctx, TOK_VAR, &tok);
|
|
if (status != BSHELL_SUCCESS) {
|
|
return status;
|
|
}
|
|
|
|
enqueue_token(ctx, tok);
|
|
return status;
|
|
case SYM_AT:
|
|
if (!lex_state_push(ctx, LEX_STATE_ARITHMETIC)) {
|
|
return BSHELL_ERR_NO_MEMORY;
|
|
}
|
|
|
|
status = read_var(ctx, TOK_VAR_SPLAT, &tok);
|
|
if (status != BSHELL_SUCCESS) {
|
|
return status;
|
|
}
|
|
|
|
enqueue_token(ctx, tok);
|
|
return status;
|
|
case SYM_DOLLAR_LEFT_BRACE:
|
|
if (!lex_state_push(ctx, LEX_STATE_ARITHMETIC)) {
|
|
return BSHELL_ERR_NO_MEMORY;
|
|
}
|
|
|
|
status = read_braced_var(ctx, TOK_VAR, &tok);
|
|
if (status != BSHELL_SUCCESS) {
|
|
return status;
|
|
}
|
|
|
|
enqueue_token(ctx, tok);
|
|
return status;
|
|
case SYM_AT_LEFT_BRACE:
|
|
if (!lex_state_push(ctx, LEX_STATE_ARITHMETIC)) {
|
|
return BSHELL_ERR_NO_MEMORY;
|
|
}
|
|
|
|
status = read_braced_var(ctx, TOK_VAR_SPLAT, &tok);
|
|
if (status != BSHELL_SUCCESS) {
|
|
return status;
|
|
}
|
|
|
|
enqueue_token(ctx, tok);
|
|
return status;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
push_symbol(ctx, sym->id);
|
|
|
|
switch (sym->id) {
|
|
case SYM_LEFT_PAREN:
|
|
lex_state_push(ctx, LEX_STATE_EXPRESSION);
|
|
return BSHELL_SUCCESS;
|
|
case SYM_LEFT_BRACE:
|
|
case SYM_DOLLAR_LEFT_PAREN:
|
|
lex_state_push(ctx, LEX_STATE_STATEMENT);
|
|
return BSHELL_SUCCESS;
|
|
case SYM_RIGHT_PAREN:
|
|
case SYM_RIGHT_BRACE:
|
|
lex_state_pop(ctx);
|
|
return BSHELL_SUCCESS;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (sym->enabled_states & LEX_STATE_COMMAND) {
|
|
lex_state_change(ctx, LEX_STATE_COMMAND);
|
|
} else if (sym->enabled_states & LEX_STATE_ARITHMETIC) {
|
|
lex_state_change(ctx, LEX_STATE_ARITHMETIC);
|
|
}
|
|
|
|
return BSHELL_SUCCESS;
|
|
}
|
|
|
|
static enum bshell_status statement_word(struct lex_ctx *ctx)
|
|
{
|
|
struct lex_token *word = NULL;
|
|
enum bshell_status status = read_word(ctx, &word);
|
|
if (status != BSHELL_SUCCESS) {
|
|
return status;
|
|
}
|
|
|
|
bool converted = convert_word_to_keyword(word);
|
|
if (!converted) {
|
|
converted = convert_word_to_int(word);
|
|
}
|
|
|
|
if (converted) {
|
|
lex_state_change(ctx, LEX_STATE_ARITHMETIC);
|
|
} else {
|
|
lex_state_change(ctx, LEX_STATE_COMMAND);
|
|
}
|
|
|
|
enqueue_token(ctx, word);
|
|
return BSHELL_SUCCESS;
|
|
}
|
|
|
|
static enum bshell_status statement_pump_token(struct lex_ctx *ctx)
|
|
{
|
|
fx_wchar c = peek_char(ctx);
|
|
bool newline = false;
|
|
|
|
while (fx_wchar_is_space(c)) {
|
|
if (c == '\n') {
|
|
newline = true;
|
|
}
|
|
|
|
advance_char_noread(ctx);
|
|
c = peek_char_noread(ctx);
|
|
}
|
|
|
|
if (newline) {
|
|
struct lex_token *tok = lex_token_create(TOK_LINEFEED);
|
|
enqueue_token(ctx, tok);
|
|
return BSHELL_SUCCESS;
|
|
}
|
|
|
|
if (char_can_begin_symbol(ctx, c)) {
|
|
return statement_symbol(ctx);
|
|
}
|
|
|
|
return statement_word(ctx);
|
|
}
|
|
|
|
const struct lex_state_type lex_statement_state = {
|
|
.s_id = LEX_STATE_STATEMENT,
|
|
.s_pump_token = statement_pump_token,
|
|
};
|