Archived
1

Model Redesign: Added Reference Frames

Added Inverse Functions
UI Redesign
Cleaned Code
This commit is contained in:
Kim Wittenburg
2014-10-07 20:25:54 +02:00
parent 8f2f773909
commit 82259f87e2
40 changed files with 1124 additions and 998 deletions

View File

@@ -8,6 +8,13 @@
@import Foundation;
#import "NSString+MPExpressionElement.h"
#import "MPToken.h"
typedef NS_ENUM(NSUInteger, MPReferenceFrame) {
MPElementReferenceFrame,
MPSymbolReferenceFrame,
MPTokenReferenceFrame
};
@class MPExpression, MPFunction, MPRangePath, MPExpressionEvaluator, MPParseError;
@protocol MPExpressionElement;
@@ -127,6 +134,34 @@
@property (nonatomic, weak) MPFunction *parent;
/*!
@method rootExpression
@brief Returns the root expression from the receiver's expression tree.
@discussion The root expression is the ultimate parent of all expressions and
functions in the expression tree. A root expression does not have
a parent.
@return The root expression from the receiver's expression tree.
*/
- (MPExpression *)rootExpression;
/*!
@method indexPath
@brief Returns the index path of the receiver in the expression tree.
@discussion The index path is calculated by going up the expression tree
collecting the respective index of the receiver. The indexes are
expressed in the indexed reference frame. If any of the indexes
exceed the respective receiver's bounds a @c NSRangeException is
raised.
@return The index path of the receiver in the expression tree.
*/
- (NSIndexPath *)indexPath;
/*!
@method numberOfElements
@brief Returns the number of elements in the receiver.
@@ -139,7 +174,7 @@
@return The current number of elements in the receiver.
*/
- (NSUInteger)numberOfElements;
- (NSUInteger)countItemsInReferenceFrame:(MPReferenceFrame)referenceFrame;
/*!
@@ -160,7 +195,23 @@
@return The element at @c anIndex.
*/
- (id<MPExpressionElement>)elementAtIndex:(NSUInteger)anIndex;
- (id)itemAtIndex:(NSUInteger)anIndex
referenceFrame:(MPReferenceFrame)referenceFrame;
- (id<MPExpressionElement>)elementAtIndex:(NSUInteger)anIndex
referenceFrame:(MPReferenceFrame)referenceFrame;
/*!
@method indexOfElement:
@brief Returns the index of @c element or @c NSNotFound if it was not
found.
@param element
The element to find.
@return The index of @c element expressed in the indexed reference frame.
*/
- (NSUInteger)indexOfElement:(id<MPExpressionElement>)element;
/*!
@@ -185,7 +236,8 @@
The length of the returned array is equal to the length of the
specified range.
*/
- (NSArray *)elementsInIndexedRange:(NSRange)range;
- (NSArray *)itemsInRange:(NSRange)range
referenceFrame:(MPReferenceFrame)referenceFrame;
/*!
@@ -197,7 +249,51 @@
@return An array of all elements from the receiver.
*/
- (NSArray *)elements;
- (NSArray *)allItemsInReferenceFrame:(MPReferenceFrame)referenceFrame;
/*!
@method elementAtIndexPath:
@brief Returns the element at the specified index path.
@discussion This method @em walks down the expression tree (including
functions) using the specified index path and finds the
corresponding element. The returned object can be an @c NSString,
a @c MPFunction or an @c MPExpression depending on the element @c
indexPath points to. If any of the indexes exceed the bounds of
the respective receiver an @c NSRangeException is raised.
If the index path does not contain any indexes the receiver
itself is returned.
@param indexPath
The index path the required object is located at. The indexes are
expressed in the indexed reference frame.
@return The element located at @c indexPath. The element is not copied
before it is returned. Be aware of the fact that any mutations
made to the returned object are reflected in the receiver.
*/
- (id)elementAtIndexPath:(NSIndexPath *)indexPath;
- (NSUInteger)convertIndex:(NSUInteger)index
fromReferenceFrame:(MPReferenceFrame)fromReferenceFrame
toReferenceFrame:(MPReferenceFrame)toReferenceFrame;
- (NSUInteger)convertIndex:(NSUInteger)index
fromReferenceFrame:(MPReferenceFrame)fromReferenceFrame
toReferenceFrame:(MPReferenceFrame)toReferenceFrame
offset:(NSUInteger *)offset;
- (NSRange)convertRange:(NSRange)aRange
fromReferenceFrame:(MPReferenceFrame)fromReferenceFrame
toReferenceFrame:(MPReferenceFrame)toReferenceFrame;
- (NSRange)convertRange:(NSRange)aRange
fromReferenceFrame:(MPReferenceFrame)fromReferenceFrame
toReferenceFrame:(MPReferenceFrame)toReferenceFrame
leadingOffset:(NSUInteger *)leadingOffset
trailingOffset:(NSUInteger *)trailingOffset;
#pragma mark Mutating Expressions
@@ -228,9 +324,16 @@
The elements that should replace the symbols specified by @c
range.
*/
- (void)replaceSymbolsInRange:(NSRange)range
withElements:(NSArray *)elements;
- (void)replaceItemsInRange:(NSRange)range
referenceFrame:(MPReferenceFrame)referenceFrame
withElements:(NSArray *)elements;
- (MPExpression *)subexpressionFromIndex:(NSUInteger)from
referenceFrame:(MPReferenceFrame)referenceFrame;
- (MPExpression *)subexpressionToIndex:(NSUInteger)to
referenceFrame:(MPReferenceFrame)referenceFrame;
- (MPExpression *)subexpressionWithRange:(NSRange)range
referenceFrame:(MPReferenceFrame)referenceFrame;
#pragma mark Evaluating Expressions
@@ -256,17 +359,6 @@
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error;
/*!
@property evaluator
@brief Returns an object that can evaluate the receiver.
@discussion To just evaluate an expression it is recommended to send it an
@c evaluateWithError: message. You can however use this property
instead if you need more control over the evaluation process.
*/
@property (readonly, nonatomic, strong) MPExpressionEvaluator *evaluator;
#pragma mark Notifications
// All notification methods should create a new rangePath with the receiver's index added to the beginning of the path and then ascend the message to it's parent
@@ -291,8 +383,8 @@
The number of elements replacing the elements specified by @c
rangePath.
*/
- (void)didChangeElementsInIndexedRangePath:(MPRangePath *)rangePath
replacementLength:(NSUInteger)replacementLength;
- (void)didChangeElementsInRangePath:(MPRangePath *)rangePath
replacementLength:(NSUInteger)replacementLength;
#pragma mark Basic NSObject Methods
@@ -301,412 +393,63 @@
@end
/* --------------------------------------------------------------------------- */
/* Extension Methods */
/* --------------------------------------------------------------------------- */
@interface MPExpression (MPExpressionExtension)
@interface MPExpression (MPExpressionConvenience)
#pragma mark Querying Expressions
- (NSUInteger)countElements;
- (NSUInteger)countSymbols;
- (NSUInteger)countTokens;
/*!
@method length
@brief Returns the length of the receiver.
@discussion The length of an expression is calculated by going over each
element in the receiver and sending it a @c -length message. This
method should be used to determine the number of digits or
symbols in an expression.
The result of this method is expressed in the located reference
frame. The respective method for the indexed reference frame is
@c -numberOfSymbols.
@return The length of the receiver. This is the number of symbols in all
elements in the receiver where a function element is counted as a
single symbol.
*/
- (NSUInteger)length;
/*!
@method rootExpression
@brief Returns the root expression from the receiver's expression tree.
@discussion The root expression is the ultimate parent of all expressions and
functions in the expression tree. A root expression does not have
a parent.
@return The root expression from the receiver's expression tree.
*/
- (MPExpression *)rootExpression;
/*!
@method indexPath
@brief Returns the index path of the receiver in the expression tree.
@discussion The index path is calculated by going up the expression tree
collecting the respective index of the receiver. The indexes are
expressed in the indexed reference frame. If any of the indexes
exceed the respective receiver's bounds a @c NSRangeException is
raised.
@return The index path of the receiver in the expression tree.
*/
- (NSIndexPath *)indexPath;
// Subscripting is supported in the indexed reference frame
- (id)objectAtIndexedSubscript:(NSUInteger)idx;
#pragma mark Working With Expressions
/*!
@method elementAtLocation:
@brief Returns the element that is located at @c location.
@discussion This method finds an element in the located reference frame. If
@c location is greater or equal to the @c length of the receiver
a @c NSRangeException is raised.
@param location
The location of the element to find expressed in the located
reference frame.
@return The element located at @c location.
*/
- (id<MPExpressionElement>)elementAtLocation:(NSUInteger)location;
/*!
@method elementAtIndexPath:
@brief Returns the element at the specified index path.
@discussion This method @em walks down the expression tree (including
functions) using the specified index path and finds the
corresponding element. The returned object can be an @c NSString,
a @c MPFunction or an @c MPExpression depending on the element @c
indexPath points to. If any of the indexes exceed the bounds of
the respective receiver an @c NSRangeException is raised.
If the index path does not contain any indexes the receiver
itself is returned.
@param indexPath
The index path the required object is located at. The indexes are
expressed in the indexed reference frame.
@return The element located at @c indexPath. The element is not copied
before it is returned. Be aware of the fact that any mutations
made to the returned object are reflected in the receiver.
*/
- (id)elementAtIndexPath:(NSIndexPath *)indexPath;
/*!
@method elementsInIndexedRangePath:
@brief Returns the elements in the specified range path.
@discussion This method works similar to @c elementAtIndexPath: except that
it queries multiple elements at once.
@param rangePath
The range path the requested objects are located at. The complete
range path is expressed in the indexed reference frame.
@return An array of objects specified by the range path. The returned
elements are not copied before they are returned. Be aware that
any mutations made to the returned objects are reflected in the
receiver.
*/
- (NSArray *)elementsInIndexedRangePath:(MPRangePath *)rangePath;
/*!
@method indexOfElement:
@brief Returns the index of @c element or @c NSNotFound if it was not
found.
@param element
The element to find.
@return The index of @c element expressed in the indexed reference frame.
*/
- (NSUInteger)indexOfElement:(id<MPExpressionElement>)element;
#pragma mark Converting Between Indexes and Locations
/*!
@method indexOfElementAtLocation:offset:
@brief Calculates the index of the element the specified location points
to.
@discussion The @c location is in the located reference frame whereas the
returned value is an index. This method converts from the former
to the latter.
This method prefers higher indexes. This means that if the
returned @c offset would be equal to the length of the element at
the calculated index, insead index+1 is returned and the @c
offset is set to @c 0.
If the @c location exceeds the receiver's bounds a @c
NSRangeException will be raised.
@param location
The location of which you want the corresponding element index.
@param offset
An output parameter that gets set to the offst into the symbol
whose index is returned. If location for example points to the
symbol @c '2' in the string element @c '123' the offset @c would
be set to @c 1.
@return The index of the element the location points to.
*/
- (NSUInteger)indexOfElementAtLocation:(NSUInteger)location offset:(out NSUInteger *)offset;
/*!
@method locationOfElementAtIndex:
@brief Calculates the location of the element at @c index.
@discussion @c index is expressed in the indexed reference frame. Use this
method to convert an index into the located reference frame.
If the index exceeds the receiver's number of elements a @c
NSRangeException will be raised.
@param index
The index of the element that is to be converted into the length
reference frame.
@return The number of symbols (in the length reference frame) before the
element at @c index.
*/
- (NSUInteger)locationOfElementAtIndex:(NSUInteger)index;
/*!
@method indexedRangeForRange:
@brief Converts @c aRange from the located reference frame into the
indexed reference frame.
@discussion If the range exceeds the receiver's bounds a @c NSRangeException
is raised.
@param aRange
The range to be converted. Expressed in the located reference
frame.
@return @c aRange converted into the indexed reference frame.
*/
- (NSRange)indexedRangeForRange:(NSRange)aRange;
/*!
@method rangeForIndexedRange:
@brief Converts @c aRange from the indexed reference frame into the
located reference frame.
@discussion In the range exceeds the receiver's bounds a @c NSRangeException
is raised.
@param aRange
The range to be converted. Expressed in the indexed reference
frame.
@return @c aRange converted into the located reference frame.
*/
- (NSRange)rangeForIndexedRange:(NSRange)aRange;
- (id<MPExpressionElement>)elementAtIndex:(NSUInteger)index;
- (id<MPExpressionElement>)symbolAtIndex:(NSUInteger)index;
- (id<MPToken>)tokenAtIndex:(NSUInteger)index;
#pragma mark Mutating Expressions
- (MPExpression *)subexpressionFromIndex:(NSUInteger)from;
- (MPExpression *)subexpressionToIndex:(NSUInteger)to;
- (MPExpression *)subexpressionWithIndexedRange:(NSRange)range;
/*!
@method subexpressionFromLocation:
@brief Creates a new expression from the specified location (inclusive)
to the end of the receiver.
@method appendElement:
@brief Appends @c anElement to the receiver.
@discussion The elements in the newly created expression are copied to the
new expression. The location is specified in the located
reference frame.
If the given location exceeds the receiver's bounds a @c
NSRangeException is raised.
@param from
The first location to be included in the new expression.
@return A new expression from the given location to the end of the
receiver.
*/
- (MPExpression *)subexpressionFromLocation:(NSUInteger)from;
/*!
@method subexpressionToLocation:
@brief Creates a new expression from the beginning to the specified
location (exclusive).
@discussion The elements in the newly created expression are copied to the
new expression. The location is specified in the located
reference frame.
If the given location exceeds the receiver's bounds a @c
NSRangeException is raised.
@param to
The first location not to be included in the new expression (or
the length of the new expression).
@return A new expression with the first @c to symbols of the receiver.
*/
- (MPExpression *)subexpressionToLocation:(NSUInteger)to;
/*!
@method subexpressionWithRange:
@brief Creates a new expression with the symbols in the specified range.
@discussion The elements in the newly created expression are copied to the
new exoression. The range is specified in the located reference
frame.
If the given range exceeds the receiver's bounds a @c
NSRangeException is raised.
@param range
The range from which to create the new expression.
@return A new expression with the symbols in the specified range.
*/
- (MPExpression *)subexpressionWithRange:(NSRange)range;
- (void)replaceElementsInIndexedRange:(NSRange)range
withElements:(NSArray *)elements;
- (void)replaceSymbolsInRangePath:(MPRangePath *)rangePath
withElements:(NSArray *)elements;
/*!
@method appendElement:
@brief Appends @c anElement to the receiver.
@param anElement
The element to append to the receiver.
@param anElement
The element to append to the receiver.
*/
- (void)appendElement:(id<MPExpressionElement>)anElement;
/*!
@method appendElements:
@brief Appends the objects from @c elements to the receiver.
@method appendElements:
@brief Appends the objects from @c elements to the receiver.
@param elements
The elements to append to the receiver.
@param elements
The elements to append to the receiver.
*/
- (void)appendElements:(NSArray *)elements;
- (void)insertElement:(id<MPExpressionElement>)anElement
atIndex:(NSUInteger)index;
atIndex:(NSUInteger)index
referenceFrame:(MPReferenceFrame)referenceFrame;
- (void)insertElements:(NSArray *)elements
atIndex:(NSUInteger)index;
/*!
@method insertElement:atLocation:
@brief Inserts @c anElement at @c location.
@discussion The location is specified in the length reference frame.
If the given location exceeds the receiver's bounds a @c
NSRangeException is raised.
@param anElement
The element to be inserted into the receiver.
@param location
The location @c anElement should be inserted at.
*/
- (void)insertElement:(id<MPExpressionElement>)anElement
atLocation:(NSUInteger)location;
atIndex:(NSUInteger)index
referenceFrame:(MPReferenceFrame)referenceFrame;
/*!
@method insertElements:atLocation:
@brief Inserts the elements from @c elements at @c location.
@method deleteElementsInRange:
@brief Removes the elements specified by @c range from the receiver.
@discussion The location is specified in the length reference frame.
@discussion The range is specified in the length reference frame.
If the given location exceeds the receiver's bounds a @c
NSRangeException is raised.
If @c range exceeds the receiver's bounds a @c NSRangeException
is raised.
@param elements
The elements to be inserted into the receiver.
@param location
The location the elements in @c elements should be inserted into
the receiver.
@param range
The range to remove from the receiver.
*/
- (void)insertElements:(NSArray *)elements
atLocation:(NSUInteger)location;
- (void)deleteElementsInIndexedRange:(NSRange)range;
/*!
@method deleteElementsInRange:
@brief Removes the elements specified by @c range from the receiver.
@discussion The range is specified in the length reference frame.
If @c range exceeds the receiver's bounds a @c NSRangeException
is raised.
@param range
The range to remove from the receiver.
*/
- (void)deleteElementsInRange:(NSRange)range;
/*!
@method mutableElements
@brief Returns a proxy mutable array object that responds to all methods
defined by @c NSMutableArray.
@discussion Mutations on the proxy object also change the receiver. The proxy
object does not respond to coding methods. Copying the proxy
object will not duplicate it.
@return A proxy object that responds to all methods defined by @c
NSMutableArray.
*/
// - (NSMutableArray *)mutableElements;
/* Subscripting is supported for elements in the indexed reference frame */
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
- (void)deleteElementsInRange:(NSRange)range
referenceFrame:(MPReferenceFrame)referenceFrame;
@end