Added Evaluation Context and Math Rules
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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];
|
||||||
|
} else {
|
||||||
|
*error = MPParseError(NSMakeRange(((MPFunction *)element).range.location, 0), @"Implicit Multiplication not allowed");
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
[currentProduct addFactor:(MPFunction *)element];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
MathPad/MPMathRules.h
Normal file
28
MathPad/MPMathRules.h
Normal 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
95
MathPad/MPMathRules.m
Normal 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
|
||||||
Reference in New Issue
Block a user