mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-23 09:03:37 +08:00
Clean up various block types and state as part of new parser
This commit is contained in:
parent
6b3a37c597
commit
cc12225142
75
builtin.cpp
75
builtin.cpp
|
@ -3309,78 +3309,6 @@ static int builtin_bg(parser_t &parser, wchar_t **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Builtin for looping over a list
|
|
||||||
*/
|
|
||||||
static int builtin_for(parser_t &parser, wchar_t **argv)
|
|
||||||
{
|
|
||||||
int argc = builtin_count_args(argv);
|
|
||||||
int res=STATUS_BUILTIN_ERROR;
|
|
||||||
|
|
||||||
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
|
|
||||||
if (argc == 1)
|
|
||||||
{
|
|
||||||
builtin_print_help(parser, argv[0], stdout_buffer);
|
|
||||||
return STATUS_BUILTIN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc < 3)
|
|
||||||
{
|
|
||||||
append_format(stderr_buffer,
|
|
||||||
BUILTIN_FOR_ERR_COUNT,
|
|
||||||
argv[0] ,
|
|
||||||
argc);
|
|
||||||
builtin_print_help(parser, argv[0], stderr_buffer);
|
|
||||||
}
|
|
||||||
else if (wcsvarname(argv[1]))
|
|
||||||
{
|
|
||||||
append_format(stderr_buffer,
|
|
||||||
BUILTIN_FOR_ERR_NAME,
|
|
||||||
argv[0],
|
|
||||||
argv[1]);
|
|
||||||
builtin_print_help(parser, argv[0], stderr_buffer);
|
|
||||||
}
|
|
||||||
else if (wcscmp(argv[2], L"in") != 0)
|
|
||||||
{
|
|
||||||
append_format(stderr_buffer,
|
|
||||||
BUILTIN_FOR_ERR_IN,
|
|
||||||
argv[0]);
|
|
||||||
builtin_print_help(parser, argv[0], stderr_buffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
res=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (res)
|
|
||||||
{
|
|
||||||
parser.push_block(new fake_block_t());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const wchar_t *for_variable = argv[1];
|
|
||||||
for_block_t *fb = new for_block_t(for_variable);
|
|
||||||
parser.push_block(fb);
|
|
||||||
fb->tok_pos = parser.get_pos();
|
|
||||||
|
|
||||||
/* Note that we store the sequence of values in opposite order */
|
|
||||||
wcstring_list_t &for_vars = fb->sequence;
|
|
||||||
for (int i=argc-1; i>3; i--)
|
|
||||||
for_vars.push_back(argv[i]);
|
|
||||||
|
|
||||||
if (argc > 3)
|
|
||||||
{
|
|
||||||
env_set(for_variable, argv[3], ENV_LOCAL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
parser.current_block()->skip=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function handles both the 'continue' and the 'break' builtins
|
This function handles both the 'continue' and the 'break' builtins
|
||||||
that are used for loop control.
|
that are used for loop control.
|
||||||
|
@ -3509,7 +3437,6 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
|
||||||
for (size_t i=0; i < function_block_idx; i++)
|
for (size_t i=0; i < function_block_idx; i++)
|
||||||
{
|
{
|
||||||
block_t *b = parser.block_at_index(i);
|
block_t *b = parser.block_at_index(i);
|
||||||
b->mark_as_fake();
|
|
||||||
b->skip = true;
|
b->skip = true;
|
||||||
}
|
}
|
||||||
parser.block_at_index(function_block_idx)->skip = true;
|
parser.block_at_index(function_block_idx)->skip = true;
|
||||||
|
@ -3734,7 +3661,7 @@ static const builtin_data_t builtin_datas[]=
|
||||||
{ L"exec", &builtin_generic, N_(L"Run command in current process") },
|
{ L"exec", &builtin_generic, N_(L"Run command in current process") },
|
||||||
{ L"exit", &builtin_exit, N_(L"Exit the shell") },
|
{ L"exit", &builtin_exit, N_(L"Exit the shell") },
|
||||||
{ L"fg", &builtin_fg, N_(L"Send job to foreground") },
|
{ L"fg", &builtin_fg, N_(L"Send job to foreground") },
|
||||||
{ L"for", &builtin_for, N_(L"Perform a set of commands multiple times") },
|
{ L"for", &builtin_generic, N_(L"Perform a set of commands multiple times") },
|
||||||
{ L"function", &builtin_generic, N_(L"Define a new function") },
|
{ L"function", &builtin_generic, N_(L"Define a new function") },
|
||||||
{ L"functions", &builtin_functions, N_(L"List or remove functions") },
|
{ L"functions", &builtin_functions, N_(L"List or remove functions") },
|
||||||
{ L"history", &builtin_history, N_(L"History of commands executed by user") },
|
{ L"history", &builtin_history, N_(L"History of commands executed by user") },
|
||||||
|
|
|
@ -447,7 +447,7 @@ parse_execution_result_t parse_execution_context_t::run_for_statement(const pars
|
||||||
|
|
||||||
/* Get the contents to iterate over. */
|
/* Get the contents to iterate over. */
|
||||||
const parse_node_t *unmatched_wildcard = NULL;
|
const parse_node_t *unmatched_wildcard = NULL;
|
||||||
wcstring_list_t argument_list = this->determine_arguments(header, &unmatched_wildcard);
|
wcstring_list_t argument_sequence = this->determine_arguments(header, &unmatched_wildcard);
|
||||||
if (unmatched_wildcard != NULL)
|
if (unmatched_wildcard != NULL)
|
||||||
{
|
{
|
||||||
return report_unmatched_wildcard_error(*unmatched_wildcard);
|
return report_unmatched_wildcard_error(*unmatched_wildcard);
|
||||||
|
@ -455,15 +455,12 @@ parse_execution_result_t parse_execution_context_t::run_for_statement(const pars
|
||||||
|
|
||||||
parse_execution_result_t ret = parse_execution_success;
|
parse_execution_result_t ret = parse_execution_success;
|
||||||
|
|
||||||
for_block_t *fb = new for_block_t(for_var_name);
|
for_block_t *fb = new for_block_t();
|
||||||
parser->push_block(fb);
|
parser->push_block(fb);
|
||||||
|
|
||||||
/* Note that we store the sequence of values in opposite order */
|
|
||||||
std::reverse(argument_list.begin(), argument_list.end());
|
|
||||||
fb->sequence = argument_list;
|
|
||||||
|
|
||||||
/* Now drive the for loop. */
|
/* Now drive the for loop. */
|
||||||
while (! fb->sequence.empty())
|
const size_t arg_count = argument_sequence.size();
|
||||||
|
for (size_t i=0; i < arg_count; i++)
|
||||||
{
|
{
|
||||||
if (should_cancel_execution(fb))
|
if (should_cancel_execution(fb))
|
||||||
{
|
{
|
||||||
|
@ -471,10 +468,8 @@ parse_execution_result_t parse_execution_context_t::run_for_statement(const pars
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wcstring &for_variable = fb->variable;
|
const wcstring &val = argument_sequence.at(i);
|
||||||
const wcstring &val = fb->sequence.back();
|
env_set(for_var_name, val.c_str(), ENV_LOCAL);
|
||||||
env_set(for_variable, val.c_str(), ENV_LOCAL);
|
|
||||||
fb->sequence.pop_back();
|
|
||||||
fb->loop_status = LOOP_NORMAL;
|
fb->loop_status = LOOP_NORMAL;
|
||||||
fb->skip = 0;
|
fb->skip = 0;
|
||||||
|
|
||||||
|
@ -551,7 +546,7 @@ parse_execution_result_t parse_execution_context_t::run_switch_statement(const p
|
||||||
}
|
}
|
||||||
const wcstring &switch_value_expanded = switch_values_expanded.at(0).completion;
|
const wcstring &switch_value_expanded = switch_values_expanded.at(0).completion;
|
||||||
|
|
||||||
switch_block_t *sb = new switch_block_t(switch_value_expanded);
|
switch_block_t *sb = new switch_block_t();
|
||||||
parser->push_block(sb);
|
parser->push_block(sb);
|
||||||
|
|
||||||
if (result == parse_execution_success)
|
if (result == parse_execution_success)
|
||||||
|
@ -620,7 +615,6 @@ parse_execution_result_t parse_execution_context_t::run_while_statement(const pa
|
||||||
|
|
||||||
/* Push a while block */
|
/* Push a while block */
|
||||||
while_block_t *wb = new while_block_t();
|
while_block_t *wb = new while_block_t();
|
||||||
wb->status = WHILE_TEST_FIRST;
|
|
||||||
wb->node_offset = this->get_offset(header);
|
wb->node_offset = this->get_offset(header);
|
||||||
parser->push_block(wb);
|
parser->push_block(wb);
|
||||||
|
|
||||||
|
|
41
parser.cpp
41
parser.cpp
|
@ -249,7 +249,9 @@ void parser_t::push_block(block_t *new_current)
|
||||||
|
|
||||||
const block_t *old_current = this->current_block();
|
const block_t *old_current = this->current_block();
|
||||||
if (old_current && old_current->skip)
|
if (old_current && old_current->skip)
|
||||||
new_current->mark_as_fake();
|
{
|
||||||
|
new_current->skip = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
New blocks should be skipped if the outer block is skipped,
|
New blocks should be skipped if the outer block is skipped,
|
||||||
|
@ -1407,7 +1409,6 @@ void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &erro
|
||||||
|
|
||||||
block_t::block_t(block_type_t t) :
|
block_t::block_t(block_type_t t) :
|
||||||
block_type(t),
|
block_type(t),
|
||||||
made_fake(false),
|
|
||||||
skip(),
|
skip(),
|
||||||
had_command(),
|
had_command(),
|
||||||
tok_pos(),
|
tok_pos(),
|
||||||
|
@ -1427,12 +1428,7 @@ block_t::~block_t()
|
||||||
|
|
||||||
/* Various block constructors */
|
/* Various block constructors */
|
||||||
|
|
||||||
if_block_t::if_block_t() :
|
if_block_t::if_block_t() : block_t(IF)
|
||||||
block_t(IF),
|
|
||||||
if_expr_evaluated(false),
|
|
||||||
is_elseif_entry(false),
|
|
||||||
any_branch_taken(false),
|
|
||||||
else_evaluated(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1455,45 +1451,28 @@ source_block_t::source_block_t(const wchar_t *src) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
for_block_t::for_block_t(const wcstring &var) :
|
for_block_t::for_block_t() : block_t(FOR)
|
||||||
block_t(FOR),
|
|
||||||
variable(var),
|
|
||||||
sequence()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
while_block_t::while_block_t() :
|
while_block_t::while_block_t() : block_t(WHILE)
|
||||||
block_t(WHILE),
|
|
||||||
status(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_block_t::switch_block_t(const wcstring &sv) :
|
switch_block_t::switch_block_t() : block_t(SWITCH)
|
||||||
block_t(SWITCH),
|
|
||||||
switch_taken(false),
|
|
||||||
switch_value(sv)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
fake_block_t::fake_block_t() :
|
fake_block_t::fake_block_t() : block_t(FAKE)
|
||||||
block_t(FAKE)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
function_def_block_t::function_def_block_t() :
|
scope_block_t::scope_block_t(block_type_t type) : block_t(type)
|
||||||
block_t(FUNCTION_DEF),
|
|
||||||
function_data()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
scope_block_t::scope_block_t(block_type_t type) :
|
|
||||||
block_t(type)
|
|
||||||
{
|
{
|
||||||
assert(type == BEGIN || type == TOP || type == SUBST);
|
assert(type == BEGIN || type == TOP || type == SUBST);
|
||||||
}
|
}
|
||||||
|
|
||||||
breakpoint_block_t::breakpoint_block_t() :
|
breakpoint_block_t::breakpoint_block_t() : block_t(BREAKPOINT)
|
||||||
block_t(BREAKPOINT)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
parser.h
44
parser.h
|
@ -64,8 +64,7 @@ enum block_type_t
|
||||||
SOURCE, /**< Block created by the . (source) builtin */
|
SOURCE, /**< Block created by the . (source) builtin */
|
||||||
EVENT, /**< Block created on event notifier invocation */
|
EVENT, /**< Block created on event notifier invocation */
|
||||||
BREAKPOINT, /**< Breakpoint block */
|
BREAKPOINT, /**< Breakpoint block */
|
||||||
}
|
};
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
block_t represents a block of commands.
|
block_t represents a block of commands.
|
||||||
|
@ -78,18 +77,11 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const block_type_t block_type; /**< Type of block. */
|
const block_type_t block_type; /**< Type of block. */
|
||||||
bool made_fake;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
block_type_t type() const
|
block_type_t type() const
|
||||||
{
|
{
|
||||||
return this->made_fake ? FAKE : this->block_type;
|
return this->block_type;
|
||||||
}
|
|
||||||
|
|
||||||
/** Mark a block as fake; this is used by the return statement. */
|
|
||||||
void mark_as_fake()
|
|
||||||
{
|
|
||||||
this->made_fake = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool skip; /**< Whether execution of the commands in this block should be skipped */
|
bool skip; /**< Whether execution of the commands in this block should be skipped */
|
||||||
|
@ -122,11 +114,6 @@ public:
|
||||||
|
|
||||||
struct if_block_t : public block_t
|
struct if_block_t : public block_t
|
||||||
{
|
{
|
||||||
bool if_expr_evaluated; // whether we've evaluated the if expression
|
|
||||||
bool is_elseif_entry; // whether we're at the beginning of an ELSEIF branch
|
|
||||||
bool any_branch_taken; // whether the clause of the if statement or any elseif has been found to be true
|
|
||||||
bool else_evaluated; // whether we've encountered a terminal else block
|
|
||||||
|
|
||||||
if_block_t();
|
if_block_t();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -151,22 +138,17 @@ struct source_block_t : public block_t
|
||||||
|
|
||||||
struct for_block_t : public block_t
|
struct for_block_t : public block_t
|
||||||
{
|
{
|
||||||
wcstring variable; // the variable that will be assigned each value in the sequence
|
for_block_t();
|
||||||
wcstring_list_t sequence; // the sequence of values
|
|
||||||
for_block_t(const wcstring &var);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct while_block_t : public block_t
|
struct while_block_t : public block_t
|
||||||
{
|
{
|
||||||
int status;
|
|
||||||
while_block_t();
|
while_block_t();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct switch_block_t : public block_t
|
struct switch_block_t : public block_t
|
||||||
{
|
{
|
||||||
bool switch_taken;
|
switch_block_t();
|
||||||
const wcstring switch_value;
|
|
||||||
switch_block_t(const wcstring &sv);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fake_block_t : public block_t
|
struct fake_block_t : public block_t
|
||||||
|
@ -174,12 +156,6 @@ struct fake_block_t : public block_t
|
||||||
fake_block_t();
|
fake_block_t();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct function_def_block_t : public block_t
|
|
||||||
{
|
|
||||||
function_data_t function_data;
|
|
||||||
function_def_block_t();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct scope_block_t : public block_t
|
struct scope_block_t : public block_t
|
||||||
{
|
{
|
||||||
scope_block_t(block_type_t type); //must be BEGIN, TOP or SUBST
|
scope_block_t(block_type_t type); //must be BEGIN, TOP or SUBST
|
||||||
|
@ -201,18 +177,6 @@ enum loop_status
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Possible states for a while block
|
|
||||||
*/
|
|
||||||
enum while_status
|
|
||||||
{
|
|
||||||
WHILE_TEST_FIRST, /**< This is the first command of the first lap of a while loop */
|
|
||||||
WHILE_TEST_AGAIN, /**< This is not the first lap of the while loop, but it is the first command of the loop */
|
|
||||||
WHILE_TESTED, /**< This is not the first command in the loop */
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Errors that can be generated by the parser
|
Errors that can be generated by the parser
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue
Block a user