// // MPExpressionEvaluator.m // MathPad // // Created by Kim Wittenburg on 31.08.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import "MPExpressionEvaluator.h" #import "MPExpression.h" #import "MPFunction.h" #import "MPParsedFactor.h" #import "MPFunction+MPParsedFactor.h" #import "MPMathRules.h" @interface MPExpressionEvaluator () @property (readwrite, nonatomic, strong) NSString *definedVariable; @end @implementation MPExpressionEvaluator { MPElementParser *parser; } - (id)initWithExpression:(MPExpression *)expression { self = [super init]; if (self) { _expression = expression; parser = [[MPElementParser alloc] init]; } return self; } #pragma mark Evaluating Expressions - (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error { return [self evaluateVariableDefinition:NO error:error]; } - (NSDecimalNumber *)evaluateVariableDefinition:(BOOL)flag error:(MPParseError *__autoreleasing *)error { // Empty Expression if (self.expression.numberOfElements == 0) { *error = MPParseError(NSMakeRange(0, 0), @"Expected Expression"); return nil; } NSMutableArray *products = [[NSMutableArray alloc] init]; MPParsedProduct *currentProduct = nil; for (NSUInteger elementIndex = 0; elementIndex < self.expression.numberOfElements; elementIndex++) { id element = [self.expression elementAtIndex:elementIndex]; if ([element isString]) { id nextFactor = nil; if (elementIndex < self.expression.numberOfElements - 1) { MPFunction *nextFunction = (MPFunction *)[self.expression elementAtIndex:elementIndex+1]; nextFactor = nextFunction; } 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 { if (!currentProduct) { currentProduct = [[MPParsedProduct alloc] init]; } else if ([MPMathRules sharedRules].allowsImplicitMultiplication) { [currentProduct addFactor:(MPFunction *)element]; } else { *error = MPParseError(NSMakeRange(((MPFunction *)element).range.location, 0), @"Implicit Multiplication not allowed"); return nil; } } } [products addObject:currentProduct]; NSDecimalNumber *value = [NSDecimalNumber zero]; for (MPParsedProduct *product in products) { NSDecimalNumber *productValue = [product evaluateWithError:error]; if (!productValue) { return nil; } value = [value decimalNumberByAdding:productValue]; } return value; } @end