Archived
1

Added Evaluation Context and Math Rules

This commit is contained in:
Kim Wittenburg
2014-09-15 15:58:35 +02:00
parent 6573cd1b5c
commit 3cf2006af7
6 changed files with 191 additions and 41 deletions

View File

@@ -14,15 +14,6 @@
@interface MPElementParser : NSObject @interface MPElementParser : NSObject
+ (BOOL)isUsingDefaultValuesFromUserDefaults;
+ (void)setUsingDefaultValuesFromUserDefaults:(BOOL)flag;
@property (nonatomic) BOOL allowsImplicitMultiplications; // wether 2 3 is equal to 6 or error
// Default value uses the key "..." in NSUserDefaults or ... if the key does not exist.
@property (nonatomic) NSUInteger maximumOperatorChainLength; // +--++-5 -> Chain length: 6, 2 default (sign of number and operator) (0 is invalid?)
@property (nonatomic) NSUInteger maximumOperatorChainLengthInMultiplication; // Default: 1, 0 means actually 0
@property (nonatomic) NSUInteger maximumOperatorChainLengthInFunction; // For sin, cos, tan. Default: 1
- (NSArray *)parseElement:(NSString *)string - (NSArray *)parseElement:(NSString *)string
previousProduct:(MPParsedProduct *)previousProduct previousProduct:(MPParsedProduct *)previousProduct
nextFactor:(id<MPParsedFactor>)nextFactor nextFactor:(id<MPParsedFactor>)nextFactor

View File

@@ -8,6 +8,7 @@
#import "MPElementParser.h" #import "MPElementParser.h"
#import "NSRegularExpression+MPParsingAdditions.h" #import "NSRegularExpression+MPParsingAdditions.h"
#import "MPMathRules.h"
#import "MPParsedFactor.h" #import "MPParsedFactor.h"
#import "MPParsedNumber.h" #import "MPParsedNumber.h"
@@ -21,6 +22,11 @@
@property (nonatomic) NSString *input; @property (nonatomic) NSString *input;
@property (nonatomic) NSUInteger parsePosition; @property (nonatomic) NSUInteger parsePosition;
- (BOOL)allowsImplicitMultiplication;
- (BOOL)maximumOperatorChainLength;
- (BOOL)maximumOperatorChainLengthInMultiplication;
- (BOOL)maximumOperatorChainLengthInFunction;
- (void)setError:(MPParseError *)error; - (void)setError:(MPParseError *)error;
- (BOOL)isAtEnd; - (BOOL)isAtEnd;
@@ -30,7 +36,9 @@
- (NSRange)parseWhitespaces; - (NSRange)parseWhitespaces;
- (NSRange)parseMultiplicationSymbol; - (NSRange)parseMultiplicationSymbol;
- (MPParsedOperator *)parseOperators; - (MPParsedOperator *)parseOperators;
- (id<MPParsedFactor>)parseValue;
- (MPParsedNumber *)parseNumber; - (MPParsedNumber *)parseNumber;
- (MPParsedVariable *)parseVariable;
@end @end
@@ -38,36 +46,25 @@
MPParseError *__autoreleasing *outError; MPParseError *__autoreleasing *outError;
} }
static BOOL useUserDefaults; #pragma mark Helpers
- (BOOL)allowsImplicitMultiplication
#pragma mark Creation Methods
+ (void)initialize
{ {
useUserDefaults = YES; return [MPMathRules sharedRules].allowsImplicitMultiplication;
} }
- (instancetype)init - (BOOL)maximumOperatorChainLength
{ {
self = [super init]; return [MPMathRules sharedRules].maximumOperatorChainLength;
if (self) {
self.allowsImplicitMultiplications = NO;
self.maximumOperatorChainLength = 2;
self.maximumOperatorChainLengthInMultiplication = 1;
}
return self;
} }
#pragma mark Properties - (BOOL)maximumOperatorChainLengthInFunction
+ (BOOL)isUsingDefaultValuesFromUserDefaults
{ {
return useUserDefaults; return [MPMathRules sharedRules].maximumOperatorChainLengthInFunction;
} }
+ (void)setUsingDefaultValuesFromUserDefaults:(BOOL)flag - (BOOL)maximumOperatorChainLengthInMultiplication
{ {
useUserDefaults = flag; return [MPMathRules sharedRules].maximumOperatorChainLengthInMultiplication;
} }
#pragma mark Parsing Methods #pragma mark Parsing Methods
@@ -136,10 +133,10 @@ static BOOL useUserDefaults;
// NSRange functionRange = ... // NSRange functionRange = ...
// BOOL hasFunction = functionRange.location != NSNotFound; // BOOL hasFunction = functionRange.location != NSNotFound;
MPParsedNumber *number = [self parseNumber]; id<MPParsedFactor> value = [self parseValue];
if (!number.exists) { if (!value.exists) {
if ([self isAtEnd] && nextFactor != nil) { if ([self isAtEnd] && nextFactor != nil) {
if (hasMultiplicationSymbol) { if (hasMultiplicationSymbol) {
if (operators.numberOfOperators > self.maximumOperatorChainLengthInFunction) { if (operators.numberOfOperators > self.maximumOperatorChainLengthInFunction) {
@@ -155,13 +152,11 @@ static BOOL useUserDefaults;
[products addObject:currentProduct]; [products addObject:currentProduct];
currentProduct = [[MPParsedProduct alloc] init]; currentProduct = [[MPParsedProduct alloc] init];
[currentProduct addFactor:operators]; [currentProduct addFactor:operators];
} else if (self.allowsImplicitMultiplications) { } else if (self.allowsImplicitMultiplication) {
NSLog(@"Here I am");
if (!currentProduct) { if (!currentProduct) {
currentProduct = [[MPParsedProduct alloc] init]; currentProduct = [[MPParsedProduct alloc] init];
} }
} else { } else {
NSLog(@"ERR");
self.error = MPParseError(NSMakeRange(self.parsePosition, 0), @"Implicit Multiplication not allowed."); self.error = MPParseError(NSMakeRange(self.parsePosition, 0), @"Implicit Multiplication not allowed.");
return nil; return nil;
} }
@@ -184,7 +179,7 @@ static BOOL useUserDefaults;
return nil; return nil;
} }
[currentProduct addFactor:operators]; [currentProduct addFactor:operators];
[currentProduct addFactor:number]; [currentProduct addFactor:value];
} else { } else {
self.error = MPParseError(multiplicationSymbolRange, @"Unexpected Symbol. Expected Number."); self.error = MPParseError(multiplicationSymbolRange, @"Unexpected Symbol. Expected Number.");
return nil; return nil;
@@ -198,13 +193,13 @@ static BOOL useUserDefaults;
[products addObject:currentProduct]; [products addObject:currentProduct];
} }
currentProduct = [[MPParsedProduct alloc] initWithFactor:operators]; currentProduct = [[MPParsedProduct alloc] initWithFactor:operators];
[currentProduct addFactor:number]; [currentProduct addFactor:value];
} else if (!currentProduct) { } else if (!currentProduct) {
currentProduct = [[MPParsedProduct alloc] initWithFactor:number]; currentProduct = [[MPParsedProduct alloc] initWithFactor:value];
} else if (self.allowsImplicitMultiplications) { } else if (self.allowsImplicitMultiplication) {
[currentProduct addFactor:number]; [currentProduct addFactor:value];
} else { } else {
self.error = MPParseError(NSMakeRange(number.range.location, 0), @"Implicit Multiplication not allowed."); self.error = MPParseError(NSMakeRange(value.range.location, 0), @"Implicit Multiplication not allowed.");
return nil; return nil;
} }
} }
@@ -294,6 +289,18 @@ static NSRegularExpression *operatorsRegex;
inString:self.input]; inString:self.input];
} }
- (id<MPParsedFactor>)parseValue
{
MPParsedNumber *parsedNumber = [self parseNumber];
if (!parsedNumber.exists) {
MPParsedVariable *parsedVariable = [self parseVariable];
if (parsedVariable.exists) {
return parsedVariable;
}
}
return parsedNumber;
}
- (MPParsedNumber *)parseNumber - (MPParsedNumber *)parseNumber
{ {
NSString *decimalSeparatorRegexString = [NSRegularExpression escapedPatternForString:[[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]]; NSString *decimalSeparatorRegexString = [NSRegularExpression escapedPatternForString:[[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]];
@@ -314,4 +321,25 @@ static NSRegularExpression *operatorsRegex;
inString:self.input]; inString:self.input];
} }
static NSRegularExpression *variableRegex;
- (MPParsedVariable *)parseVariable
{
if (!variableRegex) {
variableRegex = [NSRegularExpression regularExpressionWithPattern:@"\\A\\s*([A-Za-z])\\s*"
options:0
error:NULL];
}
NSTextCheckingResult *match = [variableRegex firstMatchInString:self.input
fromIndex:self.parsePosition];
NSRange matchRange;
if (!match) {
matchRange = NSMakeRange(NSNotFound, 0);
} else {
self.parsePosition = NSMaxRange(match.range);
matchRange = [match rangeAtIndex:1];
}
return [[MPParsedVariable alloc] initWithRange:matchRange
inString:self.input];
}
@end @end

View File

@@ -25,6 +25,9 @@ static MPEvaluationContext *sharedContext;
- (instancetype)init - (instancetype)init
{ {
if (sharedContext) {
return sharedContext;
}
self = [super init]; self = [super init];
if (self) { if (self) {
_stack = [[NSMutableArray alloc] init]; _stack = [[NSMutableArray alloc] init];

View File

@@ -11,6 +11,7 @@
#import "MPFunction.h" #import "MPFunction.h"
#import "MPParsedFactor.h" #import "MPParsedFactor.h"
#import "MPFunction+MPParsedFactor.h" #import "MPFunction+MPParsedFactor.h"
#import "MPMathRules.h"
@interface MPExpressionEvaluator () @interface MPExpressionEvaluator ()
@property (readwrite, nonatomic, strong) NSString *definedVariable; @property (readwrite, nonatomic, strong) NSString *definedVariable;
@@ -87,8 +88,12 @@
} else { } else {
if (!currentProduct) { if (!currentProduct) {
currentProduct = [[MPParsedProduct alloc] init]; currentProduct = [[MPParsedProduct alloc] init];
} } else if ([MPMathRules sharedRules].allowsImplicitMultiplication) {
[currentProduct addFactor:(MPFunction *)element]; [currentProduct addFactor:(MPFunction *)element];
} else {
*error = MPParseError(NSMakeRange(((MPFunction *)element).range.location, 0), @"Implicit Multiplication not allowed");
return nil;
}
} }
} }

28
MathPad/MPMathRules.h Normal file
View File

@@ -0,0 +1,28 @@
//
// MPMathRules.h
// MathPad
//
// Created by Kim Wittenburg on 14.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT NSString *MPMathRulesAllowsImplicitMultiplicationKey;
FOUNDATION_EXPORT NSString *MPMathRulesMaximumOperatorChainLengthKey;
FOUNDATION_EXPORT NSString *MPMathRulesMaximumOperatorChainLengthInMultiplicationKey;
FOUNDATION_EXPORT NSString *MPMathRulesMaximumOperatorChainLengthInFunctionKey;
@interface MPMathRules : NSObject
+ (MPMathRules *)sharedRules;
@property (nonatomic, getter = isUsingUserDefaultValues) BOOL usingUserDefaultValues;
@property (nonatomic) BOOL allowsImplicitMultiplication; // wether 2 3 is equal to 6 or error
// Default value uses the key "..." in NSUserDefaults or ... if the key does not exist.
@property (nonatomic) NSUInteger maximumOperatorChainLength; // +--++-5 -> Chain length: 6, 2 default (sign of number and operator) (0 is invalid?)
@property (nonatomic) NSUInteger maximumOperatorChainLengthInMultiplication; // Default: 1, 0 means actually 0
@property (nonatomic) NSUInteger maximumOperatorChainLengthInFunction; // For sin, cos, tan. Default: 1
@end

95
MathPad/MPMathRules.m Normal file
View File

@@ -0,0 +1,95 @@
//
// MPMathRules.m
// MathPad
//
// Created by Kim Wittenburg on 14.09.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
#import "MPMathRules.h"
NSString *MPMathRulesAllowsImplicitMultiplicationKey = @"MPMathRulesAllowsImplicitMultiplicationKey";
NSString *MPMathRulesMaximumOperatorChainLengthKey = @"MPMathRulesMaximumOperatorChainLengthKey";
NSString *MPMathRulesMaximumOperatorChainLengthInMultiplicationKey = @"MPMathRulesMaximumOperatorChainLengthInMultiplicationKey";
NSString *MPMathRulesMaximumOperatorChainLengthInFunctionKey = @"MPMathRulesMaximumOperatorChainLengthInFunctionKey";
@implementation MPMathRules
static MPMathRules *sharedRules;
+ (MPMathRules *)sharedRules
{
if (!sharedRules) {
sharedRules = [[MPMathRules alloc] init];
}
return sharedRules;
}
- (instancetype)init
{
if (sharedRules) {
return sharedRules;
}
self = [super init];
if (self) {
_usingUserDefaultValues = YES;
NSNumber *userDefaultsAllowImplicitMultiplication = [[NSUserDefaults standardUserDefaults] objectForKey:MPMathRulesAllowsImplicitMultiplicationKey];
NSNumber *userDefaultsMaximumOperatorChainLength = [[NSUserDefaults standardUserDefaults] objectForKey:MPMathRulesMaximumOperatorChainLengthKey];
NSNumber *userDefaultsMaximumOperatorChainLengthInMultiplication = [[NSUserDefaults standardUserDefaults] objectForKey:MPMathRulesMaximumOperatorChainLengthInMultiplicationKey];
NSNumber *userDefaultsMaximumOperatorChainLengthInFunction = [[NSUserDefaults standardUserDefaults] objectForKey:MPMathRulesMaximumOperatorChainLengthInFunctionKey];
_allowsImplicitMultiplication = userDefaultsAllowImplicitMultiplication != nil ? userDefaultsAllowImplicitMultiplication.boolValue : NO;
_maximumOperatorChainLength = userDefaultsMaximumOperatorChainLength != nil ? userDefaultsMaximumOperatorChainLength.unsignedIntegerValue : 2;
_maximumOperatorChainLengthInMultiplication = userDefaultsMaximumOperatorChainLengthInMultiplication != nil ? userDefaultsMaximumOperatorChainLengthInMultiplication.unsignedIntegerValue : 1;
_maximumOperatorChainLengthInFunction = userDefaultsMaximumOperatorChainLengthInFunction != nil ? userDefaultsMaximumOperatorChainLengthInFunction.unsignedIntegerValue : 1;
}
return self;
}
- (void)setUsingUserDefaultValues:(BOOL)usingUserDefaultValues
{
_usingUserDefaultValues = usingUserDefaultValues;
// Save the current values
self.allowsImplicitMultiplication = self.allowsImplicitMultiplication;
self.maximumOperatorChainLength = self.maximumOperatorChainLength;
self.maximumOperatorChainLengthInMultiplication = self.maximumOperatorChainLengthInMultiplication;
self.maximumOperatorChainLengthInFunction = self.maximumOperatorChainLengthInFunction;
}
- (void)setAllowsImplicitMultiplication:(BOOL)allowsImplicitMultiplication
{
_allowsImplicitMultiplication = allowsImplicitMultiplication;
if (self.isUsingUserDefaultValues) {
[[NSUserDefaults standardUserDefaults] setBool:allowsImplicitMultiplication
forKey:MPMathRulesAllowsImplicitMultiplicationKey];
}
}
- (void)setMaximumOperatorChainLength:(NSUInteger)maximumOperatorChainLength
{
_maximumOperatorChainLength = maximumOperatorChainLength;
if (self.isUsingUserDefaultValues) {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedInteger:maximumOperatorChainLength]
forKey:MPMathRulesMaximumOperatorChainLengthKey];
}
}
- (void)setMaximumOperatorChainLengthInMultiplication:(NSUInteger)maximumOperatorChainLengthInMultiplication
{
_maximumOperatorChainLengthInMultiplication = maximumOperatorChainLengthInMultiplication;
if (self.isUsingUserDefaultValues) {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedInteger:maximumOperatorChainLengthInMultiplication]
forKey:MPMathRulesMaximumOperatorChainLengthInMultiplicationKey];
}
}
- (void)setMaximumOperatorChainLengthInFunction:(NSUInteger)maximumOperatorChainLengthInFunction
{
_maximumOperatorChainLengthInFunction = maximumOperatorChainLengthInFunction;
if (self.isUsingUserDefaultValues) {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedInteger:maximumOperatorChainLengthInFunction]
forKey:MPMathRulesMaximumOperatorChainLengthInFunctionKey];
}
}
@end