Implemented Expression Evaluation/Parsing with Proper Error Handling
This commit is contained in:
@@ -8,9 +8,11 @@
|
||||
|
||||
#import "MPExpressionEvaluator.h"
|
||||
#import "MPExpression.h"
|
||||
#import "MPFunction.h"
|
||||
|
||||
@interface MPExpressionEvaluator ()
|
||||
@property (readwrite, nonatomic, strong) NSString *definedVariable;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPExpressionEvaluator {
|
||||
@@ -52,146 +54,74 @@
|
||||
|
||||
- (NSDecimalNumber *)evaluateVariableDefinition:(BOOL)flag error:(MPParseError *__autoreleasing *)error
|
||||
{
|
||||
#warning Implement Cache
|
||||
// Empty Expression
|
||||
if (self.expression.numberOfElements == 0) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Empty Expression");
|
||||
}
|
||||
*error = MPParseError(NSMakeRange(0, 0), @"Expected Expression");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Expression of just one element
|
||||
if (self.expression.numberOfElements == 1) {
|
||||
id<MPExpressionElement> singleElement = [self.expression elementAtIndex:0];
|
||||
if ([singleElement isString]) {
|
||||
MPParsedElement *parseResult = [parser parseElement:(NSString *)singleElement
|
||||
error:error];
|
||||
if ([parseResult isValidStandaloneElement:error]) {
|
||||
if (flag && parseResult.definedVariable) {
|
||||
self.definedVariable = parseResult.definedVariable;
|
||||
} else if (flag) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Expected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
} else if (parseResult.definedVariable) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Unexpected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
return parseResult.standaloneValue;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
return [singleElement evaluate:error];
|
||||
}
|
||||
}
|
||||
|
||||
// Expression with any number of elements
|
||||
NSDecimalNumber *value = [NSDecimalNumber zero];
|
||||
NSDecimalNumber *currentSummand = nil;
|
||||
NSMutableArray *products = [[NSMutableArray alloc] init];
|
||||
MPParsedProduct *currentProduct = nil;
|
||||
|
||||
// Process the first element
|
||||
id<MPExpressionElement> firstElement = [self.expression elementAtIndex:0];
|
||||
if ([firstElement isString]) {
|
||||
MPParsedElement *parseResult = [parser parseElement:(NSString *)firstElement
|
||||
error:error];
|
||||
if (parseResult && [parseResult isValidElementAtBeginning:error]) {
|
||||
if (flag && parseResult.definedVariable) {
|
||||
self.definedVariable = parseResult.definedVariable;
|
||||
} else if (flag) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Expected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
} else if (parseResult.definedVariable) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Unexpected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
if ([parseResult isFactor]) {
|
||||
currentSummand = parseResult.value;
|
||||
} else {
|
||||
value = [parseResult valueAtBeginning];
|
||||
currentSummand = parseResult.suffixMultiplicator;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentSummand = [firstElement evaluate:error];
|
||||
}
|
||||
if (!currentSummand) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Process the elements between the first and last element
|
||||
for (NSUInteger index = 1; index < self.expression.numberOfElements-1; index++) {
|
||||
id<MPExpressionElement> element = [self.expression elementAtIndex:index];
|
||||
for (NSUInteger elementIndex = 0; elementIndex < self.expression.numberOfElements; elementIndex++) {
|
||||
|
||||
id<MPExpressionElement> element = [self.expression elementAtIndex:elementIndex];
|
||||
|
||||
if ([element isString]) {
|
||||
MPParsedElement *parseResult = [parser parseElement:(NSString *)element
|
||||
error:error];
|
||||
if (parseResult) {
|
||||
if (parseResult.definedVariable) {
|
||||
if (error) {
|
||||
*error = MPParseError(index, @"Unexpected Variable Definition");
|
||||
}
|
||||
MPParsedFactor *nextFactor = nil;
|
||||
if (elementIndex < self.expression.numberOfElements - 1) {
|
||||
MPFunction *nextFunction = (MPFunction *)[self.expression elementAtIndex:elementIndex+1];
|
||||
NSDecimalNumber *functionValue = [nextFunction evaluate:error];
|
||||
if (!functionValue) {
|
||||
return nil;
|
||||
}
|
||||
if ([parseResult isFactor]) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:parseResult.value];
|
||||
} else {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:parseResult.prefixMultiplicator];
|
||||
value = [[value decimalNumberByAdding:currentSummand] decimalNumberByAdding:parseResult.value];
|
||||
currentSummand = parseResult.suffixMultiplicator;
|
||||
}
|
||||
nextFactor = [MPParsedFactor factorWithDecimalNumber:functionValue];
|
||||
}
|
||||
|
||||
NSArray *newProducts;
|
||||
if (elementIndex == 0 && flag) {
|
||||
NSString *definedVariable;
|
||||
newProducts = [parser parseElement:(NSString *)element
|
||||
previousProduct:currentProduct
|
||||
nextFactor:nextFactor
|
||||
definesVariable:YES
|
||||
definedVariable:&definedVariable
|
||||
error:error];
|
||||
self.definedVariable = definedVariable;
|
||||
} else {
|
||||
newProducts = [parser parseElement:(NSString *)element
|
||||
previousProduct:currentProduct
|
||||
nextFactor:nextFactor
|
||||
error:error];
|
||||
}
|
||||
if (!newProducts) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
for (NSUInteger productIndex = 0; productIndex < newProducts.count-1; productIndex++) {
|
||||
[products addObject:newProducts[productIndex]];
|
||||
}
|
||||
currentProduct = newProducts.lastObject;
|
||||
|
||||
elementIndex++;
|
||||
} else {
|
||||
NSDecimalNumber *result = [element evaluate:error];
|
||||
if (result) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:result];
|
||||
} else {
|
||||
NSDecimalNumber *functionValue = [(MPFunction *)element evaluate:error];
|
||||
if (!functionValue) {
|
||||
return nil;
|
||||
}
|
||||
if (!currentProduct) {
|
||||
currentProduct = [[MPParsedProduct alloc] init];
|
||||
}
|
||||
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:functionValue]];
|
||||
}
|
||||
}
|
||||
|
||||
// Process the last element
|
||||
id<MPExpressionElement> lastElement = [self.expression elementAtIndex:self.expression.numberOfElements-1];
|
||||
if ([lastElement isString]) {
|
||||
MPParsedElement *parseResult = [parser parseElement:(NSString *)lastElement
|
||||
error:error];
|
||||
if (parseResult && [parseResult isValidElementAtEnd:error]) {
|
||||
if (parseResult.definedVariable) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Unexpected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
if ([parseResult isFactor]) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:parseResult.value];
|
||||
} else {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:parseResult.prefixMultiplicator];
|
||||
value = [[value decimalNumberByAdding:currentSummand] decimalNumberByAdding:parseResult.value];
|
||||
currentSummand = parseResult.suffixMultiplicator;
|
||||
}
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
NSDecimalNumber *result = [lastElement evaluate:error];
|
||||
if (result) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:result];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
value = [value decimalNumberByAdding:currentSummand];
|
||||
[products addObject:currentProduct];
|
||||
|
||||
NSDecimalNumber *value = [NSDecimalNumber zero];
|
||||
for (MPParsedProduct *product in products) {
|
||||
value = [value decimalNumberByAdding:product.value];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user