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-07 16:45:31 +02:00

199 lines
7.0 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"
@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
{
#warning Implement Cache
// Empty Expression
if (self.expression.numberOfElements == 0) {
if (error) {
*error = MPParseError(0, @"Empty 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;
// 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];
if ([element isString]) {
MPParsedElement *parseResult = [parser parseElement:(NSString *)element
error:error];
if (parseResult) {
if (parseResult.definedVariable) {
if (error) {
*error = MPParseError(index, @"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 = [element evaluate:error];
if (result) {
currentSummand = [currentSummand decimalNumberByMultiplyingBy:result];
} else {
return nil;
}
}
}
// 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];
return value;
}
@end