Implemented Evaluation
This commit is contained in:
@@ -9,11 +9,13 @@
|
||||
#import "MPExpressionEvaluator.h"
|
||||
#import "MPExpression.h"
|
||||
|
||||
#import "MPParsedElement.h"
|
||||
#import "MPMath.h"
|
||||
@interface MPExpressionEvaluator ()
|
||||
@property (readwrite, nonatomic, strong) NSString *definedVariable;
|
||||
@end
|
||||
|
||||
@implementation MPExpressionEvaluator {
|
||||
NSMutableDictionary *_variableBindings;
|
||||
MPElementParser *parser;
|
||||
}
|
||||
- (id)initWithExpression:(MPExpression *)expression
|
||||
{
|
||||
@@ -21,36 +23,176 @@
|
||||
if (self) {
|
||||
_expression = expression;
|
||||
_variableBindings = [[NSMutableDictionary alloc] init];
|
||||
parser = [[MPElementParser alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark Lexing
|
||||
- (MPParsedElement *)structuredRepresentationOfElementAtIndex:(NSUInteger)index
|
||||
{
|
||||
NSString *string = (NSString *)[self.expression elementAtIndex:index];
|
||||
YY_BUFFER_STATE buffer = yy_scan_string(string.UTF8String);
|
||||
yyparse();
|
||||
yy_delete_buffer(buffer);
|
||||
return [parseResult copy];
|
||||
}
|
||||
|
||||
#pragma mark Evaluating Expressions
|
||||
- (NSDictionary *)variableBindings
|
||||
{
|
||||
return [_variableBindings copy];
|
||||
}
|
||||
|
||||
- (void)bindValue:(double)value toVariableName:(NSString *)name
|
||||
- (void)bindValue:(NSDecimalNumber *)value toVariableName:(NSString *)name
|
||||
{
|
||||
[_variableBindings setObject:@(value)
|
||||
[_variableBindings setObject:value
|
||||
forKey:name];
|
||||
}
|
||||
|
||||
- (double)evaluateWithError:(NSError *__autoreleasing *)error
|
||||
- (void)unbindVariableName:(NSString *)name
|
||||
{
|
||||
MPParsedElement *element = [self structuredRepresentationOfElementAtIndex:0];
|
||||
return element.standaloneValue;
|
||||
[_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
|
||||
|
||||
Reference in New Issue
Block a user