aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2012-09-03 13:24:01 -0700
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2012-09-03 13:24:01 -0700
commit1a59346b51e9ac5a89e303374f4a7ce1647d4c98 (patch)
tree2aae41b1205b7ae2e14eecb796a934c30c350ddc
parentff124465fdfe39096ad14226a6c8aaa08d17bc7f (diff)
Changed "elseif" to "else if"
-rw-r--r--builtin.cpp1
-rw-r--r--builtin.h4
-rw-r--r--doc_src/if.txt4
-rw-r--r--fish_tests.cpp8
-rw-r--r--parser.cpp133
-rw-r--r--parser.h2
-rw-r--r--parser_keywords.cpp2
-rw-r--r--parser_keywords.h2
-rw-r--r--tests/test7.in19
9 files changed, 117 insertions, 58 deletions
diff --git a/builtin.cpp b/builtin.cpp
index 8c347111..c1f0cc2e 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -3792,7 +3792,6 @@ static const builtin_data_t builtin_datas[]=
{ L"count", &builtin_count, N_( L"Count the number of arguments" ) },
{ L"echo", &builtin_echo, N_( L"Print arguments" ) },
{ 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"end", &builtin_end, N_( L"End a block of commands" ) },
{ L"exec", &builtin_generic, N_( L"Run command in current process" ) },
diff --git a/builtin.h b/builtin.h
index eee03b90..e4683f00 100644
--- a/builtin.h
+++ b/builtin.h
@@ -73,6 +73,10 @@ enum
#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
*/
diff --git a/doc_src/if.txt b/doc_src/if.txt
index aa43bdfb..dae82ca6 100644
--- a/doc_src/if.txt
+++ b/doc_src/if.txt
@@ -1,7 +1,7 @@
\section if if - conditionally execute a command
\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
@@ -24,7 +24,7 @@ variable.
<pre>
if test -f foo.txt
echo foo.txt exists
-elseif test -f bar.txt
+else if test -f bar.txt
echo bar.txt exists
else
echo foo.txt and bar.txt do not exist
diff --git a/fish_tests.cpp b/fish_tests.cpp
index 0d0c5f9b..438254b4 100644
--- a/fish_tests.cpp
+++ b/fish_tests.cpp
@@ -434,9 +434,13 @@ static void test_parser()
{
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 ) )
diff --git a/parser.cpp b/parser.cpp
index 6c195199..ab79bc4b 100644
--- a/parser.cpp
+++ b/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
*/
-#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
@@ -1408,11 +1413,6 @@ void parser_t::parse_job_argument_list( process_t *p,
{
skip=0;
}
- else if (type == IF && args.at(0).completion == L"elseif")
- {
- //skip = 0;
- printf("SKIP elseif???\n");
- }
}
if( !skip )
@@ -1898,19 +1898,37 @@ int parser_t::parse_job( process_t *p,
is_new_block=1;
consumed = true;
}
- else if( nxt == L"elseif" )
+ else if (nxt == L"else")
{
- /* Piggyback on the if block, but we need the elseif command */
- job_set_flag( j, JOB_ELSEIF, 1 );
- tok_next( tok );
- consumed = true;
-
- /* Determine if we need to unskip */
- if (current_block->type() == IF)
+ /* Record where the else is for error reporting */
+ const int else_pos = tok_get_pos(tok);
+ /* See if we have any more arguments, that is, whether we're ELSE IF ... or just ELSE. */
+ tok_next(tok);
+ if (tok_last_type(tok) == TOK_STRING && current_block->type() == IF)
{
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 */
bool if_result = (proc_get_last_status() == 0);
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;
}
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
*/
- int needs_cmd=0;
+ bool needs_cmd = false;
/*
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
_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 )
{
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 ) )
{
- needs_cmd = 1;
+ needs_cmd = true;
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 )
{
@@ -3304,16 +3321,12 @@ int parser_t::test( const wchar_t * buff,
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
- INVALID_ELSE_OR_ELSEIF_ERR_MSG,
+ INVALID_ELSE_ERR_MSG,
command.c_str());
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
- {
+ {
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 ) ) )
{
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 );
}
}
- needs_cmd=0;
+ needs_cmd = false;
had_cmd = 0;
is_pipeline=0;
forbid_pipeline=0;
@@ -3488,7 +3525,7 @@ int parser_t::test( const wchar_t * buff,
}
else
{
- needs_cmd=1;
+ needs_cmd = true;
is_pipeline=1;
had_cmd=0;
end_of_cmd = 1;
@@ -3576,8 +3613,26 @@ int parser_t::test( const wchar_t * buff,
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 );
+
+ }
+ }
+ }
}
diff --git a/parser.h b/parser.h
index de59a0d1..331ca520 100644
--- a/parser.h
+++ b/parser.h
@@ -141,7 +141,7 @@ struct 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 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 else_evaluated; // whether we've encountered a terminal else block
diff --git a/parser_keywords.cpp b/parser_keywords.cpp
index 8a5f1b74..efc2ff6e 100644
--- a/parser_keywords.cpp
+++ b/parser_keywords.cpp
@@ -43,7 +43,6 @@ bool parser_keywords_is_subcommand( const wcstring &cmd )
L"while",
L"exec",
L"if",
- L"elseif",
L"and",
L"or",
L"not" );
@@ -69,7 +68,6 @@ bool parser_keywords_is_reserved( const wcstring &word)
L"end",
L"case",
L"else",
- L"elseif",
L"return",
L"continue",
L"break" );
diff --git a/parser_keywords.h b/parser_keywords.h
index 803df49d..5bad85aa 100644
--- a/parser_keywords.h
+++ b/parser_keywords.h
@@ -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
\return 1 of the command parameter is a command, 0 otherwise
diff --git a/tests/test7.in b/tests/test7.in
index 60cc1385..8e80da59 100644
--- a/tests/test7.in
+++ b/tests/test7.in
@@ -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 -- v
-# Test if, else, and elseif
-# Test if, else, and elseif
+# Test if, else, and else if
if true
echo alpha1.1
echo alpha1.2
-elseif false
+else if false
echo beta1.1
echo beta1.2
-elseif false
+else if false
echo gamma1.1
echo gamma1.2
else
@@ -56,10 +55,10 @@ end
if false
echo alpha2.1
echo alpha2.2
-elseif begin ; true ; end
+else if begin ; true ; end
echo beta2.1
echo beta2.2
-elseif begin ; echo nope2.1; false ; end
+else if begin ; echo nope2.1; false ; end
echo gamma2.1
echo gamma2.2
else
@@ -70,10 +69,10 @@ end
if false
echo alpha3.1
echo alpha3.2
-elseif begin ; echo yep3.1; false ; end
+else if begin ; echo yep3.1; false ; end
echo beta3.1
echo beta3.2
-elseif begin ; echo yep3.2; true ; end
+else if begin ; echo yep3.2; true ; end
echo gamma3.1
echo gamma3.2
else
@@ -84,10 +83,10 @@ end
if false
echo alpha4.1
echo alpha4.2
-elseif begin ; echo yep4.1; false ; end
+else if begin ; echo yep4.1; false ; end
echo beta4.1
echo beta4.2
-elseif begin ; echo yep4.2; false ; end
+else if begin ; echo yep4.2; false ; end
echo gamma4.1
echo gamma4.2
else