diff --git a/MathPad/MPExpression.h b/MathPad/MPExpression.h index 7eb781d..28e3bd3 100644 --- a/MathPad/MPExpression.h +++ b/MathPad/MPExpression.h @@ -78,16 +78,21 @@ extern NSString *MPDivisionOperator; @interface MPMutableExpression : MPExpression -- (void)replaceSymbolsInRange:(NSRange)range withSymbols:(NSArray *)symbols; +- (void)replaceSymbolsInRange:(NSRange)range + withSymbols:(NSArray *)symbols; @end @interface MPMutableExpression (MPMutableExpressionExtensionMethods) -- (void)insertString:(NSString *)aString atIndex:(NSUInteger)loc; -- (void)insertFunction:(MPFunction *)aFunction atIndex:(NSUInteger)loc; -- (void)insertExpression:(MPExpression *)anExpression atIndex:(NSUInteger)loc; -- (void)insertSymbols:(NSArray *)symbols atIndex:(NSUInteger)loc; +- (void)insertString:(NSString *)aString + atIndex:(NSUInteger)loc; +- (void)insertFunction:(MPFunction *)aFunction + atIndex:(NSUInteger)loc; +- (void)insertExpression:(MPExpression *)anExpression + atIndex:(NSUInteger)loc; +- (void)insertSymbols:(NSArray *)symbols + atIndex:(NSUInteger)loc; - (void)deleteSymbolsInRange:(NSRange)range; diff --git a/MathPad/MPExpression.m b/MathPad/MPExpression.m index 73d604e..bdcb62d 100644 --- a/MathPad/MPExpression.m +++ b/MathPad/MPExpression.m @@ -10,6 +10,8 @@ #import "MPFunction.h" #import "MPException.h" +#import "NSObject+MPStringTest.h" + NSString *MPAdditionOperator = @"+"; NSString *MPSubtractionOperator = @"-"; NSString *MPMultiplicationOperator = @"*"; @@ -21,7 +23,9 @@ NSString *MPDivisionOperator = @"/"; - (void)validateSymbols:(NSArray *)symbols; - (NSArray *)repairedSymbols:(NSArray *)symbols; // Merges subsequent strings - (void)repairSymbols:(NSMutableArray *)symbols; -- (void)getSplitOffset:(out NSUInteger *)offset inSymbolAtIndex:(out NSUInteger *)symbolIndex forSplitLocation:(NSUInteger)loc; +- (void)getSplitOffset:(out NSUInteger *)offset + inSymbolAtIndex:(out NSUInteger *)symbolIndex + forSplitLocation:(NSUInteger)loc; @end @@ -98,7 +102,7 @@ NSString *MPDivisionOperator = @"/"; - (NSInteger)lengthOfSymbol:(id)symbol { - if ([symbol isKindOfClass:[NSString class]]) { + if ([symbol isString]) { return [symbol length]; } return 1; @@ -108,7 +112,7 @@ NSString *MPDivisionOperator = @"/"; - (void)validateSymbols:(NSArray *)symbols { for (id symbol in symbols) { - if (!([symbol isKindOfClass:[NSString class]] + if (!([symbol isString] || [symbol isKindOfClass:[MPFunction class]])) { @throw [NSException exceptionWithName:MPIllegalSymbolException reason:@"Only NSString and MPFunction objects are valid symbols." @@ -127,19 +131,26 @@ NSString *MPDivisionOperator = @"/"; - (void)repairSymbols:(NSMutableArray *)symbols { - for (NSInteger index = 1; index < symbols.count; index++) { - id last = symbols[index-1]; + for (NSInteger index = 0; index < symbols.count; index++) { + id next = index+1 < symbols.count ? symbols[index+1] : nil; id current = symbols[index]; - if ([last isKindOfClass:[NSString class]] && [current isKindOfClass:[NSString class]]) { - NSString *new = [NSString stringWithFormat:@"%@%@", last, current]; - [symbols replaceObjectAtIndex:index-1 withObject:new]; - [symbols removeObjectAtIndex:index]; - index--; + if ([current isString]) { + if ([current length] == 0) { + [symbols removeObjectAtIndex:index]; + index--; + } else if ([next isString]) { + NSString *new = [NSString stringWithFormat:@"%@%@", current, next]; + [symbols replaceObjectAtIndex:index withObject:new]; + [symbols removeObjectAtIndex:index+1]; + index--; + } } } } -- (void)getSplitOffset:(out NSUInteger *)offset inSymbolAtIndex:(out NSUInteger *)symbolIndex forSplitLocation:(NSUInteger)loc +- (void)getSplitOffset:(out NSUInteger *)offset + inSymbolAtIndex:(out NSUInteger *)symbolIndex + forSplitLocation:(NSUInteger)loc { NSUInteger length = 0; NSUInteger index = 0; @@ -227,7 +238,9 @@ NSString *MPDivisionOperator = @"/"; - (MPExpression *)subexpressionWithRange:(NSRange)range { if (NSMaxRange(range) > self.length) { - @throw [NSException exceptionWithName:NSRangeException reason:@"Range outside bounds of expression." userInfo:nil]; + @throw [NSException exceptionWithName:NSRangeException + reason:@"Range outside bounds of expression." + userInfo:nil]; } if (range.location == self.length || NSMaxRange(range) == 0 || range.length == 0) { // Speed this up @@ -235,20 +248,24 @@ NSString *MPDivisionOperator = @"/"; } NSUInteger startOffset; NSUInteger startSymbolIndex; - [self getSplitOffset:&startOffset inSymbolAtIndex:&startSymbolIndex forSplitLocation:range.location]; + [self getSplitOffset:&startOffset + inSymbolAtIndex:&startSymbolIndex + forSplitLocation:range.location]; id startSymbol = _symbols[startSymbolIndex]; if (startOffset == [self lengthOfSymbol:startSymbol]) { startOffset = 0; startSymbolIndex++; startSymbol = _symbols[startSymbolIndex]; - } else if ([startSymbol isKindOfClass:[NSString class]]) { + } else if ([startSymbol isString]) { startSymbol = [startSymbol substringFromIndex:startOffset]; } NSUInteger endOffset; NSUInteger endSymbolIndex; - [self getSplitOffset:&endOffset inSymbolAtIndex:&endSymbolIndex forSplitLocation:NSMaxRange(range)]; + [self getSplitOffset:&endOffset + inSymbolAtIndex:&endSymbolIndex + forSplitLocation:NSMaxRange(range)]; id endSymbol = _symbols[endSymbolIndex]; - if ([endSymbol isKindOfClass:[NSString class]]) { + if ([endSymbol isString]) { endSymbol = [endSymbol substringToIndex:endOffset]; } @@ -261,9 +278,10 @@ NSString *MPDivisionOperator = @"/"; } if (endSymbolIndex > startSymbolIndex) { [symbols addObject:endSymbol]; - } else if (endSymbolIndex == startSymbolIndex && [startSymbol isKindOfClass:[NSString class]]) { + } else if (endSymbolIndex == startSymbolIndex && [startSymbol isString]) { NSString *result = [_symbols[startSymbolIndex] substringWithRange:NSMakeRange(startOffset, endOffset-startOffset)]; - [symbols replaceObjectAtIndex:0 withObject:result]; + [symbols replaceObjectAtIndex:0 + withObject:result]; } return [[MPExpression alloc] initWithSymbols:symbols]; } @@ -343,13 +361,14 @@ NSString *MPDivisionOperator = @"/"; NSMutableString *description = [[NSMutableString alloc] init]; NSUInteger index = 0; for (id symbol in _symbols) { - if ([symbol isKindOfClass:[NSString class]]) { + if ([symbol isString]) { NSMutableString *correctedSymbol = [[symbol stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] mutableCopy]; // Prefix operator if (symbol != _symbols[0]) { unichar prefix = [correctedSymbol characterAtIndex:0]; if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:prefix]) { - [correctedSymbol insertString:@"*" atIndex:0]; + [correctedSymbol insertString:@"*" + atIndex:0]; } } // Suffix operator @@ -385,7 +404,8 @@ NSString *MPDivisionOperator = @"/"; self = [super initWithSymbols:nil]; if (self) { symbols = [self repairedSymbols:symbols]; - _symbols = [[NSMutableArray alloc] initWithArray:symbols copyItems:YES]; + _symbols = [[NSMutableArray alloc] initWithArray:symbols + copyItems:YES]; } return self; } @@ -396,21 +416,26 @@ NSString *MPDivisionOperator = @"/"; return [_symbols copy]; } -- (void)replaceSymbolsInRange:(NSRange)range withSymbols:(NSArray *)symbols +- (void)replaceSymbolsInRange:(NSRange)range + withSymbols:(NSArray *)symbols { if (NSMaxRange(range) > self.length) { - @throw [NSException exceptionWithName:NSRangeException reason:@"Range out of bounds of expression." userInfo:nil]; + @throw [NSException exceptionWithName:NSRangeException + reason:@"Range out of bounds of expression." + userInfo:nil]; } [self validateSymbols:symbols]; // Locate the position, split the symbols NSUInteger startIndex; - [self splitSymbolsAtLocation:range.location insertionIndex:&startIndex]; + [self splitSymbolsAtLocation:range.location + insertionIndex:&startIndex]; // Perform the deletion if (range.length > 0) { NSUInteger endIndex; - [self splitSymbolsAtLocation:NSMaxRange(range) insertionIndex:&endIndex]; + [self splitSymbolsAtLocation:NSMaxRange(range) + insertionIndex:&endIndex]; NSMutableIndexSet *indexes = [[NSMutableIndexSet alloc] init]; for (NSUInteger index = startIndex; index < endIndex; index++) { [indexes addIndex:index]; @@ -421,7 +446,8 @@ NSString *MPDivisionOperator = @"/"; // Perform the insertion if (symbols.count > 0) { NSArray *newSymbols = [[NSArray alloc] initWithArray:symbols copyItems:YES]; - [(NSMutableArray *)_symbols replaceObjectsInRange:NSMakeRange(startIndex, 0) withObjectsFromArray:newSymbols]; + [(NSMutableArray *)_symbols replaceObjectsInRange:NSMakeRange(startIndex, 0) + withObjectsFromArray:newSymbols]; } // Revalidate structure and invalidate length @@ -429,11 +455,14 @@ NSString *MPDivisionOperator = @"/"; _length = 0; } -- (void)splitSymbolsAtLocation:(NSUInteger)loc insertionIndex:(out NSUInteger *)insertionIndex +- (void)splitSymbolsAtLocation:(NSUInteger)loc + insertionIndex:(out NSUInteger *)insertionIndex { NSUInteger splitSymbolIndex; NSUInteger splitOffset; - [self getSplitOffset:&splitOffset inSymbolAtIndex:&splitSymbolIndex forSplitLocation:loc]; + [self getSplitOffset:&splitOffset + inSymbolAtIndex:&splitSymbolIndex + forSplitLocation:loc]; id splitSymbol = _symbols[splitSymbolIndex]; NSInteger splitSymbolLength = [self lengthOfSymbol:splitSymbol]; if (splitOffset == splitSymbolLength) { @@ -443,9 +472,11 @@ NSString *MPDivisionOperator = @"/"; if (splitOffset != 0) { NSString *leftPart = [splitSymbol substringToIndex:splitOffset]; NSString *rightPart = [splitSymbol substringFromIndex:splitOffset]; - [(NSMutableArray *)_symbols replaceObjectAtIndex:splitSymbolIndex withObject:leftPart]; + [(NSMutableArray *)_symbols replaceObjectAtIndex:splitSymbolIndex + withObject:leftPart]; splitSymbolIndex++; - [(NSMutableArray *)_symbols insertObject:rightPart atIndex:splitSymbolIndex]; + [(NSMutableArray *)_symbols insertObject:rightPart + atIndex:splitSymbolIndex]; } *insertionIndex = splitSymbolIndex; } @@ -454,22 +485,29 @@ NSString *MPDivisionOperator = @"/"; @implementation MPMutableExpression (MPMutableExpressionExtensionMethods) -- (void)insertString:(NSString *)aString atIndex:(NSUInteger)loc +- (void)insertString:(NSString *)aString + atIndex:(NSUInteger)loc { - [self insertSymbols:@[aString] atIndex:loc]; + [self insertSymbols:@[aString] + atIndex:loc]; } -- (void)insertFunction:(MPFunction *)aFunction atIndex:(NSUInteger)loc +- (void)insertFunction:(MPFunction *)aFunction + atIndex:(NSUInteger)loc { - [self insertSymbols:@[aFunction] atIndex:loc]; + [self insertSymbols:@[aFunction] + atIndex:loc]; } -- (void)insertExpression:(MPExpression *)anExpression atIndex:(NSUInteger)loc +- (void)insertExpression:(MPExpression *)anExpression + atIndex:(NSUInteger)loc { - [self insertSymbols:anExpression.symbols atIndex:loc]; + [self insertSymbols:anExpression.symbols + atIndex:loc]; } -- (void)insertSymbols:(NSArray *)symbols atIndex:(NSUInteger)loc +- (void)insertSymbols:(NSArray *)symbols + atIndex:(NSUInteger)loc { [self replaceSymbolsInRange:NSMakeRange(loc, 0) withSymbols:symbols]; diff --git a/MathPad/MPFunction.h b/MathPad/MPFunction.h index 060814a..8e2bafa 100644 --- a/MathPad/MPFunction.h +++ b/MathPad/MPFunction.h @@ -18,7 +18,8 @@ - (NSUInteger)numberOfChildren; - (MPExpression *)childAtIndex:(NSUInteger)index; -- (void)setChild:(MPExpression *)child atIndex:(NSUInteger)index; +- (void)setChild:(MPExpression *)child + atIndex:(NSUInteger)index; #pragma mark Evaluating Functions diff --git a/MathPad/MPFunction.m b/MathPad/MPFunction.m index 5424a0c..a1aa526 100644 --- a/MathPad/MPFunction.m +++ b/MathPad/MPFunction.m @@ -32,7 +32,8 @@ return nil; } -- (void)setChild:(MPExpression *)child atIndex:(NSUInteger)index +- (void)setChild:(MPExpression *)child + atIndex:(NSUInteger)index {} #pragma mark Evaluating Functions