Archived
1

Redesign of the Evaluation System

This commit is contained in:
Kim Wittenburg
2014-09-13 23:16:44 +02:00
parent a3e1cc6df4
commit b50c444578
20 changed files with 431 additions and 135 deletions

View File

@@ -25,13 +25,13 @@
- (NSArray *)parseElement:(NSString *)string
previousProduct:(MPParsedProduct *)previousProduct
nextFactor:(MPParsedFactor *)nextFactor
nextFactor:(id<MPParsedFactor>)nextFactor
definesVariable:(BOOL)flag
definedVariable:(NSString *__autoreleasing *)variableName
error:(out MPParseError *__autoreleasing *)error;
- (NSArray *)parseElement:(NSString *)string
previousProduct:(MPParsedProduct *)previousProduct
nextFactor:(MPParsedFactor *)nextFactor
nextFactor:(id<MPParsedFactor>)nextFactor
error:(out MPParseError *__autoreleasing *)error;
@end

View File

@@ -9,6 +9,11 @@
#import "MPElementParser.h"
#import "NSRegularExpression+MPParsingAdditions.h"
#import "MPParsedFactor.h"
#import "MPParsedNumber.h"
#import "MPParsedVariable.h"
#import "MPParsedOperator.h"
#define MPMultiplicationSymbol @"*"
@interface MPElementParser ()
@@ -24,11 +29,8 @@
- (NSRange)parseWhitespaces;
- (NSRange)parseMultiplicationSymbol;
- (NSRange)parseOperators;
- (NSUInteger)countOperatorsInRange:(NSRange)range
multiplicator:(out NSDecimalNumber *__autoreleasing *)multiplicator;
- (NSRange)parseNumber;
- (NSDecimalNumber *)numberInRange:(NSRange)range;
- (MPParsedOperator *)parseOperators;
- (MPParsedNumber *)parseNumber;
@end
@@ -84,7 +86,7 @@ static BOOL useUserDefaults;
- (NSArray *)parseElement:(NSString *)string
previousProduct:(MPParsedProduct *)previousProduct
nextFactor:(MPParsedFactor *)nextFactor
nextFactor:(id<MPParsedFactor>)nextFactor
error:(out MPParseError *__autoreleasing *)error
{
return [self parseElement:string
@@ -97,7 +99,7 @@ static BOOL useUserDefaults;
- (NSArray *)parseElement:(NSString *)string
previousProduct:(MPParsedProduct *)previousProduct
nextFactor:(MPParsedFactor *)nextFactor
nextFactor:(id<MPParsedFactor>)nextFactor
definesVariable:(BOOL)flag
definedVariable:(NSString *__autoreleasing *)variableName
error:(out MPParseError *__autoreleasing *)error
@@ -123,90 +125,86 @@ static BOOL useUserDefaults;
NSMutableArray *products = [[NSMutableArray alloc] init];
MPParsedProduct *currentProduct = previousProduct;
while (![self isAtEnd]) {
while (YES) {
[self parseWhitespaces];
NSRange multiplicationSymbolRange = [self parseMultiplicationSymbol];
BOOL hasMultiplicationSymbol = multiplicationSymbolRange.location != NSNotFound;
NSRange operatorsRange = [self parseOperators];
BOOL hasOperators = operatorsRange.location != NSNotFound;
MPParsedOperator *operators = [self parseOperators];
// NSRange functionRange = ...
// BOOL hasFunction = functionRange.location != NSNotFound;
NSRange numberRange = [self parseNumber];
BOOL hasNumber = numberRange.location != NSNotFound;
MPParsedNumber *number = [self parseNumber];
NSDecimalNumber *operatorMultiplicator;
NSUInteger operatorCount = [self countOperatorsInRange:operatorsRange
multiplicator:&operatorMultiplicator];
if (!hasNumber) {
if (!number.exists) {
if ([self isAtEnd] && nextFactor != nil) {
if (hasMultiplicationSymbol) {
if (operatorCount > self.maximumOperatorChainLengthInFunction) {
self.error = MPParseError(operatorsRange, @"Too many operators in multiplication.");
if (operators.numberOfOperators > self.maximumOperatorChainLengthInFunction) {
self.error = MPParseError(operators.range, @"Too many operators in multiplication.");
return nil;
}
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:operatorMultiplicator]];
} else if (hasOperators) {
if (operatorCount > self.maximumOperatorChainLength) {
self.error = MPParseError(operatorsRange, @"Too many operators.");
[currentProduct addFactor:operators];
} else if (operators.exists) {
if (operators.numberOfOperators > self.maximumOperatorChainLength) {
self.error = MPParseError(operators.range, @"Too many operators.");
return nil;
}
[products addObject:currentProduct];
currentProduct = [[MPParsedProduct alloc] init];
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:[[NSDecimalNumber alloc] initWithUnsignedInteger:operatorCount]]];
[currentProduct addFactor:operators];
} else if (self.allowsImplicitMultiplications) {
NSLog(@"Here I am");
if (!currentProduct) {
currentProduct = [[MPParsedProduct alloc] init];
}
} else {
NSLog(@"ERR");
self.error = MPParseError(NSMakeRange(self.parsePosition, 0), @"Implicit Multiplication not allowed.");
return nil;
}
break;
} else if ([self isAtEnd]) {
if (hasMultiplicationSymbol || operators.exists) {
self.error = MPParseError(NSMakeRange(self.parsePosition, 0), @"Unexpected End. Expected Number.");
return nil;
}
} else {
self.error = MPParseError(NSMakeRange(self.parsePosition, 1), @"Unexpected Symbol. Expected Number.");
return nil;
}
break;
} else {
NSDecimalNumber *number = [self numberInRange:numberRange];
NSDecimalNumber *value = [operatorMultiplicator decimalNumberByMultiplyingBy:number];
if (hasMultiplicationSymbol) {
if (currentProduct) {
if (operatorCount > self.maximumOperatorChainLengthInMultiplication) {
self.error = MPParseError(operatorsRange, @"Too many operators in multiplication.");
if (operators.numberOfOperators > self.maximumOperatorChainLengthInMultiplication) {
self.error = MPParseError(operators.range, @"Too many operators in multiplication.");
return nil;
}
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:value]];
[currentProduct addFactor:operators];
[currentProduct addFactor:number];
} else {
self.error = MPParseError(multiplicationSymbolRange, @"Unexpected Symbol. Expected Number.");
return nil;
}
} else if (hasOperators) {
if (operatorCount > self.maximumOperatorChainLength) {
self.error = MPParseError(operatorsRange, @"Too many operators.");
} else if (operators.exists) {
if (operators.numberOfOperators > self.maximumOperatorChainLength) {
self.error = MPParseError(operators.range, @"Too many operators.");
return nil;
}
if (currentProduct) {
[products addObject:currentProduct];
}
currentProduct = [[MPParsedProduct alloc] init];
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:value]];
currentProduct = [[MPParsedProduct alloc] initWithFactor:operators];
[currentProduct addFactor:number];
} else if (!currentProduct) {
currentProduct = [[MPParsedProduct alloc] init];
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:value]];
currentProduct = [[MPParsedProduct alloc] initWithFactor:number];
} else if (self.allowsImplicitMultiplications) {
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:value]];
[currentProduct addFactor:number];
} else {
self.error = MPParseError(NSMakeRange(numberRange.location, 0), @"Implicit Multiplication not allowed.");
self.error = MPParseError(NSMakeRange(number.range.location, 0), @"Implicit Multiplication not allowed.");
return nil;
}
}
@@ -276,7 +274,7 @@ static NSRegularExpression *multiplicationSymbolRegex;
}
static NSRegularExpression *operatorsRegex;
- (NSRange)parseOperators
- (MPParsedOperator *)parseOperators
{
if (!operatorsRegex) {
operatorsRegex = [NSRegularExpression regularExpressionWithPattern:@"\\A\\s*([+-](?:\\s*[+-])*)\\s*"
@@ -285,33 +283,18 @@ static NSRegularExpression *operatorsRegex;
}
NSTextCheckingResult *match = [operatorsRegex firstMatchInString:self.input
fromIndex:self.parsePosition];
if (match == nil) {
return NSMakeRange(NSNotFound, 0);
}
NSRange matchRange;
if (!match) {
matchRange = NSMakeRange(NSNotFound, 0);
} else {
self.parsePosition = NSMaxRange(match.range);
return [match rangeAtIndex:1];
matchRange = [match rangeAtIndex:1];
}
return [[MPParsedOperator alloc] initWithRange:matchRange
inString:self.input];
}
- (NSUInteger)countOperatorsInRange:(NSRange)range
multiplicator:(out NSDecimalNumber *__autoreleasing *)outMultiplicator
{
if (range.location == NSNotFound) {
*outMultiplicator = [NSDecimalNumber one];
return 0;
}
NSString *operatorsString = [self.input substringWithRange:range];
NSString *operators = [[operatorsString componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:@""];
NSInteger multiplicator = 1;
for (NSUInteger characterIndex; characterIndex < operators.length; characterIndex++) {
if ([[operators substringWithRange:NSMakeRange(characterIndex, 1)] isEqualToString:@"-"]) {
multiplicator *= -1;
}
}
*outMultiplicator = [[NSDecimalNumber alloc] initWithInteger:multiplicator];
return operators.length;
}
- (NSRange)parseNumber
- (MPParsedNumber *)parseNumber
{
NSString *decimalSeparatorRegexString = [NSRegularExpression escapedPatternForString:[[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]];
NSString *numberRegexFormat = [NSString stringWithFormat:@"\\A\\s*((?:\\d+(?:%@\\d+)?)|(?:%@\\d+))\\s*", decimalSeparatorRegexString, decimalSeparatorRegexString];
@@ -320,17 +303,15 @@ static NSRegularExpression *operatorsRegex;
error:NULL];
NSTextCheckingResult *match = [numberRegex firstMatchInString:self.input
fromIndex:self.parsePosition];
NSRange matchRange;
if (!match) {
return NSMakeRange(NSNotFound, 0);
}
matchRange = NSMakeRange(NSNotFound, 0);
} else {
self.parsePosition = NSMaxRange(match.range);
return [match rangeAtIndex:1];
}
- (NSDecimalNumber *)numberInRange:(NSRange)range
{
NSString *numberString = [self.input substringWithRange:range];
return [NSDecimalNumber decimalNumberWithString:numberString];
matchRange = [match rangeAtIndex:1];
}
return [[MPParsedNumber alloc] initWithRange:matchRange
inString:self.input];
}
@end

View File

@@ -0,0 +1,23 @@
//
// MPEvaluationContext.h
// MathPad
//
// Created by Kim Wittenburg on 12.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface MPEvaluationContext : NSObject
+ (MPEvaluationContext *)sharedContext;
- (void)push;
- (void)pop;
- (void)bindValue:(NSDecimalNumber *)value toName:(NSString *)variableName;
- (void)unbindVariableName:(NSString *)variableName;
- (NSDecimalNumber *)valueForVariableName:(NSString *)variableName;
@end

View File

@@ -0,0 +1,63 @@
//
// MPEvaluationContext.m
// MathPad
//
// Created by Kim Wittenburg on 12.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import "MPEvaluationContext.h"
@interface MPEvaluationContext ()
@property (nonatomic, strong) NSMutableArray *stack;
@end
@implementation MPEvaluationContext
static MPEvaluationContext *sharedContext;
+ (MPEvaluationContext *)sharedContext
{
if (!sharedContext) {
sharedContext = [[MPEvaluationContext alloc] init];
}
return sharedContext;
}
- (instancetype)init
{
self = [super init];
if (self) {
_stack = [[NSMutableArray alloc] init];
}
return self;
}
- (void)push
{
[self.stack addObject:[[NSMutableDictionary alloc] init]];
}
- (void)pop
{
[self.stack removeLastObject];
}
- (void)bindValue:(NSDecimalNumber *)value toName:(NSString *)variableName
{
NSMutableDictionary *currentBindings = self.stack.lastObject;
currentBindings[variableName] = value;
}
- (void)unbindVariableName:(NSString *)variableName
{
NSMutableDictionary *currentBindings = self.stack.lastObject;
[currentBindings removeObjectForKey:variableName];
}
- (NSDecimalNumber *)valueForVariableName:(NSString *)variableName
{
NSMutableDictionary *currentBindings = self.stack.lastObject;
return currentBindings[variableName];
}
@end

View File

@@ -16,15 +16,9 @@
// Do not instanciate yourself, use evaluator property of MPExpression instead
- (instancetype)initWithExpression:(MPExpression *)expression;
@property (readonly, nonatomic, weak) MPExpression *expression;
#pragma mark Evaluating Expressions
@property (readonly, nonatomic, strong) NSDictionary *variableBindings;
- (void)bindValue:(NSDecimalNumber *)value toVariableName:(NSString *)name;
- (void)unbindVariableName:(NSString *)name;
@property (readonly, nonatomic, strong) NSString *definedVariable;
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error;

View File

@@ -9,6 +9,8 @@
#import "MPExpressionEvaluator.h"
#import "MPExpression.h"
#import "MPFunction.h"
#import "MPParsedFactor.h"
#import "MPFunction+MPParsedFactor.h"
@interface MPExpressionEvaluator ()
@property (readwrite, nonatomic, strong) NSString *definedVariable;
@@ -16,7 +18,6 @@
@end
@implementation MPExpressionEvaluator {
NSMutableDictionary *_variableBindings;
MPElementParser *parser;
}
- (id)initWithExpression:(MPExpression *)expression
@@ -24,29 +25,12 @@
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];
@@ -68,14 +52,10 @@
id<MPExpressionElement> element = [self.expression elementAtIndex:elementIndex];
if ([element isString]) {
MPParsedFactor *nextFactor = nil;
id<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];
nextFactor = nextFunction;
}
NSArray *newProducts;
@@ -105,14 +85,10 @@
elementIndex++;
} else {
NSDecimalNumber *functionValue = [(MPFunction *)element evaluate:error];
if (!functionValue) {
return nil;
}
if (!currentProduct) {
currentProduct = [[MPParsedProduct alloc] init];
}
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:functionValue]];
[currentProduct addFactor:(MPFunction *)element];
}
}
@@ -120,7 +96,11 @@
NSDecimalNumber *value = [NSDecimalNumber zero];
for (MPParsedProduct *product in products) {
value = [value decimalNumberByAdding:product.value];
NSDecimalNumber *productValue = [product evaluateWithError:error];
if (!productValue) {
return nil;
}
value = [value decimalNumberByAdding:productValue];
}
return value;
}

View File

@@ -0,0 +1,14 @@
//
// MPFunction+MPParsedFactor.h
// MathPad
//
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import <MathKit/MathKit.h>
#import "MPParsedFactor.h"
@interface MPFunction (MPParsedFactor) <MPParsedFactor>
@end

View File

@@ -0,0 +1,30 @@
//
// MPFunction+MPParsedFactor.m
// MathPad
//
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import "MPFunction+MPParsedFactor.h"
@implementation MPFunction (MPParsedFactor)
- (instancetype)initWithRange:(NSRange)range
inString:(NSString *)string
{
return [self init];
}
- (BOOL)exists
{
return YES;
}
- (NSRange)range
{
NSUInteger selfIndex = [self.parent indexOfElement:self];
return NSMakeRange([self.parent locationOfElementAtIndex:selfIndex], 1);
}
@end

View File

@@ -38,7 +38,7 @@
- (id)elementAtIndexPath:(NSIndexPath *)indexPath;
#pragma mark Evaluating Functions
- (NSDecimalNumber *)evaluate:(MPParseError *__autoreleasing *)error;
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error;
#pragma mark Messages
- (void)didChangeElementsInRangePath:(MPRangePath *)rangePath

View File

@@ -82,7 +82,7 @@
}
#pragma mark Evaluating Functions
- (NSDecimalNumber *)evaluate:(MPParseError *__autoreleasing *)error
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error
{
return [NSDecimalNumber zero];
}

View File

@@ -2,21 +2,19 @@
// MPParsedFactor.h
// MathPad
//
// Created by Kim Wittenburg on 10.09.14.
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MPParseError.h"
@interface MPParsedFactor : NSObject
@protocol MPParsedFactor <NSObject>
+ (MPParsedFactor *)factorWithDecimalNumber:(NSDecimalNumber *)number;
+ (MPParsedFactor *)sinFactorWithFactor:(MPParsedFactor *)factor;
+ (MPParsedFactor *)cosFactorWithFactor:(MPParsedFactor *)factor;
+ (MPParsedFactor *)tanFactorWithFactor:(MPParsedFactor *)factor;
- (instancetype)initWithRange:(NSRange)range inString:(NSString *)string;
- (instancetype)initWithDecimalNumber:(NSDecimalNumber *)number;
- (NSDecimalNumber *)value;
- (NSRange)range;
- (BOOL)exists;
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error;
@end

16
MathPad/MPParsedNumber.h Normal file
View File

@@ -0,0 +1,16 @@
//
// MPParsedNumber.h
// MathPad
//
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MPParsedFactor.h"
@interface MPParsedNumber : NSObject <MPParsedFactor>
- (NSDecimalNumber *)number;
@end

42
MathPad/MPParsedNumber.m Normal file
View File

@@ -0,0 +1,42 @@
//
// MPParsedNumber.m
// MathPad
//
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import "MPParsedNumber.h"
@interface MPParsedNumber ()
@property (nonatomic) NSRange range;
@property (nonatomic, strong) NSDecimalNumber *number;
@end
@implementation MPParsedNumber
- (instancetype)initWithRange:(NSRange)range
inString:(NSString *)string
{
self = [super init];
if (self) {
_range = range;
if (range.location != NSNotFound) {
NSString *stringValue = [string substringWithRange:range];
_number = [NSDecimalNumber decimalNumberWithString:stringValue];
}
}
return self;
}
- (BOOL)exists
{
return self.range.location != NSNotFound;
}
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error
{
return self.number;
}
@end

View File

@@ -0,0 +1,17 @@
//
// MPParsedOperator.h
// MathPad
//
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MPParsedFactor.h"
@interface MPParsedOperator : NSObject <MPParsedFactor>
- (NSUInteger)numberOfOperators;
- (NSDecimalNumber *)multiplicator;
@end

View File

@@ -0,0 +1,54 @@
//
// MPParsedOperator.m
// MathPad
//
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import "MPParsedOperator.h"
@interface MPParsedOperator ()
@property (nonatomic) NSRange range;
@property (nonatomic) NSUInteger numberOfOperators;
@property (nonatomic, strong) NSDecimalNumber *multiplicator;
@end
@implementation MPParsedOperator
- (instancetype)initWithRange:(NSRange)range
inString:(NSString *)string
{
self = [super init];
if (self) {
_range = range;
if (range.location == NSNotFound) {
_multiplicator = [NSDecimalNumber one];
_numberOfOperators = 0;
} else {
NSString *stringValue = [string substringWithRange:range];
NSString *operators = [[stringValue componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:@""];
NSInteger multiplicator = 1;
for (NSUInteger characterIndex = 0; characterIndex < operators.length; characterIndex++) {
if ([[operators substringWithRange:NSMakeRange(characterIndex, 1)] isEqualToString:@"-"]) {
multiplicator *= -1;
}
}
_multiplicator = [[NSDecimalNumber alloc] initWithInteger:multiplicator];
_numberOfOperators = operators.length;
}
}
return self;
}
- (BOOL)exists
{
return self.range.location != NSNotFound;
}
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error
{
return self.multiplicator;
}
@end

View File

@@ -11,10 +11,12 @@
@interface MPParsedProduct : NSObject
- (instancetype)init; // designated initializer
- (instancetype)initWithFactor:(id<MPParsedFactor>)factor; // designated initializer.
@property (readonly, nonatomic, strong) NSArray *factors;
- (void)addFactor:(id<MPParsedFactor>)factor;
- (void)addFactor:(MPParsedFactor *)factor;
- (NSDecimalNumber *)value;
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error;
@end

View File

@@ -21,24 +21,37 @@
return self;
}
- (instancetype)initWithFactor:(id<MPParsedFactor>)factor
{
self = [super init];
if (self) {
_factors = [[NSMutableArray alloc] initWithObjects:factor, nil];
}
return self;
}
- (NSArray *)factors
{
return _factors;
}
- (void)addFactor:(MPParsedFactor *)factor
- (void)addFactor:(id<MPParsedFactor>)factor
{
[_factors addObject:factor];
}
- (NSDecimalNumber *)value
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error
{
if (_factors.count == 0) {
return [NSDecimalNumber zero];
}
NSDecimalNumber *value = [NSDecimalNumber one];
for (MPParsedFactor *factor in _factors) {
value = [value decimalNumberByMultiplyingBy:factor.value];
for (id<MPParsedFactor> factor in _factors) {
NSDecimalNumber *factorValue = [factor evaluateWithError:error];
if (!factorValue) {
return nil;
}
value = [value decimalNumberByMultiplyingBy:factorValue];
}
return value;
}

View File

@@ -0,0 +1,16 @@
//
// MPParsedVariable.h
// MathPad
//
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MPParsedFactor.h"
@interface MPParsedVariable : NSObject <MPParsedFactor>
- (NSString *)variableName;
@end

View File

@@ -0,0 +1,47 @@
//
// MPParsedVariable.m
// MathPad
//
// Created by Kim Wittenburg on 13.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import "MPParsedVariable.h"
#import "MPEvaluationContext.h"
@interface MPParsedVariable ()
@property (nonatomic) NSRange range;
@property (nonatomic, strong) NSString *variableName;
@end
@implementation MPParsedVariable
- (instancetype)initWithRange:(NSRange)range
inString:(NSString *)string
{
self = [super init];
if (self) {
_range = range;
if (range.location != NSNotFound) {
_variableName = [string substringWithRange:range];
}
}
return self;
}
- (BOOL)exists
{
return self.range.location != NSNotFound;
}
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error
{
NSDecimalNumber *value = [[MPEvaluationContext sharedContext] valueForVariableName:self.variableName];
if (!value) {
*error = MPParseError(self.range, @"Undefined Variable.");
return nil;
}
return value;
}
@end

View File

@@ -10,6 +10,7 @@
#import "MPExpression.h"
#import "MPExpressionEvaluator.h"
#import "MPEvaluationContext.h"
@implementation MPSumFunction
@@ -99,7 +100,7 @@
}
#pragma mark Evaluating Functions
- (NSDecimalNumber *)evaluate:(MPParseError *__autoreleasing *)error
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error
{
MPExpressionEvaluator *startEvaluator = self.startExpression.evaluator;
NSDecimalNumber *start = [startEvaluator evaluateVariableDefinition:YES error:error];
@@ -111,10 +112,12 @@
return nil;
}
[[MPEvaluationContext sharedContext] push];
MPExpressionEvaluator *sumEvaluator = self.sumExpression.evaluator;
NSDecimalNumber *value = [NSDecimalNumber zero];
for (NSDecimalNumber *iterator = start; [iterator compare:target] <= 0; iterator = [iterator decimalNumberByAdding:[[NSDecimalNumber alloc] initWithInteger:1]]) {
[sumEvaluator bindValue:iterator toVariableName:startEvaluator.definedVariable];
[[MPEvaluationContext sharedContext] bindValue:iterator toName:startEvaluator.definedVariable];
NSDecimalNumber *summand = [sumEvaluator evaluateWithError:error];
if (summand) {
value = [value decimalNumberByAdding:summand];
@@ -122,6 +125,9 @@
return nil;
}
}
[[MPEvaluationContext sharedContext] pop];
return value;
}