116 lines
4.5 KiB
Objective-C
116 lines
4.5 KiB
Objective-C
//
|
|
// 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 <MPExpressionElement> 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 equalsRange = [match rangeAtIndex:8];
|
|
NSRange whitespaceRange = [match rangeAtIndex:9];
|
|
|
|
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(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
|