mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-11 23:47:25 +00:00
Rewrite parser_t::eval_args to use new AST parser
This commit is contained in:
parent
1305c02579
commit
1c58b6d83e
4 changed files with 43 additions and 69 deletions
|
@ -1249,7 +1249,7 @@ void completer_t::complete_from_args(const wcstring &str,
|
|||
if (! is_autosuggest)
|
||||
proc_push_interactive(0);
|
||||
|
||||
parser.eval_args(args.c_str(), possible_comp);
|
||||
parser.eval_args(args, possible_comp);
|
||||
|
||||
if (! is_autosuggest)
|
||||
proc_pop_interactive();
|
||||
|
|
|
@ -620,6 +620,15 @@ static void test_parser()
|
|||
/* This is disabled since it produces a long backtrace. We should find a way to either visually compress the backtrace, or disable error spewing */
|
||||
parser_t::principal_parser().eval(L"function recursive1 ; recursive2 ; end ; function recursive2 ; recursive1 ; end ; recursive1; ", io_chain_t(), TOP);
|
||||
#endif
|
||||
|
||||
say(L"Testing eval_args");
|
||||
completion_list_t comps;
|
||||
parser_t::principal_parser().eval_args(L"alpha 'beta gamma' delta", comps);
|
||||
do_test(comps.size() == 3);
|
||||
do_test(comps.at(0).completion == L"alpha");
|
||||
do_test(comps.at(1).completion == L"beta gamma");
|
||||
do_test(comps.at(2).completion == L"delta");
|
||||
|
||||
}
|
||||
|
||||
/* Wait a while and then SIGINT the main thread */
|
||||
|
|
90
parser.cpp
90
parser.cpp
|
@ -546,7 +546,8 @@ void parser_t::print_errors_stderr()
|
|||
}
|
||||
}
|
||||
|
||||
void parser_t::eval_args(const wchar_t *line, std::vector<completion_t> &args)
|
||||
|
||||
void parser_t::eval_args(const wcstring &arg_list_src, std::vector<completion_t> &output_arg_list)
|
||||
{
|
||||
expand_flags_t eflags = 0;
|
||||
if (! show_errors)
|
||||
|
@ -554,77 +555,44 @@ void parser_t::eval_args(const wchar_t *line, std::vector<completion_t> &args)
|
|||
if (this->parser_type != PARSER_TYPE_GENERAL)
|
||||
eflags |= EXPAND_SKIP_CMDSUBST;
|
||||
|
||||
bool do_loop=1;
|
||||
|
||||
if (! line) return;
|
||||
|
||||
// PCA we need to suppress calling proc_push_interactive off of the main thread.
|
||||
/* Suppress calling proc_push_interactive off of the main thread. */
|
||||
if (this->parser_type == PARSER_TYPE_GENERAL)
|
||||
proc_push_interactive(0);
|
||||
|
||||
tokenizer_t tok(line, (show_errors ? 0 : TOK_SQUASH_ERRORS));
|
||||
|
||||
/*
|
||||
eval_args may be called while evaulating another command, so we
|
||||
save the previous tokenizer and restore it on exit
|
||||
*/
|
||||
scoped_push<tokenizer_t*> tokenizer_push(¤t_tokenizer, &tok);
|
||||
scoped_push<int> tokenizer_pos_push(¤t_tokenizer_pos, 0);
|
||||
|
||||
error_code=0;
|
||||
|
||||
for (; do_loop && tok_has_next(&tok) ; tok_next(&tok))
|
||||
{
|
||||
current_tokenizer_pos = tok_get_pos(&tok);
|
||||
switch (tok_last_type(&tok))
|
||||
proc_push_interactive(0);
|
||||
}
|
||||
|
||||
/* Parse the string as an argument list */
|
||||
parse_node_tree_t tree;
|
||||
if (! parse_tree_from_string(arg_list_src, parse_flag_none, &tree, NULL /* errors */, symbol_argument_list))
|
||||
{
|
||||
/* Failed to parse. Here we expect to have reported any errors in test_args */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the root argument list */
|
||||
assert(! tree.empty());
|
||||
const parse_node_t *arg_list = &tree.at(0);
|
||||
assert(arg_list->type == symbol_argument_list);
|
||||
|
||||
/* Extract arguments from it */
|
||||
while (arg_list != NULL)
|
||||
{
|
||||
const parse_node_t *arg_node = tree.next_node_in_node_list(*arg_list, symbol_argument, &arg_list);
|
||||
if (arg_node != NULL)
|
||||
{
|
||||
case TOK_STRING:
|
||||
const wcstring arg_src = arg_node->get_source(arg_list_src);
|
||||
if (expand_string(arg_src, output_arg_list, eflags) == EXPAND_ERROR)
|
||||
{
|
||||
const wcstring tmp = tok_last(&tok);
|
||||
if (expand_string(tmp, args, eflags) == EXPAND_ERROR)
|
||||
{
|
||||
err_pos=tok_get_pos(&tok);
|
||||
do_loop=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_END:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_ERROR:
|
||||
{
|
||||
if (show_errors)
|
||||
error(SYNTAX_ERROR,
|
||||
tok_get_pos(&tok),
|
||||
TOK_ERR_MSG,
|
||||
tok_last(&tok));
|
||||
|
||||
do_loop=0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (show_errors)
|
||||
error(SYNTAX_ERROR,
|
||||
tok_get_pos(&tok),
|
||||
UNEXPECTED_TOKEN_ERR_MSG,
|
||||
tok_get_desc(tok_last_type(&tok)));
|
||||
|
||||
do_loop=0;
|
||||
/* Failed to expand a string */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (show_errors)
|
||||
this->print_errors_stderr();
|
||||
|
||||
if (this->parser_type == PARSER_TYPE_GENERAL)
|
||||
{
|
||||
proc_pop_interactive();
|
||||
}
|
||||
}
|
||||
|
||||
void parser_t::stack_trace(size_t block_idx, wcstring &buff) const
|
||||
|
|
11
parser.h
11
parser.h
|
@ -340,15 +340,12 @@ public:
|
|||
/**
|
||||
Evaluate line as a list of parameters, i.e. tokenize it and perform parameter expansion and cmdsubst execution on the tokens.
|
||||
The output is inserted into output.
|
||||
Errors are ignored.
|
||||
|
||||
\param line Line to evaluate
|
||||
\param output List to insert output to
|
||||
\param arg_src String to evaluate as an argument list
|
||||
\param output List to insert output into
|
||||
*/
|
||||
/**
|
||||
\param line Line to evaluate
|
||||
\param output List to insert output to
|
||||
*/
|
||||
void eval_args(const wchar_t *line, std::vector<completion_t> &output);
|
||||
void eval_args(const wcstring &arg_src, std::vector<completion_t> &output);
|
||||
|
||||
/**
|
||||
Sets the current evaluation error. This function should only be used by libraries that are called by
|
||||
|
|
Loading…
Reference in a new issue