mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
Changed "elseif" to "else if"
This commit is contained in:
parent
ff124465fd
commit
1a59346b51
9 changed files with 117 additions and 58 deletions
|
@ -3792,7 +3792,6 @@ static const builtin_data_t builtin_datas[]=
|
||||||
{ L"count", &builtin_count, N_( L"Count the number of arguments" ) },
|
{ L"count", &builtin_count, N_( L"Count the number of arguments" ) },
|
||||||
{ L"echo", &builtin_echo, N_( L"Print arguments" ) },
|
{ L"echo", &builtin_echo, N_( L"Print arguments" ) },
|
||||||
{ L"else", &builtin_else, N_( L"Evaluate block if condition is false" ) },
|
{ L"else", &builtin_else, N_( L"Evaluate block if condition is false" ) },
|
||||||
{ L"elseif", &builtin_generic, N_( L"Evaluate block if this condition is true but all previous were false" ) },
|
|
||||||
{ L"emit", &builtin_emit, N_( L"Emit an event" ) },
|
{ L"emit", &builtin_emit, N_( L"Emit an event" ) },
|
||||||
{ L"end", &builtin_end, N_( L"End a block of commands" ) },
|
{ L"end", &builtin_end, N_( L"End a block of commands" ) },
|
||||||
{ L"exec", &builtin_generic, N_( L"Run command in current process" ) },
|
{ L"exec", &builtin_generic, N_( L"Run command in current process" ) },
|
||||||
|
|
|
@ -73,6 +73,10 @@ enum
|
||||||
|
|
||||||
#define BUILTIN_FOR_ERR_NAME _( L"%ls: '%ls' is not a valid variable name\n" )
|
#define BUILTIN_FOR_ERR_NAME _( L"%ls: '%ls' is not a valid variable name\n" )
|
||||||
|
|
||||||
|
/** Error messages for 'else if' */
|
||||||
|
#define BUILTIN_ELSEIF_ERR_COUNT _( L"%ls: can only take 'if' and then another command as an argument\n")
|
||||||
|
#define BUILTIN_ELSEIF_ERR_ARGUMENT _( L"%ls: any second argument must be 'if'\n")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Error message when too many arguments are supplied to a builtin
|
Error message when too many arguments are supplied to a builtin
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
\section if if - conditionally execute a command
|
\section if if - conditionally execute a command
|
||||||
|
|
||||||
\subsection if-synopsis Synopsis
|
\subsection if-synopsis Synopsis
|
||||||
<tt>if CONDITION; COMMANDS_TRUE...; [elseif CONDITION2; COMMANDS_TRUE2...;] [else; COMMANDS_FALSE...;] end</tt>
|
<tt>if CONDITION; COMMANDS_TRUE...; [else if CONDITION2; COMMANDS_TRUE2...;] [else; COMMANDS_FALSE...;] end</tt>
|
||||||
|
|
||||||
\subsection if-description Description
|
\subsection if-description Description
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ variable.
|
||||||
<pre>
|
<pre>
|
||||||
if test -f foo.txt
|
if test -f foo.txt
|
||||||
echo foo.txt exists
|
echo foo.txt exists
|
||||||
elseif test -f bar.txt
|
else if test -f bar.txt
|
||||||
echo bar.txt exists
|
echo bar.txt exists
|
||||||
else
|
else
|
||||||
echo foo.txt and bar.txt do not exist
|
echo foo.txt and bar.txt do not exist
|
||||||
|
|
|
@ -434,9 +434,13 @@ static void test_parser()
|
||||||
{
|
{
|
||||||
err( L"'else' command outside of conditional block context undetected" );
|
err( L"'else' command outside of conditional block context undetected" );
|
||||||
}
|
}
|
||||||
if( !parser.test( L"elseif", 0, 0, 0 ) )
|
if( !parser.test( L"else if", 0, 0, 0 ) )
|
||||||
{
|
{
|
||||||
err( L"'elseif' command outside of conditional block context undetected" );
|
err( L"'else if' command outside of conditional block context undetected" );
|
||||||
|
}
|
||||||
|
if( !parser.test( L"if false; else if; end", 0, 0, 0 ) )
|
||||||
|
{
|
||||||
|
err( L"'else if' missing command undetected" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !parser.test( L"break", 0, 0, 0 ) )
|
if( !parser.test( L"break", 0, 0, 0 ) )
|
||||||
|
|
133
parser.cpp
133
parser.cpp
|
@ -146,7 +146,12 @@ The fish parser. Contains functions for parsing and evaluating code.
|
||||||
/**
|
/**
|
||||||
Error when using else builtin outside of if block
|
Error when using else builtin outside of if block
|
||||||
*/
|
*/
|
||||||
#define INVALID_ELSE_OR_ELSEIF_ERR_MSG _( L"'%ls' builtin not inside of if block" )
|
#define INVALID_ELSE_ERR_MSG _( L"'%ls' builtin not inside of if block" )
|
||||||
|
|
||||||
|
/**
|
||||||
|
Error when using 'else if' past a naked 'else'
|
||||||
|
*/
|
||||||
|
#define INVALID_ELSEIF_PAST_ELSE_ERR_MSG _( L"'%ls' used past terminating 'else'" )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Error when using end builtin outside of block
|
Error when using end builtin outside of block
|
||||||
|
@ -1408,11 +1413,6 @@ void parser_t::parse_job_argument_list( process_t *p,
|
||||||
{
|
{
|
||||||
skip=0;
|
skip=0;
|
||||||
}
|
}
|
||||||
else if (type == IF && args.at(0).completion == L"elseif")
|
|
||||||
{
|
|
||||||
//skip = 0;
|
|
||||||
printf("SKIP elseif???\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !skip )
|
if( !skip )
|
||||||
|
@ -1898,19 +1898,37 @@ int parser_t::parse_job( process_t *p,
|
||||||
is_new_block=1;
|
is_new_block=1;
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
else if( nxt == L"elseif" )
|
else if (nxt == L"else")
|
||||||
{
|
{
|
||||||
/* Piggyback on the if block, but we need the elseif command */
|
/* Record where the else is for error reporting */
|
||||||
job_set_flag( j, JOB_ELSEIF, 1 );
|
const int else_pos = tok_get_pos(tok);
|
||||||
tok_next( tok );
|
/* See if we have any more arguments, that is, whether we're ELSE IF ... or just ELSE. */
|
||||||
consumed = true;
|
tok_next(tok);
|
||||||
|
if (tok_last_type(tok) == TOK_STRING && current_block->type() == IF)
|
||||||
/* Determine if we need to unskip */
|
|
||||||
if (current_block->type() == IF)
|
|
||||||
{
|
{
|
||||||
const if_block_t *ib = static_cast<const if_block_t *>(current_block);
|
const if_block_t *ib = static_cast<const if_block_t *>(current_block);
|
||||||
/* We want to execute this ELSEIF if the IF expression was evaluated, it failed, and so has every other ELSEIF (if any) */
|
|
||||||
unskip = (ib->if_expr_evaluated && ! ib->any_branch_taken);
|
/* If we've already encountered an else, complain */
|
||||||
|
if (ib->else_evaluated)
|
||||||
|
{
|
||||||
|
error( SYNTAX_ERROR,
|
||||||
|
else_pos,
|
||||||
|
INVALID_ELSEIF_PAST_ELSE_ERR_MSG,
|
||||||
|
L"else if");
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
job_set_flag( j, JOB_ELSEIF, 1 );
|
||||||
|
consumed = true;
|
||||||
|
|
||||||
|
/* We're at the IF. Go past it. */
|
||||||
|
tok_next(tok);
|
||||||
|
|
||||||
|
/* We want to execute this ELSEIF if the IF expression was evaluated, it failed, and so has every other ELSEIF (if any) */
|
||||||
|
unskip = (ib->if_expr_evaluated && ! ib->any_branch_taken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2489,7 +2507,9 @@ void parser_t::eval_job( tokenizer *tok )
|
||||||
/* Execute the IF */
|
/* Execute the IF */
|
||||||
bool if_result = (proc_get_last_status() == 0);
|
bool if_result = (proc_get_last_status() == 0);
|
||||||
ib->any_branch_taken = if_result;
|
ib->any_branch_taken = if_result;
|
||||||
current_block->skip = ! if_result; //don't execute if the expression failed
|
|
||||||
|
/* Don't execute if the expression failed */
|
||||||
|
current_block->skip = ! if_result;
|
||||||
ib->if_expr_evaluated = true;
|
ib->if_expr_evaluated = true;
|
||||||
}
|
}
|
||||||
else if (ib->is_elseif_entry && ! ib->any_branch_taken)
|
else if (ib->is_elseif_entry && ! ib->any_branch_taken)
|
||||||
|
@ -2962,7 +2982,7 @@ int parser_t::test( const wchar_t * buff,
|
||||||
/*
|
/*
|
||||||
Set to one if an additional process specification is needed
|
Set to one if an additional process specification is needed
|
||||||
*/
|
*/
|
||||||
int needs_cmd=0;
|
bool needs_cmd = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Counter on the number of arguments this function has encountered
|
Counter on the number of arguments this function has encountered
|
||||||
|
@ -3050,7 +3070,7 @@ int parser_t::test( const wchar_t * buff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
needs_cmd=0;
|
needs_cmd = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3066,9 +3086,9 @@ int parser_t::test( const wchar_t * buff,
|
||||||
/*
|
/*
|
||||||
Store the block level. This needs to be done
|
Store the block level. This needs to be done
|
||||||
_after_ checking for end commands, but _before_
|
_after_ checking for end commands, but _before_
|
||||||
shecking for block opening commands.
|
checking for block opening commands.
|
||||||
*/
|
*/
|
||||||
bool is_else_or_elseif = (command == L"else" || command == L"elseif");
|
bool is_else_or_elseif = (command == L"else");
|
||||||
if( block_level )
|
if( block_level )
|
||||||
{
|
{
|
||||||
block_level[tok_get_pos( &tok )] = count + (is_else_or_elseif?-1:0);
|
block_level[tok_get_pos( &tok )] = count + (is_else_or_elseif?-1:0);
|
||||||
|
@ -3107,7 +3127,7 @@ int parser_t::test( const wchar_t * buff,
|
||||||
*/
|
*/
|
||||||
if( parser_keywords_is_subcommand( command ) && !parser_keywords_skip_arguments(command ) )
|
if( parser_keywords_is_subcommand( command ) && !parser_keywords_skip_arguments(command ) )
|
||||||
{
|
{
|
||||||
needs_cmd = 1;
|
needs_cmd = true;
|
||||||
had_cmd = 0;
|
had_cmd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3231,8 +3251,6 @@ int parser_t::test( const wchar_t * buff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3289,13 +3307,12 @@ int parser_t::test( const wchar_t * buff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test that else and elseif are only used directly in an if-block
|
Test that else and else-if are only used directly in an if-block
|
||||||
*/
|
*/
|
||||||
if( command == L"else" || command == L"elseif" )
|
if( command == L"else")
|
||||||
{
|
{
|
||||||
if( !count || block_type[count-1]!=IF )
|
if( !count || block_type[count-1]!=IF )
|
||||||
{
|
{
|
||||||
|
@ -3304,16 +3321,12 @@ int parser_t::test( const wchar_t * buff,
|
||||||
{
|
{
|
||||||
error( SYNTAX_ERROR,
|
error( SYNTAX_ERROR,
|
||||||
tok_get_pos( &tok ),
|
tok_get_pos( &tok ),
|
||||||
INVALID_ELSE_OR_ELSEIF_ERR_MSG,
|
INVALID_ELSE_ERR_MSG,
|
||||||
command.c_str());
|
command.c_str());
|
||||||
|
|
||||||
print_errors( *out, prefix );
|
print_errors( *out, prefix );
|
||||||
|
|
||||||
/* Don't complain about elseif missing a command for elseif if we already complained about elseif being out of place */
|
|
||||||
if (needs_cmd) had_cmd = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3336,12 +3349,10 @@ int parser_t::test( const wchar_t * buff,
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err |= parser_test_argument( tok_last( &tok ), out, prefix, tok_get_pos( &tok ) );
|
err |= parser_test_argument( tok_last( &tok ), out, prefix, tok_get_pos( &tok ) );
|
||||||
|
|
||||||
/*
|
/* If possible, keep track of number of supplied arguments */
|
||||||
If possible, keep track of number of supplied arguments
|
|
||||||
*/
|
|
||||||
if( arg_count >= 0 && expand_is_clean( tok_last( &tok ) ) )
|
if( arg_count >= 0 && expand_is_clean( tok_last( &tok ) ) )
|
||||||
{
|
{
|
||||||
arg_count++;
|
arg_count++;
|
||||||
|
@ -3398,6 +3409,32 @@ int parser_t::test( const wchar_t * buff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (command == L"else")
|
||||||
|
{
|
||||||
|
if (arg_count == 1)
|
||||||
|
{
|
||||||
|
/* Any second argument must be "if" */
|
||||||
|
if (wcscmp(tok_last(&tok), L"if") != 0)
|
||||||
|
{
|
||||||
|
err = 1;
|
||||||
|
|
||||||
|
if( out )
|
||||||
|
{
|
||||||
|
error( SYNTAX_ERROR,
|
||||||
|
tok_get_pos( &tok ),
|
||||||
|
BUILTIN_ELSEIF_ERR_ARGUMENT,
|
||||||
|
L"else" );
|
||||||
|
print_errors( *out, prefix );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Successfully detected "else if". Now we need a new command. */
|
||||||
|
needs_cmd = true;
|
||||||
|
had_cmd = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3439,7 +3476,7 @@ int parser_t::test( const wchar_t * buff,
|
||||||
print_errors( *out, prefix );
|
print_errors( *out, prefix );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
needs_cmd=0;
|
needs_cmd = false;
|
||||||
had_cmd = 0;
|
had_cmd = 0;
|
||||||
is_pipeline=0;
|
is_pipeline=0;
|
||||||
forbid_pipeline=0;
|
forbid_pipeline=0;
|
||||||
|
@ -3488,7 +3525,7 @@ int parser_t::test( const wchar_t * buff,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
needs_cmd=1;
|
needs_cmd = true;
|
||||||
is_pipeline=1;
|
is_pipeline=1;
|
||||||
had_cmd=0;
|
had_cmd=0;
|
||||||
end_of_cmd = 1;
|
end_of_cmd = 1;
|
||||||
|
@ -3576,8 +3613,26 @@ int parser_t::test( const wchar_t * buff,
|
||||||
print_errors( *out, prefix );
|
print_errors( *out, prefix );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if (has_command && command == L"else")
|
||||||
|
{
|
||||||
|
if (arg_count == 1)
|
||||||
|
{
|
||||||
|
/* If we have any arguments, we must have at least two...either "else" or "else if foo..." */
|
||||||
|
err = true;
|
||||||
|
if (out)
|
||||||
|
{
|
||||||
|
error( SYNTAX_ERROR,
|
||||||
|
tok_get_pos( &tok ),
|
||||||
|
BUILTIN_ELSEIF_ERR_COUNT,
|
||||||
|
L"else",
|
||||||
|
arg_count );
|
||||||
|
|
||||||
|
print_errors( *out, prefix );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
parser.h
2
parser.h
|
@ -141,7 +141,7 @@ struct block_t
|
||||||
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 if_expr_evaluated; // whether we've evaluated the if expression
|
||||||
bool is_elseif_entry; // whether we're at the beginning of an active branch (IF or ELSEIF)
|
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 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
|
bool else_evaluated; // whether we've encountered a terminal else block
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@ bool parser_keywords_is_subcommand( const wcstring &cmd )
|
||||||
L"while",
|
L"while",
|
||||||
L"exec",
|
L"exec",
|
||||||
L"if",
|
L"if",
|
||||||
L"elseif",
|
|
||||||
L"and",
|
L"and",
|
||||||
L"or",
|
L"or",
|
||||||
L"not" );
|
L"not" );
|
||||||
|
@ -69,7 +68,6 @@ bool parser_keywords_is_reserved( const wcstring &word)
|
||||||
L"end",
|
L"end",
|
||||||
L"case",
|
L"case",
|
||||||
L"else",
|
L"else",
|
||||||
L"elseif",
|
|
||||||
L"return",
|
L"return",
|
||||||
L"continue",
|
L"continue",
|
||||||
L"break" );
|
L"break" );
|
||||||
|
|
|
@ -26,7 +26,7 @@ bool parser_keywords_is_switch( const wcstring &cmd );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Tests if the specified commands parameters should be interpreted as another command, which will be true if the command is either 'command', 'exec', 'if', 'while', 'elseif', or 'builtin'.
|
Tests if the specified commands parameters should be interpreted as another command, which will be true if the command is either 'command', 'exec', 'if', 'while', or 'builtin'. This does not handle "else if" which is more complicated.
|
||||||
|
|
||||||
\param cmd The command name to test
|
\param cmd The command name to test
|
||||||
\return 1 of the command parameter is a command, 0 otherwise
|
\return 1 of the command parameter is a command, 0 otherwise
|
||||||
|
|
|
@ -37,15 +37,14 @@ contains -i -- string a b c string d
|
||||||
contains -i -- -- a b c; or echo nothing
|
contains -i -- -- a b c; or echo nothing
|
||||||
contains -i -- -- a b c -- v
|
contains -i -- -- a b c -- v
|
||||||
|
|
||||||
# Test if, else, and elseif
|
# Test if, else, and else if
|
||||||
# Test if, else, and elseif
|
|
||||||
if true
|
if true
|
||||||
echo alpha1.1
|
echo alpha1.1
|
||||||
echo alpha1.2
|
echo alpha1.2
|
||||||
elseif false
|
else if false
|
||||||
echo beta1.1
|
echo beta1.1
|
||||||
echo beta1.2
|
echo beta1.2
|
||||||
elseif false
|
else if false
|
||||||
echo gamma1.1
|
echo gamma1.1
|
||||||
echo gamma1.2
|
echo gamma1.2
|
||||||
else
|
else
|
||||||
|
@ -56,10 +55,10 @@ end
|
||||||
if false
|
if false
|
||||||
echo alpha2.1
|
echo alpha2.1
|
||||||
echo alpha2.2
|
echo alpha2.2
|
||||||
elseif begin ; true ; end
|
else if begin ; true ; end
|
||||||
echo beta2.1
|
echo beta2.1
|
||||||
echo beta2.2
|
echo beta2.2
|
||||||
elseif begin ; echo nope2.1; false ; end
|
else if begin ; echo nope2.1; false ; end
|
||||||
echo gamma2.1
|
echo gamma2.1
|
||||||
echo gamma2.2
|
echo gamma2.2
|
||||||
else
|
else
|
||||||
|
@ -70,10 +69,10 @@ end
|
||||||
if false
|
if false
|
||||||
echo alpha3.1
|
echo alpha3.1
|
||||||
echo alpha3.2
|
echo alpha3.2
|
||||||
elseif begin ; echo yep3.1; false ; end
|
else if begin ; echo yep3.1; false ; end
|
||||||
echo beta3.1
|
echo beta3.1
|
||||||
echo beta3.2
|
echo beta3.2
|
||||||
elseif begin ; echo yep3.2; true ; end
|
else if begin ; echo yep3.2; true ; end
|
||||||
echo gamma3.1
|
echo gamma3.1
|
||||||
echo gamma3.2
|
echo gamma3.2
|
||||||
else
|
else
|
||||||
|
@ -84,10 +83,10 @@ end
|
||||||
if false
|
if false
|
||||||
echo alpha4.1
|
echo alpha4.1
|
||||||
echo alpha4.2
|
echo alpha4.2
|
||||||
elseif begin ; echo yep4.1; false ; end
|
else if begin ; echo yep4.1; false ; end
|
||||||
echo beta4.1
|
echo beta4.1
|
||||||
echo beta4.2
|
echo beta4.2
|
||||||
elseif begin ; echo yep4.2; false ; end
|
else if begin ; echo yep4.2; false ; end
|
||||||
echo gamma4.1
|
echo gamma4.1
|
||||||
echo gamma4.2
|
echo gamma4.2
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue