Bläddra i källkod

Fix bug with leading negation operator in roll commands

master
Said Achmiz 9 år sedan
förälder
incheckning
f8c6031507
1 ändrade filer med 96 tillägg och 79 borttagningar
  1. 96
    79
      SA_DiceParser.m

+ 96
- 79
SA_DiceParser.m Visa fil

@@ -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
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)
{
addErrorToExpression(SA_DB_ERROR_UNKNOWN_OPERATOR, expression);
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

Laddar…
Avbryt
Spara