The "+" operator can be used arithmetically or for string concatenation.
The "-" operator can be used only arithmetically.
"+" and "-" have the same operator strength. That means that when we are parsing an expression, we evaluate operands from left to right and apply the respective operators in order.
1 + 2 - 3 + 4 - 5
=> ( ( (1 + 2 ) - 3 ) + 4 ) - 5
NOT 1 + ( 2 - ( 3 + ( 4 - 5 ) ) )
Code:
[color=green]> ashq print( 1 + 2 - 3 + 4 - 5 )[/color]
-1
does what you expect because the whole expression is arithmetic and is coerced to a string at the end. But as soon as you put in a string, you are starting the string concatenation immediately.
Here is
Java'a operator precedence table .
Notice that at level 11, there are + and - (additive) and also + (string concatenation) and operands are evaluated left to right.
Here is
ASH's operator precedence table.
ASH's operator precedence is coded in Operator.java:
Code:
private int operStrength()
{
if (this.operator.equals(Parser.POST_INCREMENT) ||
this.operator.equals(Parser.POST_DECREMENT))
{
return 14;
}
if ( this.operator.equals( "!" ) ||
this.operator.equals( "~" ) ||
this.operator.equals( "contains" ) ||
this.operator.equals( "remove" ) ||
this.operator.equals(Parser.PRE_INCREMENT) ||
this.operator.equals(Parser.PRE_DECREMENT))
{
return 13;
}
if ( this.operator.equals( "**" ) )
{
return 12;
}
if ( this.operator.equals( "*" ) ||
this.operator.equals( "/" ) ||
this.operator.equals( "%" ) )
{
return 11;
}
if ( this.operator.equals( "+" ) ||
this.operator.equals( "-" ) )
{
return 10;
}
if ( this.operator.equals( "<<" ) ||
this.operator.equals( ">>" ) ||
this.operator.equals( ">>>" ) )
{
return 9;
}
if ( this.operator.equals( "<" ) ||
this.operator.equals( ">" ) ||
this.operator.equals( "<=" ) ||
this.operator.equals( ">=" ) )
{
return 8;
}
if ( this.operator.equals( "==" ) ||
this.operator.equals( Parser.APPROX ) ||
this.operator.equals( "!=" ) )
{
return 7;
}
if ( this.operator.equals( "&" ) )
{
return 6;
}
if ( this.operator.equals( "^" ) )
{
return 5;
}
if ( this.operator.equals( "|" ) )
{
return 4;
}
if ( this.operator.equals( "&&" ) )
{
return 3;
}
if ( this.operator.equals( "||" ) )
{
return 2;
}
if ( this.operator.equals( "?" ) ||
this.operator.equals( ":" ) )
{
return 1;
}
return -1;
}
As I said, "+" and "-" are at the same level. We do not distinguish in this method between "arithmetic +" and and "concatenation +".
I also notice that the Wiki's table has a number of "reserved for" levels which are now implemented.

I think your expectations are incorrect.
That said, if we wanted, we could presumably define Parser.CONCAT and use that operator when we see "+" and the lhs is a string. But I don't want to do that; if you are famliar with Java expressions, ASH expressions should be familiar to you. Let's not create an exception.