DDMathParser の作成者はこちら...
Jonathan's answerを拡張するために、DDMathParser で完全に行う方法を次に示します。ただし、文字列をそのまま解析するには、2 つのことを行う必要があります。
if
まず、関数を作成する必要があります。
DDMathEvaluator *evaluator = [DDMathEvaluator sharedMathEvaluator];
[evaluator registerFunction:^DDExpression *(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError *__autoreleasing *error) {
if ([args count] == 3) {
DDExpression *condition = [args objectAtIndex:0];
DDExpression *resultExpression = nil;
NSNumber *conditionValue = [condition evaluateWithSubstitutions:vars evaluator:eval error:error];
if ([conditionValue boolValue] == YES) {
resultExpression = [args objectAtIndex:1];
} else {
resultExpression = [args objectAtIndex:2];
}
NSNumber *result = [resultExpression evaluateWithSubstitutions:vars evaluator:eval error:error];
return [DDExpression numberExpressionWithNumber:result];
}
return nil;
} forName:@"if"];
これにより、if()
3 つのパラメーターを受け取る関数が作成されます。最初のパラメーターがどのように評価されるかに応じて、2 番目または 3 番目のパラメーターの結果に評価されます。
もう 1 つ必要なことは、評価者に何height
をweight
意味するかを伝えることです。文字で始まらないため、$
変数ではなく関数として解釈されます。で始まる場合は$
、次のように評価するのと同じくらい簡単です。
NSString *expression = @"if(($height > 0), ($weight+ 2 ), ( $weight-1 ) )";
NSDictionary *variables = @{@"height" : @42, @"weight" : @13};
NSNumber *result = [expression evaluateWithSubstitutions:variables evaluator:evaluator error:nil];
ただし、これらはa で始まらない$
ため、関数です。つまり、関数の評価結果をエバリュエーターに伝える必要があります。の場合と同様に、height
との両方に関数を作成することで、これを行うことができます。weight
if
[evaluator registerFunction:^DDExpression *(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError **error) {
return [DDExpression numberExpressionWithNumber:@42];
} forName:@"height"];
または、もう少し動的にして のfunctionResolver
ブロックを使用することもできますDDMathEvaluator
。これは、ブロック (woooooo) を返すブロックであり、次のようになります。
NSDictionary *values = @{@"height": @42, @"weight": @13};
[evaluator setFunctionResolver:^DDMathFunction(NSString *name) {
DDMathFunction f = ^(NSArray *args, NSDictionary *vars, DDMathEvaluator *eval, NSError **error) {
NSNumber *n = [values objectForKey:name];
if (!n) { n = @0; }
return [DDExpression numberExpressionWithNumber:n];
};
return f;
}];
これらの 2 つの部分 (およびの値を登録if
して提供する) があれば、次のことができます。height
weight
NSString *expression = @"if((height > 0), (weight+ 2 ), ( weight-1 ) )";
NSNumber *result = [expression evaluateWithSubstitutions:nil evaluator:evaluator error:nil];
...そして の適切な結果を返します@15
。
(不明な関数が提供された変数値にフォールバックできるようにする計画がDDMathParser
ありますが、まだ完全には完了していません)