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

129 lines
4.1 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"
@interface MPExpressionEvaluator ()
@property (readwrite, nonatomic, strong) NSString *definedVariable;
@end
@implementation MPExpressionEvaluator {
NSMutableDictionary *_variableBindings;
MPElementParser *parser;
}
- (id)initWithExpression:(MPExpression *)expression
{
self = [super init];
if (self) {
_expression = expression;
_variableBindings = [[NSMutableDictionary alloc] init];
parser = [[MPElementParser alloc] init];
}
return self;
}
#pragma mark Evaluating Expressions
- (NSDictionary *)variableBindings
{
return [_variableBindings copy];
}
- (void)bindValue:(NSDecimalNumber *)value toVariableName:(NSString *)name
{
[_variableBindings setObject:value
forKey:name];
}
- (void)unbindVariableName:(NSString *)name
{
[_variableBindings removeObjectForKey:name];
}
- (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]) {
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;
}
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 *functionValue = [(MPFunction *)element evaluate:error];
if (!functionValue) {
return nil;
}
if (!currentProduct) {
currentProduct = [[MPParsedProduct alloc] init];
}
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:functionValue]];
}
}
[products addObject:currentProduct];
NSDecimalNumber *value = [NSDecimalNumber zero];
for (MPParsedProduct *product in products) {
value = [value decimalNumberByAdding:product.value];
}
return value;
}
@end