mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 14:03:58 +00:00
Continued adoption of tnode_t in parse_execution
Migrate boolean statements
This commit is contained in:
parent
7a3d5ddeae
commit
8a14a4a5ff
5 changed files with 25 additions and 30 deletions
|
@ -1002,11 +1002,10 @@ bool parse_execution_context_t::determine_io_chain(const parse_node_t &statement
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_execution_result_t parse_execution_context_t::populate_boolean_process(
|
parse_execution_result_t parse_execution_context_t::populate_boolean_process(
|
||||||
job_t *job, process_t *proc, const parse_node_t &bool_statement) {
|
job_t *job, process_t *proc, tnode_t<g::boolean_statement> bool_statement) {
|
||||||
// Handle a boolean statement.
|
// Handle a boolean statement.
|
||||||
bool skip_job = false;
|
bool skip_job = false;
|
||||||
assert(bool_statement.type == symbol_boolean_statement);
|
switch (bool_statement_type(bool_statement)) {
|
||||||
switch (parse_node_tree_t::statement_boolean_type(bool_statement)) {
|
|
||||||
case parse_bool_and: {
|
case parse_bool_and: {
|
||||||
// AND. Skip if the last job failed.
|
// AND. Skip if the last job failed.
|
||||||
skip_job = (proc_get_last_status() != 0);
|
skip_job = (proc_get_last_status() != 0);
|
||||||
|
@ -1027,8 +1026,8 @@ parse_execution_result_t parse_execution_context_t::populate_boolean_process(
|
||||||
if (skip_job) {
|
if (skip_job) {
|
||||||
return parse_execution_skipped;
|
return parse_execution_skipped;
|
||||||
}
|
}
|
||||||
const parse_node_t &subject = *tree().get_child(bool_statement, 1, symbol_statement);
|
return this->populate_job_process(job, proc,
|
||||||
return this->populate_job_process(job, proc, subject);
|
bool_statement.require_get_child<g::statement, 1>());
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_execution_result_t parse_execution_context_t::populate_block_process(
|
parse_execution_result_t parse_execution_context_t::populate_block_process(
|
||||||
|
@ -1051,20 +1050,16 @@ parse_execution_result_t parse_execution_context_t::populate_block_process(
|
||||||
return parse_execution_success;
|
return parse_execution_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a process_t allocated with new. It's the caller's responsibility to delete it (!).
|
|
||||||
parse_execution_result_t parse_execution_context_t::populate_job_process(
|
parse_execution_result_t parse_execution_context_t::populate_job_process(
|
||||||
job_t *job, process_t *proc, const parse_node_t &statement_node) {
|
job_t *job, process_t *proc, tnode_t<grammar::statement> statement) {
|
||||||
assert(statement_node.type == symbol_statement);
|
|
||||||
assert(statement_node.child_count == 1);
|
|
||||||
|
|
||||||
// Get the "specific statement" which is boolean / block / if / switch / decorated.
|
// Get the "specific statement" which is boolean / block / if / switch / decorated.
|
||||||
const parse_node_t &specific_statement = *get_child(statement_node, 0);
|
const parse_node_t &specific_statement = *get_child(statement, 0);
|
||||||
|
|
||||||
parse_execution_result_t result = parse_execution_success;
|
parse_execution_result_t result = parse_execution_success;
|
||||||
|
|
||||||
switch (specific_statement.type) {
|
switch (specific_statement.type) {
|
||||||
case symbol_boolean_statement: {
|
case symbol_boolean_statement: {
|
||||||
result = this->populate_boolean_process(job, proc, specific_statement);
|
result = this->populate_boolean_process(job, proc, {&tree(), &specific_statement});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case symbol_block_statement:
|
case symbol_block_statement:
|
||||||
|
@ -1100,15 +1095,15 @@ parse_execution_result_t parse_execution_context_t::populate_job_from_job_node(
|
||||||
|
|
||||||
// We are going to construct process_t structures for every statement in the job. Get the first
|
// We are going to construct process_t structures for every statement in the job. Get the first
|
||||||
// statement.
|
// statement.
|
||||||
tnode_t<g::statement> statement_node = job_node.child<0>();
|
tnode_t<g::statement> statement = job_node.child<0>();
|
||||||
assert(statement_node);
|
assert(statement);
|
||||||
|
|
||||||
parse_execution_result_t result = parse_execution_success;
|
parse_execution_result_t result = parse_execution_success;
|
||||||
|
|
||||||
// Create processes. Each one may fail.
|
// Create processes. Each one may fail.
|
||||||
process_list_t processes;
|
process_list_t processes;
|
||||||
processes.emplace_back(new process_t());
|
processes.emplace_back(new process_t());
|
||||||
result = this->populate_job_process(j, processes.back().get(), *statement_node);
|
result = this->populate_job_process(j, processes.back().get(), statement);
|
||||||
|
|
||||||
// Construct process_ts for job continuations (pipelines), by walking the list until we hit the
|
// Construct process_ts for job continuations (pipelines), by walking the list until we hit the
|
||||||
// terminal (empty) job continuation.
|
// terminal (empty) job continuation.
|
||||||
|
|
|
@ -85,9 +85,9 @@ class parse_execution_context_t {
|
||||||
|
|
||||||
// These create process_t structures from statements.
|
// These create process_t structures from statements.
|
||||||
parse_execution_result_t populate_job_process(job_t *job, process_t *proc,
|
parse_execution_result_t populate_job_process(job_t *job, process_t *proc,
|
||||||
const parse_node_t &statement_node);
|
tnode_t<grammar::statement> statement);
|
||||||
parse_execution_result_t populate_boolean_process(job_t *job, process_t *proc,
|
parse_execution_result_t populate_boolean_process(
|
||||||
const parse_node_t &bool_statement);
|
job_t *job, process_t *proc, tnode_t<grammar::boolean_statement> bool_statement);
|
||||||
parse_execution_result_t populate_plain_process(job_t *job, process_t *proc,
|
parse_execution_result_t populate_plain_process(job_t *job, process_t *proc,
|
||||||
const parse_node_t &statement);
|
const parse_node_t &statement);
|
||||||
parse_execution_result_t populate_block_process(job_t *job, process_t *proc,
|
parse_execution_result_t populate_block_process(job_t *job, process_t *proc,
|
||||||
|
|
|
@ -1327,6 +1327,10 @@ enum parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statemen
|
||||||
return decoration;
|
return decoration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_statement> stmt) {
|
||||||
|
return static_cast<parse_bool_statement_type_t>(stmt.tag());
|
||||||
|
}
|
||||||
|
|
||||||
bool parse_node_tree_t::statement_is_in_pipeline(const parse_node_t &node,
|
bool parse_node_tree_t::statement_is_in_pipeline(const parse_node_t &node,
|
||||||
bool include_first) const {
|
bool include_first) const {
|
||||||
// Moderately nasty hack! Walk up our ancestor chain and see if we are in a job_continuation.
|
// Moderately nasty hack! Walk up our ancestor chain and see if we are in a job_continuation.
|
||||||
|
@ -1429,12 +1433,6 @@ parse_node_tree_t::parse_node_list_t parse_node_tree_t::comment_nodes_for_node(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum parse_bool_statement_type_t parse_node_tree_t::statement_boolean_type(
|
|
||||||
const parse_node_t &node) {
|
|
||||||
assert(node.type == symbol_boolean_statement);
|
|
||||||
return static_cast<parse_bool_statement_type_t>(node.tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_node_tree_t::job_should_be_backgrounded(const parse_node_t &job) const {
|
bool parse_node_tree_t::job_should_be_backgrounded(const parse_node_t &job) const {
|
||||||
assert(job.type == symbol_job);
|
assert(job.type == symbol_job);
|
||||||
const parse_node_t *opt_background = get_child(job, 2, symbol_optional_background);
|
const parse_node_t *opt_background = get_child(job, 2, symbol_optional_background);
|
||||||
|
|
|
@ -222,9 +222,6 @@ class parse_node_tree_t : public std::vector<parse_node_t> {
|
||||||
/// Given a node, return all of its comment nodes.
|
/// Given a node, return all of its comment nodes.
|
||||||
parse_node_list_t comment_nodes_for_node(const parse_node_t &node) const;
|
parse_node_list_t comment_nodes_for_node(const parse_node_t &node) const;
|
||||||
|
|
||||||
/// Returns the boolean type for a boolean node.
|
|
||||||
static enum parse_bool_statement_type_t statement_boolean_type(const parse_node_t &node);
|
|
||||||
|
|
||||||
/// Given a job, return whether it should be backgrounded, because it has a & specifier.
|
/// Given a job, return whether it should be backgrounded, because it has a & specifier.
|
||||||
bool job_should_be_backgrounded(const parse_node_t &job) const;
|
bool job_should_be_backgrounded(const parse_node_t &job) const;
|
||||||
|
|
||||||
|
@ -303,6 +300,9 @@ class tnode_t {
|
||||||
// return the tag, or 0 if missing.
|
// return the tag, or 0 if missing.
|
||||||
parse_node_tag_t tag() const { return nodeptr ? nodeptr->tag : 0; }
|
parse_node_tag_t tag() const { return nodeptr ? nodeptr->tag : 0; }
|
||||||
|
|
||||||
|
// return the number of children, or 0 if missing.
|
||||||
|
uint8_t child_count() const { return nodeptr ? nodeptr->child_count : 0; }
|
||||||
|
|
||||||
maybe_t<source_range_t> source_range() const {
|
maybe_t<source_range_t> source_range() const {
|
||||||
if (!has_source()) return none();
|
if (!has_source()) return none();
|
||||||
return source_range_t{nodeptr->source_start, nodeptr->source_length};
|
return source_range_t{nodeptr->source_start, nodeptr->source_length};
|
||||||
|
@ -416,6 +416,9 @@ maybe_t<wcstring> command_for_plain_statement(tnode_t<grammar::plain_statement>
|
||||||
/// Return the decoration for a plain statement.
|
/// Return the decoration for a plain statement.
|
||||||
parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statement> stmt);
|
parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statement> stmt);
|
||||||
|
|
||||||
|
/// Return the type for a boolean statement.
|
||||||
|
enum parse_bool_statement_type_t bool_statement_type(tnode_t<grammar::boolean_statement> stmt);
|
||||||
|
|
||||||
/// The big entry point. Parse a string, attempting to produce a tree for the given goal type.
|
/// The big entry point. Parse a string, attempting to produce a tree for the given goal type.
|
||||||
bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags,
|
bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags,
|
||||||
parse_node_tree_t *output, parse_error_list_t *errors,
|
parse_node_tree_t *output, parse_error_list_t *errors,
|
||||||
|
|
|
@ -1068,8 +1068,7 @@ static bool detect_errors_in_backgrounded_job(const parse_node_tree_t &node_tree
|
||||||
tnode_t<grammar::statement> next_stmt = next_job.child<0>();
|
tnode_t<grammar::statement> next_stmt = next_job.child<0>();
|
||||||
if (auto bool_stmt = next_stmt.try_get_child<grammar::boolean_statement, 0>()) {
|
if (auto bool_stmt = next_stmt.try_get_child<grammar::boolean_statement, 0>()) {
|
||||||
// The next job is indeed a boolean statement.
|
// The next job is indeed a boolean statement.
|
||||||
parse_bool_statement_type_t bool_type =
|
parse_bool_statement_type_t bool_type = bool_statement_type(bool_stmt);
|
||||||
parse_node_tree_t::statement_boolean_type(*bool_stmt.node());
|
|
||||||
if (bool_type == parse_bool_and) { // this is not allowed
|
if (bool_type == parse_bool_and) { // this is not allowed
|
||||||
errored = append_syntax_error(parse_errors, bool_stmt.source_range()->start,
|
errored = append_syntax_error(parse_errors, bool_stmt.source_range()->start,
|
||||||
BOOL_AFTER_BACKGROUND_ERROR_MSG, L"and");
|
BOOL_AFTER_BACKGROUND_ERROR_MSG, L"and");
|
||||||
|
@ -1145,7 +1144,7 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src,
|
||||||
has_unclosed_block = true;
|
has_unclosed_block = true;
|
||||||
} else if (node.type == symbol_boolean_statement) {
|
} else if (node.type == symbol_boolean_statement) {
|
||||||
// 'or' and 'and' can be in a pipeline, as long as they're first.
|
// 'or' and 'and' can be in a pipeline, as long as they're first.
|
||||||
parse_bool_statement_type_t type = parse_node_tree_t::statement_boolean_type(node);
|
parse_bool_statement_type_t type = bool_statement_type({&node_tree, &node});
|
||||||
if ((type == parse_bool_and || type == parse_bool_or) &&
|
if ((type == parse_bool_and || type == parse_bool_or) &&
|
||||||
node_tree.statement_is_in_pipeline(node, false /* don't count first */)) {
|
node_tree.statement_is_in_pipeline(node, false /* don't count first */)) {
|
||||||
errored = append_syntax_error(&parse_errors, node.source_start, EXEC_ERR_MSG,
|
errored = append_syntax_error(&parse_errors, node.source_start, EXEC_ERR_MSG,
|
||||||
|
|
Loading…
Reference in a new issue