Fix bug with leading negation operator in roll commands
This commit is contained in:
parent
eab4f6e0b8
commit
f8c6031507
179
SA_DiceParser.m
179
SA_DiceParser.m
@ -180,7 +180,70 @@ static NSDictionary *_validCharactersDict;
|
||||
{
|
||||
NSString *operator = [dieRollString substringWithRange:lastOperatorRange];
|
||||
|
||||
return [self legacyExpressionForStringDescribingOperation:dieRollString withOperator:operator atRange:lastOperatorRange];
|
||||
// If the last (and thus only) operator is the leading character of
|
||||
// the expression, then this is one of several possible special cases.
|
||||
if(lastOperatorRange.location == 0)
|
||||
{
|
||||
NSMutableDictionary *expression;
|
||||
|
||||
// First, we check for whether there even is anything more to the
|
||||
// roll string besides the operator. If not, then the string is
|
||||
// definitely malformed...
|
||||
if(dieRollString.length == lastOperatorRange.length)
|
||||
{
|
||||
expression = [NSMutableDictionary dictionary];
|
||||
expression[SA_DB_TERM_TYPE] = SA_DB_TERM_TYPE_OPERATION;
|
||||
expression[SA_DB_INPUT_STRING] = dieRollString;
|
||||
|
||||
addErrorToExpression(SA_DB_ERROR_INVALID_EXPRESSION, expression);
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
// If the last operator is the leading character (i.e. there's just
|
||||
// one operator in the expression, and it's at the beginning), and
|
||||
// there's more to the expression than just the operator, then
|
||||
// this is either an expression whose first term (which may or may
|
||||
// not be its only term) is a simple value expression which
|
||||
// represents a negative number - or, it's a malformed expression
|
||||
// (because operators other than negation cannot begin an
|
||||
// expression).
|
||||
// In the former case, we do nothing, letting the testing for
|
||||
// expression type fall through to the remaining cases (roll command
|
||||
// or simple value).
|
||||
// In the latter case, we register an error and return.
|
||||
if([[SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_MINUS] containsCharactersInString:operator])
|
||||
{
|
||||
// We've determined that this expression begins with a simple
|
||||
// value expression that represents a negative number.
|
||||
// This next line is a hack to account for the fact that Cocoa's
|
||||
// Unicode compliance is incomplete. :( NSString's integerValue
|
||||
// method only accepts the hyphen as a negation sign when reading a
|
||||
// number - not any of the Unicode characters which officially
|
||||
// symbolize negation! But we are more modern-minded, and accept
|
||||
// arbitrary symbols as minus-sign. For proper parsing, though,
|
||||
// we have to replace it like this...
|
||||
dieRollString = [dieRollString stringByReplacingCharactersInRange:lastOperatorRange withString:@"-"];
|
||||
|
||||
// Now we skip the remainder of the "is it an operator?" code
|
||||
// and fall through to "is it a roll command, or maybe a simple
|
||||
// value?"...
|
||||
}
|
||||
else
|
||||
{
|
||||
expression = [NSMutableDictionary dictionary];
|
||||
expression[SA_DB_TERM_TYPE] = SA_DB_TERM_TYPE_OPERATION;
|
||||
expression[SA_DB_INPUT_STRING] = dieRollString;
|
||||
|
||||
addErrorToExpression(SA_DB_ERROR_INVALID_EXPRESSION, expression);
|
||||
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return [self legacyExpressionForStringDescribingOperation:dieRollString withOperator:operator atRange:lastOperatorRange];
|
||||
}
|
||||
}
|
||||
|
||||
// If not an operation, the top-level term might be a die roll command.
|
||||
@ -202,90 +265,44 @@ static NSDictionary *_validCharactersDict;
|
||||
{
|
||||
NSMutableDictionary *expression;
|
||||
|
||||
// If the operator is at the beginning, this may be negation; we handle that
|
||||
// case later below. Otherwise, it's a binary operator.
|
||||
if(operatorRange.location != 0)
|
||||
expression = [NSMutableDictionary dictionary];
|
||||
expression[SA_DB_TERM_TYPE] = SA_DB_TERM_TYPE_OPERATION;
|
||||
expression[SA_DB_INPUT_STRING] = dieRollString;
|
||||
|
||||
// Operands of a binary operator are the expressions generated by
|
||||
// parsing the strings before and after the addition operator.
|
||||
expression[SA_DB_OPERAND_LEFT] = [self legacyExpressionForLegalString:[dieRollString substringToIndex:operatorRange.location]];
|
||||
expression[SA_DB_OPERAND_RIGHT] = [self legacyExpressionForLegalString:[dieRollString substringFromIndex:(operatorRange.location + operatorRange.length)]];
|
||||
|
||||
// Check to see if the term is a subtraction operation.
|
||||
if([[SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_MINUS] containsCharactersInString:operator])
|
||||
{
|
||||
expression = [NSMutableDictionary dictionary];
|
||||
expression[SA_DB_TERM_TYPE] = SA_DB_TERM_TYPE_OPERATION;
|
||||
expression[SA_DB_INPUT_STRING] = dieRollString;
|
||||
|
||||
// Operands of a binary operator are the expressions generated by
|
||||
// parsing the strings before and after the addition operator.
|
||||
expression[SA_DB_OPERAND_LEFT] = [self legacyExpressionForLegalString:[dieRollString substringToIndex:operatorRange.location]];
|
||||
expression[SA_DB_OPERAND_RIGHT] = [self legacyExpressionForLegalString:[dieRollString substringFromIndex:(operatorRange.location + operatorRange.length)]];
|
||||
|
||||
// Check to see if the term is a subtraction operation.
|
||||
if([[SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_MINUS] containsCharactersInString:operator])
|
||||
{
|
||||
expression[SA_DB_OPERATOR] = SA_DB_OPERATOR_MINUS;
|
||||
}
|
||||
// Check to see if the term is an addition operation.
|
||||
else if([[SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_PLUS] containsCharactersInString:operator])
|
||||
{
|
||||
expression[SA_DB_OPERATOR] = SA_DB_OPERATOR_PLUS;
|
||||
}
|
||||
// Check to see if the term is a multiplication operation.
|
||||
else if([[SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_TIMES] containsCharactersInString:operator])
|
||||
{
|
||||
// Look for other, lower-precedence operators to the left of the
|
||||
// multiplication operator. If found, split the string there
|
||||
// instead of at the current operator.
|
||||
NSString *allLowerPrecedenceOperators = [NSString stringWithFormat:@"%@%@", [SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_PLUS], [SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_MINUS]];
|
||||
NSRange lastLowerPrecedenceOperatorRange = [dieRollString rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:allLowerPrecedenceOperators] options:NSBackwardsSearch range:NSMakeRange(1, operatorRange.location - 1)];
|
||||
if(lastLowerPrecedenceOperatorRange.location != NSNotFound)
|
||||
{
|
||||
NSString *lowerPrecedenceOperator = [dieRollString substringWithRange:lastLowerPrecedenceOperatorRange];
|
||||
return [self legacyExpressionForStringDescribingOperation:dieRollString withOperator:lowerPrecedenceOperator atRange:lastLowerPrecedenceOperatorRange];
|
||||
}
|
||||
|
||||
expression[SA_DB_OPERATOR] = SA_DB_OPERATOR_TIMES;
|
||||
}
|
||||
else
|
||||
{
|
||||
addErrorToExpression(SA_DB_ERROR_UNKNOWN_OPERATOR, expression);
|
||||
}
|
||||
expression[SA_DB_OPERATOR] = SA_DB_OPERATOR_MINUS;
|
||||
}
|
||||
// Check to see if the term is an addition operation.
|
||||
else if([[SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_PLUS] containsCharactersInString:operator])
|
||||
{
|
||||
expression[SA_DB_OPERATOR] = SA_DB_OPERATOR_PLUS;
|
||||
}
|
||||
// Check to see if the term is a multiplication operation.
|
||||
else if([[SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_TIMES] containsCharactersInString:operator])
|
||||
{
|
||||
// Look for other, lower-precedence operators to the left of the
|
||||
// multiplication operator. If found, split the string there
|
||||
// instead of at the current operator.
|
||||
NSString *allLowerPrecedenceOperators = [NSString stringWithFormat:@"%@%@", [SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_PLUS], [SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_MINUS]];
|
||||
NSRange lastLowerPrecedenceOperatorRange = [dieRollString rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:allLowerPrecedenceOperators] options:NSBackwardsSearch range:NSMakeRange(1, operatorRange.location - 1)];
|
||||
if(lastLowerPrecedenceOperatorRange.location != NSNotFound)
|
||||
{
|
||||
NSString *lowerPrecedenceOperator = [dieRollString substringWithRange:lastLowerPrecedenceOperatorRange];
|
||||
return [self legacyExpressionForStringDescribingOperation:dieRollString withOperator:lowerPrecedenceOperator atRange:lastLowerPrecedenceOperatorRange];
|
||||
}
|
||||
|
||||
expression[SA_DB_OPERATOR] = SA_DB_OPERATOR_TIMES;
|
||||
}
|
||||
// Check to see if the term is a negation operation (we can only reach this
|
||||
// case if the subtraction operator is at the beginning).
|
||||
else
|
||||
{
|
||||
if(dieRollString.length == operatorRange.length)
|
||||
{
|
||||
expression = [NSMutableDictionary dictionary];
|
||||
expression[SA_DB_TERM_TYPE] = SA_DB_TERM_TYPE_OPERATION;
|
||||
expression[SA_DB_INPUT_STRING] = dieRollString;
|
||||
|
||||
addErrorToExpression(SA_DB_ERROR_INVALID_EXPRESSION, expression);
|
||||
|
||||
return expression;
|
||||
}
|
||||
if([[SA_DiceParser validCharactersForOperator:SA_DB_OPERATOR_MINUS] containsCharactersInString:operator])
|
||||
{
|
||||
// It turns out this isn't actually an operation expression. It's a
|
||||
// simple value expression with a negative number.
|
||||
|
||||
// This next line is a hack to account for the fact that Cocoa's
|
||||
// Unicode compliance is incomplete. :( NSString's integerValue
|
||||
// method only accepts the hyphen as a negation sign when reading a
|
||||
// number - not any of the Unicode characters which officially
|
||||
// symbolize negation! But we are more modern-minded, and accept
|
||||
// arbitrary symbols as minus-sign. For proper parsing, though,
|
||||
// we have to replace it like this...
|
||||
NSString *fixedRollString = [dieRollString stringByReplacingCharactersInRange:operatorRange withString:@"-"];
|
||||
|
||||
return [self legacyExpressionForStringDescribingNumericValue:fixedRollString];
|
||||
}
|
||||
else
|
||||
{
|
||||
expression = [NSMutableDictionary dictionary];
|
||||
expression[SA_DB_TERM_TYPE] = SA_DB_TERM_TYPE_OPERATION;
|
||||
expression[SA_DB_INPUT_STRING] = dieRollString;
|
||||
|
||||
addErrorToExpression(SA_DB_ERROR_INVALID_EXPRESSION, expression);
|
||||
|
||||
return expression;
|
||||
}
|
||||
addErrorToExpression(SA_DB_ERROR_UNKNOWN_OPERATOR, expression);
|
||||
}
|
||||
|
||||
// The operands have now been parsed recursively; this parsing may have
|
||||
|
||||
Loading…
Reference in New Issue
Block a user