// // MPExpressionLexer.m // MathPad // // Created by Kim Wittenburg on 19.09.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import "MPExpressionTokenizer.h" #import "MPToken.h" #import "MPFunction+MPToken.h" #import "NSRegularExpression+MPParsingAdditions.h" #define MPRangeExists(range) (range.location != NSNotFound) @implementation MPExpressionTokenizer - (NSArray *)tokenizeExpression:(MPExpression *)expression { NSMutableArray *tokens = [[NSMutableArray alloc] init]; for (NSUInteger index = 0; index < expression.numberOfElements; index++) { id element = [expression elementAtIndex:index]; if ([element isFunction]) { [tokens addObject:element]; } else { [tokens addObjectsFromArray:[self tokenizeElement:(NSString *)element]]; } } return tokens; } - (NSArray *)tokenizeElement:(NSString *)element { NSUInteger lexLocation = 0; NSString *decimalSeparator = [NSRegularExpression escapedPatternForString:[[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]]; NSString *regexStringFormat = @"\\A(?:" @"(\\*)|" @"([+-](?:\\s*[+-])*)|" @"((?:\\d+(?:%@\\d+)?)|(?:\\s%@\\d+))|" @"(sin)|" @"(cos)|" @"(tan)|" @"([A-Za-z])|" @"(!)|" @"(=)|" @"(\\s)" @")"; NSString *regexString = [NSString stringWithFormat:regexStringFormat, decimalSeparator, decimalSeparator]; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:NULL]; NSMutableArray *tokens = [[NSMutableArray alloc] init]; while (lexLocation < element.length) { NSTextCheckingResult *match = [regex firstMatchInString:element fromIndex:lexLocation]; NSRange range = NSMakeRange(lexLocation, 1); MPTokenType tokenType = MPUnidentifiedToken; if (match) { NSRange multiplicationSymbolRange = [match rangeAtIndex:1]; NSRange operatorRange = [match rangeAtIndex:2]; NSRange numberRange = [match rangeAtIndex:3]; NSRange sinRange = [match rangeAtIndex:4]; NSRange cosRange = [match rangeAtIndex:5]; NSRange tanRange = [match rangeAtIndex:6]; NSRange variableRange = [match rangeAtIndex:7]; NSRange factorialRange = [match rangeAtIndex:8]; NSRange equalsRange = [match rangeAtIndex:9]; NSRange whitespaceRange = [match rangeAtIndex:10]; if (MPRangeExists(multiplicationSymbolRange)) { range = multiplicationSymbolRange; tokenType = MPMultiplicationSymbolToken; } else if (MPRangeExists(operatorRange)) { range = operatorRange; tokenType = MPOperatorListToken; } else if (MPRangeExists(numberRange)) { range = numberRange; tokenType = MPNumberToken; } else if (MPRangeExists(sinRange)) { range = sinRange; tokenType = MPSinToken; } else if (MPRangeExists(cosRange)) { range = cosRange; tokenType = MPCosToken; } else if (MPRangeExists(tanRange)) { range = tanRange; tokenType = MPTanToken; } else if (MPRangeExists(variableRange)) { range = variableRange; tokenType = MPVariableToken; } else if (MPRangeExists(factorialRange)) { range = factorialRange; tokenType = MPFactorialToken; } else if (MPRangeExists(equalsRange)) { range = equalsRange; tokenType = MPEqualsToken; } else if (MPRangeExists(whitespaceRange)) { range = whitespaceRange; tokenType = MPWhitespaceToken; } else { // Should not get here range = NSMakeRange(lexLocation, 1); tokenType = MPUnidentifiedToken; } } lexLocation = NSMaxRange(range); [tokens addObject:[[MPToken alloc] initWithTokenType:tokenType range:range inString:element]]; } return tokens; } @end