custom NSExpression functions like sin(x)

551 Views Asked by At

I know how to add custom functions to NSNumber for NSExpression to work with it. But for use it i need to declarate a string like "FUNCTION(1, 'sin')". Is is any way to declarate it just like "sin(1)"?

2

There are 2 best solutions below

0
On BEST ANSWER

No, you cannot extend the syntax understood by NSExpression(format:).

For advanced expression parsing and evaluating, use 3rd party solutions such as DDMathParser.

0
On

The selected answer is, in my opinion, ridiculous. You can, of course, simply reformat your string to your desired custom function, no need to become dependent on an entire library.

In your case, something like the following would work just fine.

NSString *equation = @"2+sin(54.23+(2+sin(sin(3+5))))-4+(5-3)+cos(4)";//your equation here

NSArray *functionNames = @[@"sin", @"cos", @"tan"];//your supported functions here

for (NSString *functionName in functionNames) {
    
    NSString *functionPrefix = [NSString stringWithFormat:@"%@(", functionName];
    
    while ([equation containsString:functionPrefix]) {
        
        int parensLevel = 1;
        int functionParameterIndex = ((int)[equation rangeOfString:functionPrefix].location)+((int)functionPrefix.length);
        int characterIndex = functionParameterIndex;
        while (characterIndex < equation.length) {
            NSString *character = [equation substringWithRange:NSMakeRange(characterIndex, 1)];
            if ([character isEqualToString:@"("]) {
                parensLevel++;
            } else if ([character isEqualToString:@")"]) {
                parensLevel--;
            }
            if (parensLevel == 0) {
                break;
            }
            characterIndex++;
        }
        if (parensLevel != 0) {
            break;//parens weren't balanced, error handle as needed
        }
        
        NSString *functionParameter = [equation substringWithRange:NSMakeRange(functionParameterIndex, characterIndex-functionParameterIndex)];
        NSString *function = [NSString stringWithFormat:@"%@(%@)", functionName, functionParameter];
        
        equation = [equation stringByReplacingOccurrencesOfString:function withString:[NSString stringWithFormat:@"FUNCTION(%@,'%@')", functionParameter, functionName]];
        
    }
    
}

//po string = "2+FUNCTION(54.23+(2+FUNCTION(FUNCTION(3+5,'sin'),'sin')),'sin')-4+(5-3)+FUNCTION(4,'cos')"

I wrote this in Objective-C but it works converted to swift as well.