Archived
1
This repository has been archived on 2022-08-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
mathpad/MathPad/MPExpressionEvaluator.m
2014-09-15 15:58:35 +02:00

114 lines
3.8 KiB
Objective-C

//
// 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<MPExpressionElement> element = [self.expression elementAtIndex:elementIndex];
if ([element isString]) {
id<MPParsedFactor> 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