Archived
1

Implemented Evaluation

This commit is contained in:
Kim Wittenburg
2014-09-07 16:45:31 +02:00
parent 8df8317413
commit 21bfe221ba
13 changed files with 593 additions and 96 deletions

View File

@@ -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