Archived
1

Removed Prefix/Suffix Placeholder (not needed)

Added Operator Constants
Removed NSMutableString from NSMutableExpression (not needed)
Implemented -description
Added Tests for: -description, -copy, -mutableCopy
Some Logical Corrections.
This commit is contained in:
Kim Wittenburg
2014-04-20 14:34:42 +02:00
parent 0c16b92aea
commit 8b5a69b885
4 changed files with 110 additions and 70 deletions

View File

@@ -7,8 +7,6 @@
//
#import "MPException.h"
#import "MPException_Private.h"
NSString *MPIllegalSymbolException = @"MPIllegalSymbolException";
NSString *MPIllegalSymbolExceptionReason = @"Only NSString and MPFunction objects are valid symbols.";
NSString *MPIllegalSymbolExceptionSymbolKey = @"MPIllegalSymbolExceptionSymbolKey";

View File

@@ -8,6 +8,11 @@
@class MPExpression, MPFunction;
extern NSString *MPAdditionOperator;
extern NSString *MPSubtractionOperator;
extern NSString *MPMultiplicationOperator;
extern NSString *MPDivisionOperator;
@interface MPExpression : NSObject <NSCopying, NSMutableCopying, NSCoding>
#pragma mark Creation Methods
@@ -25,6 +30,8 @@
@interface MPExpression (MPExpressionExtensionMethods)
+ (NSArray *)operators;
#pragma mark Creation Methods
- (id)init;
@@ -47,12 +54,6 @@
- (BOOL)isEqualToExpression:(MPExpression *)anExpression;
// TODO: prefix and suffix operator
/*
- (BOOL)hasPrefix:(NSString *)aString;
- (BOOL)hasSuffix:(NSString *)aString;
*/
- (MPExpression *)expressionByAppendingString:(NSString *)aString;
- (MPExpression *)expressionByAppendingFunction:(MPFunction *)aFunction;
- (MPExpression *)expressionByAppendingExpression:(MPExpression *)anExpression;

View File

@@ -9,7 +9,11 @@
#import "MPExpression.h"
#import "MPFunction.h"
#import "MPException.h"
#import "MPException_Private.h"
NSString *MPAdditionOperator = @"+";
NSString *MPSubtractionOperator = @"-";
NSString *MPMultiplicationOperator = @"*";
NSString *MPDivisionOperator = @"/";
@interface MPExpression (MPExpressionPrivate)
@@ -71,7 +75,6 @@
- (id)mutableCopyWithZone:(NSZone *)zone
{
// TODO: Test Copying
MPMutableExpression *mutableCopy = [[MPMutableExpression allocWithZone:zone] initWithSymbols:_symbols];
return mutableCopy;
}
@@ -108,12 +111,13 @@
if (!([symbol isKindOfClass:[NSString class]]
|| [symbol isKindOfClass:[MPFunction class]])) {
@throw [NSException exceptionWithName:MPIllegalSymbolException
reason:MPIllegalSymbolExceptionReason
reason:@"Only NSString and MPFunction objects are valid symbols."
userInfo:@{MPIllegalSymbolExceptionSymbolKey: symbol}];
}
}
}
// TODO: Deal with empty strings
- (NSArray *)repairedSymbols:(NSArray *)symbols
{
NSMutableArray *mutableSymbols = [symbols mutableCopy];
@@ -127,7 +131,7 @@
id last = symbols[index-1];
id current = symbols[index];
if ([last isKindOfClass:[NSString class]] && [current isKindOfClass:[NSString class]]) {
NSMutableString *new = [NSMutableString stringWithFormat:@"%@%@", last, current];
NSString *new = [NSString stringWithFormat:@"%@%@", last, current];
[symbols replaceObjectAtIndex:index-1 withObject:new];
[symbols removeObjectAtIndex:index];
index--;
@@ -156,6 +160,11 @@
@implementation MPExpression (MPExpressionExtensionMethods)
+ (NSArray *)operators
{
return @[MPAdditionOperator, MPSubtractionOperator, MPMultiplicationOperator, MPDivisionOperator];
}
#pragma mark Creation Methods
- (instancetype)init
@@ -279,8 +288,6 @@
return [_symbols isEqualToArray:anExpression->_symbols];
}
// TODO: prefix and suffix operators
- (MPExpression *)expressionByAppendingString:(NSString *)aString
{
return [self expressionByAppendingSymbols:@[aString]];
@@ -333,11 +340,34 @@
- (NSString *)description
{
#warning Unimplemented Method
/*
Join the symbols regarding pre- and suffix operators. If there is no operator a * should be inserted
*/
return [super description];
NSMutableString *description = [[NSMutableString alloc] init];
NSUInteger index = 0;
for (id symbol in _symbols) {
if ([symbol isKindOfClass:[NSString class]]) {
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];
}
}
// Suffix operator
if (symbol != [_symbols lastObject]) {
unichar suffix = [correctedSymbol characterAtIndex:correctedSymbol.length-1];
if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:suffix]) {
[correctedSymbol appendString:@"*"];
}
}
[description appendString:correctedSymbol];
} else if (index > 0 && [_symbols[index-1] isKindOfClass:[MPFunction class]]) {
[description appendFormat:@"*%@", [symbol description]];
} else {
[description appendString:[symbol description]];
}
index++;
}
return description;
}
- (NSUInteger)hash
@@ -347,40 +377,6 @@
@end
@interface MPMutableExpression (MPMutableExpressionPrivate)
- (NSArray *)makeSymbols:(NSArray *)symbols mutable:(BOOL)mutable copySymbols:(BOOL)copy;
@end
@implementation MPMutableExpression (MPMutableExpressionPrivate)
- (NSArray *)makeSymbols:(NSArray *)symbols mutable:(BOOL)mutable copySymbols:(BOOL)copy
{
NSMutableArray *newSymbols = [[NSMutableArray alloc] initWithCapacity:symbols.count];
for (id symbol in symbols) {
id newSymbol;
if ([symbol isKindOfClass:[NSString class]]) {
if (mutable) {
newSymbol = [symbol mutableCopy];
} else {
newSymbol = [symbol copy];
}
} else {
if (copy) {
newSymbol = [symbol copy];
} else {
newSymbol = symbol;
}
}
[newSymbols addObject:newSymbol];
}
return newSymbols;
}
@end
// A mutable expression uses NSMutableString objects instead of NSString objects
@implementation MPMutableExpression
- (instancetype)initWithSymbols:(NSArray *)symbols
@@ -389,25 +385,15 @@
self = [super initWithSymbols:nil];
if (self) {
symbols = [self repairedSymbols:symbols];
_symbols = [self makeSymbols:symbols
mutable:YES
copySymbols:YES];
_symbols = [[NSMutableArray alloc] initWithArray:symbols copyItems:YES];
}
return self;
}
- (id)symbolAtIndex:(NSUInteger)index
{
id symbol = _symbols[index];
if ([symbol isKindOfClass:[NSString class]]) {
return [symbol copy];
}
return symbol;
}
- (NSArray *)symbols
{
return [self makeSymbols:_symbols mutable:NO copySymbols:NO];
// Return an immutable array:
return [_symbols copy];
}
- (void)replaceSymbolsInRange:(NSRange)range withSymbols:(NSArray *)symbols
@@ -434,7 +420,7 @@
// Perform the insertion
if (symbols.count > 0) {
NSArray *newSymbols = [self makeSymbols:symbols mutable:YES copySymbols:YES];
NSArray *newSymbols = [[NSArray alloc] initWithArray:symbols copyItems:YES];
[(NSMutableArray *)_symbols replaceObjectsInRange:NSMakeRange(startIndex, 0) withObjectsFromArray:newSymbols];
}
@@ -455,8 +441,8 @@
splitSymbolIndex++;
}
if (splitOffset != 0) {
NSMutableString *leftPart = [[splitSymbol substringToIndex:splitOffset] mutableCopy];
NSMutableString *rightPart = [[splitSymbol substringFromIndex:splitOffset] mutableCopy];
NSString *leftPart = [splitSymbol substringToIndex:splitOffset];
NSString *rightPart = [splitSymbol substringFromIndex:splitOffset];
[(NSMutableArray *)_symbols replaceObjectAtIndex:splitSymbolIndex withObject:leftPart];
splitSymbolIndex++;
[(NSMutableArray *)_symbols insertObject:rightPart atIndex:splitSymbolIndex];

View File

@@ -154,7 +154,62 @@
XCTAssertEqualObjects(expression2, expression3);
}
// TODO: Test prefix- and suffix operators via -description method
- (void)testDescription {
// Test Simple Expressions
MPExpression *testExpression = [[MPExpression alloc] initWithString:@"1234"];
XCTAssertEqualObjects([testExpression description], @"1234");
testExpression = [[MPExpression alloc] initWithFunction:[[MPFunction alloc] init]];
XCTAssertEqualObjects([testExpression description], @"[]");
// Test function after literal without explicit operator
testExpression = [[MPExpression alloc] initWithSymbols:@[@"123", [[MPFunction alloc] init]]];
XCTAssertEqualObjects([testExpression description], @"123*[]");
// Test function after literal with explicit operator
testExpression = [[MPExpression alloc] initWithSymbols:@[@"123+", [[MPFunction alloc] init]]];
XCTAssertEqualObjects([testExpression description], @"123+[]");
// Test literal after function without explicit operator
testExpression = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], @"123"]];
XCTAssertEqualObjects([testExpression description], @"[]*123");
// Test literal after function with explicit operator
testExpression = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], @"-123"]];
XCTAssertEqualObjects([testExpression description], @"[]-123");
// Test function after function without explicit operator
testExpression = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], [[MPFunction alloc] init]]];
XCTAssertEqualObjects([testExpression description], @"[]*[]");
// Test function after function with explicit operator
testExpression = [[MPExpression alloc] initWithSymbols:@[[[MPFunction alloc] init], @"-", [[MPFunction alloc] init]]];
XCTAssertEqualObjects([testExpression description], @"[]-[]");
// Test whitespaces in literal
testExpression = [[MPExpression alloc] initWithSymbols:@[@" 123 + ", [[MPFunction alloc] init]]];
XCTAssertEqualObjects([testExpression description], @"123 +[]");
}
- (void)testCopying {
MPExpression *baseExpression = [[MPExpression alloc] initWithFunction:[[MPFunction alloc] init]];
MPExpression *copy = [baseExpression copy];
XCTAssertNotEqual(copy, baseExpression);
XCTAssertNotEqual([baseExpression symbolAtIndex:0], [copy symbolAtIndex:0]);
}
- (void)testMutableCopying {
MPExpression *baseExpression = [[MPExpression alloc] initWithString:@"123"];
MPMutableExpression *expression1 = [baseExpression mutableCopy];
[expression1 appendFunction:[[MPFunction alloc] init]];
MPExpression *expression2 = [[MPExpression alloc] initWithSymbols:@[@"123", [[MPFunction alloc] init]]];
XCTAssertEqualObjects(expression1, expression2);
XCTAssertNotEqualObjects(baseExpression, expression1);
}
// TODO: Test evaluating expressions
@end