diff --git a/MathPad/MPExpression.m b/MathPad/MPExpression.m index 6c2d7e8..88176d5 100644 --- a/MathPad/MPExpression.m +++ b/MathPad/MPExpression.m @@ -22,7 +22,7 @@ -NSString *const MPIllegalElementException = @"MPIllegalElementException"; +NSString *const MPIllegalElementException = @"Illegal Element Exception"; NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptionElementKey"; @@ -30,15 +30,87 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio NSMutableArray * _elements; } +/*! + @method tokens + @brief Private method. Returns an array containing all tokens from the + receiver. + + @return All items in the @c MPTokenReferenceFrame. + */ - (NSArray *)tokens; + +/*! + @method validateElements: + @brief Private method. Checks whether all objects in the specified array + are valid expression elements. + + @discussion If an object is not valid a @c MPIllegalElementException is + raised. + + @param elements + The array of objects to be validated. + */ - (void)validateElements:(NSArray *)elements; + + +/*! + @method fixElements + @brief Private method. Restores consistency in the receiver after a + change was made. + */ - (void)fixElements; + +/*! + @method _replaceSymbolsInRange:withElements: + @brief Private method. Replaces the symbols in the specified range with + the elements from the @c elements array. + + @discussion This is the most primitive mutation method of the @c MPExpression + class. + + @param range + The range of symbols to be replaced. The range is specified in + the symbol reference frame. If the range exceeds the receiver's + bounds a @c NSRangeException is raised. + + @param elements + The elements that should replace the symbols in the specified + range. + */ - (void)_replaceSymbolsInRange:(NSRange)range withElements:(NSArray *)elements; + + +/*! + @method _splitElementsAtLocation:insertionIndex: + @brief Splits the receiver's elements at the specified @c location. + + @discussion The split location can be inside a string element. In that case + the string is replaced with two other smaller strings. + + Splitting the elements destroys the receiver's integrity. The + receiver of this message must also receive a @c -fixElements + message soon afterwards. + + @param location + The index where to split the elements. Specified in the symbol + reference frame. + + @param insertionIndex + Splitting elements may shift the indexes of the following + elements. This parameter is set to the index (specified in the + element reference frame) that should be used to insert a new + element at the location where the elements were previously + splitted. + + @return @c YES if a string element was split into two smaller strings, @c + NO if the split @c location corresponds to a location between two + elements. + */ - (BOOL)_splitElementsAtLocation:(NSUInteger)location - insertionIndex:(out NSUInteger *)insertionIndex; + insertionIndex:(NSUInteger *)insertionIndex; @end @@ -301,7 +373,7 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio - (NSUInteger)convertIndex:(NSUInteger)anIndex fromReferenceFrame:(MPReferenceFrame)fromReferenceFrame toReferenceFrame:(MPReferenceFrame)toReferenceFrame - offset:(out NSUInteger *)offset + offset:(NSUInteger *)offset { if (fromReferenceFrame == toReferenceFrame || anIndex == 0) { if (offset) { @@ -328,7 +400,6 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio symbolIndex += obj.range.length; *stop = idx >= anIndex - 1; }]; -// symbolIndex = [self.tokens[anIndex] range].location; break; } @@ -362,24 +433,23 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio case MPTokenReferenceFrame: { + NSUInteger totalLength = 0; NSUInteger tokenIndex = 0; - while (true) { - id token = self.tokens[tokenIndex++]; - if (NSMaxRange(token.range) < symbolIndex || token.range.location > symbolIndex) { - continue; - } - NSUInteger offsetInToken = anIndex - token.range.location; - if (offsetInToken == token.range.length) { - offsetInToken = 0; - tokenIndex++; - } - if (offset) { - *offset = offsetInToken; - } - return tokenIndex; + id token; + while (totalLength < symbolIndex) { + token = self.tokens[tokenIndex++]; + totalLength += token.range.length; } - // Should never get here - return 0; + --tokenIndex; + NSUInteger offsetInToken = token.range.length - totalLength + symbolIndex; + if (offsetInToken == token.range.length) { + offsetInToken = 0; + tokenIndex++; + } + if (offset) { + *offset = offsetInToken; + } + return tokenIndex; } } } @@ -497,7 +567,7 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio - (BOOL)_splitElementsAtLocation:(NSUInteger)location - insertionIndex:(out NSUInteger *)insertionIndex + insertionIndex:(NSUInteger *)insertionIndex { if (location == 0) { *insertionIndex = 0; @@ -562,7 +632,7 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio MPParsedExpression *parsedExpression = [self parse:&parsingErrors]; NSError *evaluationError; NSDecimalNumber *result = parsedExpression ? [parsedExpression evaluate:&evaluationError] : nil; - if (errors) { + if (errors && (parsedExpression || evaluationError)) { NSMutableArray *localErrors = [[NSMutableArray alloc] initWithCapacity:parsingErrors.count+1]; if (parsingErrors) { [localErrors addObjectsFromArray:parsingErrors];