mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-03-27 14:45:13 +08:00
parent
97969a9363
commit
f36705bb66
@ -178,6 +178,7 @@ enum parse_error_code_t {
|
|||||||
parse_error_unbalancing_else, // else outside of if
|
parse_error_unbalancing_else, // else outside of if
|
||||||
parse_error_unbalancing_case, // case outside of switch
|
parse_error_unbalancing_case, // case outside of switch
|
||||||
parse_error_bare_variable_assignment, // a=b without command
|
parse_error_bare_variable_assignment, // a=b without command
|
||||||
|
parse_error_andor_in_pipeline, // "and" or "or" after a pipe
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { PARSER_TEST_ERROR = 1, PARSER_TEST_INCOMPLETE = 2 };
|
enum { PARSER_TEST_ERROR = 1, PARSER_TEST_INCOMPLETE = 2 };
|
||||||
|
@ -53,14 +53,23 @@ wcstring parse_error_t::describe_with_prefix(const wcstring &src, const wcstring
|
|||||||
if (skip_caret && this->text.empty()) return L"";
|
if (skip_caret && this->text.empty()) return L"";
|
||||||
|
|
||||||
wcstring result = prefix;
|
wcstring result = prefix;
|
||||||
if (code == parse_error_bare_variable_assignment) {
|
switch (code) {
|
||||||
wcstring assignment_src = src.substr(this->source_start, this->source_length);
|
default:
|
||||||
maybe_t<size_t> equals_pos = variable_assignment_equals_pos(assignment_src);
|
break;
|
||||||
assert(equals_pos);
|
case parse_error_andor_in_pipeline:
|
||||||
wcstring variable = assignment_src.substr(0, *equals_pos);
|
append_format(result, EXEC_ERR_MSG,
|
||||||
wcstring value = assignment_src.substr(*equals_pos + 1);
|
src.substr(this->source_start, this->source_length).c_str());
|
||||||
append_format(result, ERROR_BAD_COMMAND_ASSIGN_ERR_MSG, variable.c_str(), value.c_str());
|
return result;
|
||||||
return result;
|
case parse_error_bare_variable_assignment: {
|
||||||
|
wcstring assignment_src = src.substr(this->source_start, this->source_length);
|
||||||
|
maybe_t<size_t> equals_pos = variable_assignment_equals_pos(assignment_src);
|
||||||
|
assert(equals_pos);
|
||||||
|
wcstring variable = assignment_src.substr(0, *equals_pos);
|
||||||
|
wcstring value = assignment_src.substr(*equals_pos + 1);
|
||||||
|
append_format(result, ERROR_BAD_COMMAND_ASSIGN_ERR_MSG, variable.c_str(),
|
||||||
|
value.c_str());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result.append(this->text);
|
result.append(this->text);
|
||||||
if (skip_caret || source_start >= src.size() || source_start + source_length > src.size()) {
|
if (skip_caret || source_start >= src.size() || source_start + source_length > src.size()) {
|
||||||
@ -929,6 +938,17 @@ void parse_ll_t::accept_tokens(parse_token_t token1, parse_token_t token2) {
|
|||||||
if (production == nullptr) {
|
if (production == nullptr) {
|
||||||
tnode_t<grammar::variable_assignments> variable_assignments;
|
tnode_t<grammar::variable_assignments> variable_assignments;
|
||||||
if (const parse_node_t *parent = nodes.get_parent(node)) {
|
if (const parse_node_t *parent = nodes.get_parent(node)) {
|
||||||
|
if (parent->type == symbol_statement &&
|
||||||
|
(token1.keyword == parse_keyword_and || token1.keyword == parse_keyword_or)) {
|
||||||
|
if (const parse_node_t *grandparent = nodes.get_parent(*parent)) {
|
||||||
|
if (grandparent->type == symbol_job_continuation) {
|
||||||
|
parse_error(token1, parse_error_andor_in_pipeline, L" "
|
||||||
|
/* won't be printed but must be non-empty, see
|
||||||
|
describe_with_prefix TODO clean that up */);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
switch (parent->type) {
|
switch (parent->type) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -238,4 +238,7 @@ parsed_source_ref_t parse_source(wcstring src, parse_tree_flags_t flags, parse_e
|
|||||||
/// The position of the equal sign in a variable assignment like foo=bar.
|
/// The position of the equal sign in a variable assignment like foo=bar.
|
||||||
maybe_t<size_t> variable_assignment_equals_pos(const wcstring &txt);
|
maybe_t<size_t> variable_assignment_equals_pos(const wcstring &txt);
|
||||||
|
|
||||||
|
/// Error message for improper use of the exec builtin.
|
||||||
|
#define EXEC_ERR_MSG _(L"The '%ls' command can not be used in a pipeline")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,9 +28,6 @@
|
|||||||
#include "wildcard.h"
|
#include "wildcard.h"
|
||||||
#include "wutil.h" // IWYU pragma: keep
|
#include "wutil.h" // IWYU pragma: keep
|
||||||
|
|
||||||
/// Error message for improper use of the exec builtin.
|
|
||||||
#define EXEC_ERR_MSG _(L"The '%ls' command can not be used in a pipeline")
|
|
||||||
|
|
||||||
/// Error message for use of backgrounded commands before and/or.
|
/// Error message for use of backgrounded commands before and/or.
|
||||||
#define BOOL_AFTER_BACKGROUND_ERROR_MSG \
|
#define BOOL_AFTER_BACKGROUND_ERROR_MSG \
|
||||||
_(L"The '%ls' command can not be used immediately after a backgrounded job")
|
_(L"The '%ls' command can not be used immediately after a backgrounded job")
|
||||||
|
9
tests/checks/andor.fish
Normal file
9
tests/checks/andor.fish
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#RUN: %fish %s
|
||||||
|
|
||||||
|
set -xl LANG C # uniform quotes
|
||||||
|
|
||||||
|
eval 'true | and'
|
||||||
|
# CHECKERR: {{.*}}: The 'and' command can not be used in a pipeline
|
||||||
|
|
||||||
|
eval 'true | or'
|
||||||
|
# CHECKERR: {{.*}}: The 'or' command can not be used in a pipeline
|
Loading…
x
Reference in New Issue
Block a user