Archived
1

Added Documentation

This commit is contained in:
Kim Wittenburg
2014-12-17 22:04:49 +01:00
parent 8f1f730358
commit 7f6ee6e118
31 changed files with 1141 additions and 533 deletions

View File

@@ -7,6 +7,7 @@
// //
/*! /*!
@header @header
The <code>MPExpression</code> class is used to represent a mathematical The <code>MPExpression</code> class is used to represent a mathematical
@@ -21,22 +22,24 @@
elements. String elements are represented by the <code>NSString</code> class. elements. String elements are represented by the <code>NSString</code> class.
In a valid expression string elements can only contain ASCII valid characters. In a valid expression string elements can only contain ASCII valid characters.
(and some other special characters) that make sense in a mathematical context. (and some other special characters) that make sense in a mathematical context.
Functions are represented by the <code>MPFunction</code> class. Functions Functions are represented by the <code>@link
represent everything beyond simple text (such as powers, parenthesis and roots). //apple_ref/occ/cl/MPFunction@/link</code> class. Functions represent everything
beyond simple text (such as powers, parenthesis and roots).
An expression should be pictured as a sequence of symbols that can either be An expression should be pictured as a sequence of symbols that can either be
characters or functions. For the purposes of easier processing of expressions characters or functions. For the purposes of easier processing of expressions
it is possible to access complete string or function elements. Also there is a it is possible to access complete string or function elements. Also there is a
third way of accessing an expression's contents: You can query individual tokens third way of accessing an expression's contents: You can query individual tokens
of an expression. Tokens represent logical units inside an expression. For more of an expression. Tokens represent logical units inside an expression. For more
information on tokens see the <code>MPToken</code> class. information on tokens see the documentation for <code>@link
//apple_ref/doc/header/MPToken.h MPToken@/link</code>.
<h2>The Expression Tree</h2> <h2>The Expression Tree</h2>
Like expressions functions can likewise have expressions as elements (also Like expressions functions can likewise have expressions as elements (also
called <i>children</i> in this context). Both expressions and functions are called <i>children</i> in this context). Both expressions and functions are
mutable. Through this organization expression are organized in a tree-like mutable. Through this organization expression are organized in a tree-like
structure called the <i>expression tree</i>. See <code>MPFunction</code> for structure called the <i>expression tree</i>. See <code>@link
details. //apple_ref/occ/cl/MPFunction@/link</code> for details.
<h2>Terminology</h2> <h2>Terminology</h2>
@@ -44,17 +47,19 @@
expression's contents: expression's contents:
<b>Element:</b><br /> <b>Element:</b><br />
An element is either an instance of the <code>NSString</code> or <code> An element is either an instance of the <code>NSString</code> or <code> @link
MPFunction</code> class. String elements can be multiple characters long. For //apple_ref/occ/cl/MPFunction@/link</code> class. String elements can be
example the expression <code>4+2²</code> consists of one string element multiple characters long. For example the expression <code>4+2²</code> consists
(<code>"4+2"</code>) and one function element (the square function). All of one string element (<code>"4+2"</code>) and one function element (the square
elements conform to the <code>MPExpressionElement</code> protocol. function). All elements conform to the <code>MPExpressionElement</code>
protocol.
<b>Token:</b><br /> <b>Token:</b><br />
Tokens are logical units within an expression. For example the expression Tokens are logical units within an expression. For example the expression
<code>4+2²</code> consists of 4 tokens: A number token (<code>4</code>), a plus <code>4+2²</code> consists of 4 tokens: A number token (<code>4</code>), a plus
sign token (<code>+</code>), another number (<code>2</code>) and a power token sign token (<code>+</code>), another number (<code>2</code>) and a power token
(the square function). All tokens conform to the <code>MPToken</code> protocol. (the square function). All tokens conform to the <code>@link
//apple_ref/occ/intf/MPToken@/link</code> protocol.
<b>Symbol:</b><br /> <b>Symbol:</b><br />
Symbols are the smallest possible part of an expression. A symbol is either a Symbols are the smallest possible part of an expression. A symbol is either a
@@ -72,7 +77,7 @@
A reference frame is a way to specify what an <i>item</i> is supposed to mean in A reference frame is a way to specify what an <i>item</i> is supposed to mean in
a specific context. It can either be an <i>element</i>, a <i>symbol</i> or a a specific context. It can either be an <i>element</i>, a <i>symbol</i> or a
<i>token</i>. For more information about reference frames see <i>token</i>. For more information about reference frames see
<code>MPReferenceFrame</code>. <code>@link MPReferenceFrame@/link</code>.
<b>Children:</b><br /> <b>Children:</b><br />
Children are sub-elements of functions. The term <i>children</i> normally refers Children are sub-elements of functions. The term <i>children</i> normally refers
@@ -81,29 +86,84 @@
This terminology is consistent within the MathKit Expression System. Because This terminology is consistent within the MathKit Expression System. Because
symbols are the smalles possible unit of measurement elements and tokens both symbols are the smalles possible unit of measurement elements and tokens both
consist of one or more symbols. Similarly elements consist of one or more consist of one or more symbols. Similarly elements consist of one or more
tokens. You can convert between different reference frames using one the tokens. You can convert between different reference frames using the following
following methods: methods:
<pre> <ul>
@textblock <li><code>@link convertIndex:fromReferenceFrame:toReferenceFrame:@/link</code></li>
- convertIndexFromReferenceFrame:toReferenceFrame: <li><code>@link convertIndex:fromReferenceFrame:toReferenceFrame:offset:@/link</code></li>
- convertIndexFromReferenceFrame:toReferenceFrame:offset: <li><code>@link convertRange:fromReferenceFrame:toReferenceFrame:@/link</code></li>
@/textblock <li><code>@link convertRange:fromReferenceFrame:toReferenceFrame:leadingOffset:trailingOffset:@/link</code></li>
</pre> </ul>
<h2>Evaluating Expressions</h2> <h2>Evaluating Expressions</h2>
A <code>MPExpression</code> instance can not evaluate itself. There are however A <code>MPExpression</code> instance can not evaluate itself. There are however
the <code>-parse:</code> and the <code>@link parse:@/link</code> and
<code>-parseExpectingVariableDefinition:errors:</code> methods. These parse and <code>@link parseExpectingVariable:errors:@/link</code> methods. These parse and
thereby convert a <code>MPExpression</code> instance into a thereby convert a <code>MPExpression</code> instance into a <code>@link
<code>MPParsedExpression</code> instance that can be evaluated. For more //apple_ref/occ/cl/MPParsedExpression@/link</code> instance that can be
information on evaluation see the <code>MPParsedExpression</code> and evaluated. For more information on evaluation see the <code>@link
<code>MPTerm</code> class as well as the previously mentioned methods. //apple_ref/occ/cl/MPParsedExpression@/link</code> and <code>@link
*/ //apple_ref/occ/cl/MPTerm@/link</code> class as well as the previously mentioned
methods.
*/
/*!
@protocol MPExpressionElement
@abstract This protocol defines the functionality an element in an
expression must have.
*/
@protocol MPExpressionElement <NSObject, NSCopying, NSCoding>
/*!
@method isString
@abstract Returns wether the receiver is a string.
@discussion A string is defined by being an instance of
<code>NSString</code>. If this method returns <code>YES</code>
you can be sure the receiver is an <code>NSString</code>
instance.
@return <code>YES</code> if the receiver is a string, <code>NO</code>
otherwise.
*/
- (BOOL)isString;
/*!
@method isFunction
@abstract Returns wether the receiver is a function.
@discussion A function is defined by being an instance of
<code>@link //apple_ref/occ/cl/MPFunction@/link</code>. If this
method returns <code>YES</code> you can be sure the receiver is a
<code>@link //apple_ref/occ/cl/MPFunction@/link</code> instance.
@return <code>YES</code> if the receiver is a function, <code>NO</code>
otherwise.
*/
- (BOOL)isFunction;
/*!
@method length
@abstract Calculates the length of the receiver.
@discussion The length of a <code>MPExpressionElement</code> is the number of
symbols it consists of. For strings this is the number of
characters in it. Functions have a length of <code>1</code>.
@return The receiver's length.
*/
- (NSUInteger)length;
@end
/*! /*!
@const MPIllegalElementException @const MPIllegalElementException
@brief Name for an exception that is raised if an invalid element is @abstract Name for an exception that is raised if an invalid element is
added to an expression. added to an expression.
@discussion This exception may be raised during initialization of an @discussion This exception may be raised during initialization of an
@@ -117,7 +177,7 @@ FOUNDATION_EXPORT NSString *const MPIllegalElementException;
/*! /*!
@const MPIllegalElementExceptionElementKey @const MPIllegalElementExceptionElementKey
@brief Predefined key for an invalid element that caused a @abstract Predefined key for an invalid element that caused a
<code>MPIllegalElementException</code> to be raised. <code>MPIllegalElementException</code> to be raised.
@discussion The invalid element can be of any type. Numbers and structs are @discussion The invalid element can be of any type. Numbers and structs are
@@ -129,7 +189,7 @@ FOUNDATION_EXPORT NSString *const MPIllegalElementExceptionElementKey;
/*! /*!
@typedef MPReferenceFrame @typedef MPReferenceFrame
@brief A reference frame specifies the way an <i>item</i> is to be @abstract A reference frame specifies the way an <i>item</i> is to be
interpreted. interpreted.
@constant MPElementReferenceFrame @constant MPElementReferenceFrame
@@ -155,17 +215,14 @@ typedef enum {
/*! /*!
@class MPExpression @class MPExpression
@brief A <code>MPExpression</code> instance represents a mathematical @abstract A <code>MPExpression</code> instance represents a mathematical
expression. expression.
@discussion Every expression consists of string elements (represented by the @discussion A expression consists of string elements and function elements.
<code>NSString</code> class) and function elements (represented Functions and expressions together make up the expression tree.
by the <code>MPFunction</code> class). Functions and expressions
make up the expression tree.
*/ */
@interface MPExpression : NSObject <NSCopying, NSCoding> @interface MPExpression : NSObject <NSCopying, NSCoding>
#pragma mark Creation Methods #pragma mark Creation Methods
/*! /*!
@methodgroup Creation Methods @methodgroup Creation Methods
@@ -174,7 +231,7 @@ typedef enum {
/*! /*!
@method init @method init
@brief Initlializes a new expression. @abstract Initlializes a new expression.
@discussion This method is a convenience initializer to initialize an @discussion This method is a convenience initializer to initialize an
expression with <code>0</code> elements. expression with <code>0</code> elements.
@@ -186,7 +243,7 @@ typedef enum {
/*! /*!
@method initWithElement: @method initWithElement:
@brief Initializes a new expression with the specified @abstract Initializes a new expression with the specified
<code>element</code>. <code>element</code>.
@discussion This method is a convenience initializer to initialize an @discussion This method is a convenience initializer to initialize an
@@ -203,22 +260,23 @@ typedef enum {
/*! /*!
@method initWithElements: @method initWithElements:
@brief Initializes a new expression with the specified @abstract Initializes a new expression with the specified
<code>elements</code>. <code>elements</code>.
@discussion All elements must conform to the <code>MPExpressionElement</code> @discussion All elements must conform to the <code>@link
protocol. If one or more objects do not conform to that protocol MPExpressionElement@/link</code> protocol. If one or more objects
a <code>MPIllegalElementException</code> is raised. do not conform to that protocol a <code>@link
MPIllegalElementException@/link</code> is raised.
This method is the designated initializer for the This method is the designated initializer for the
<code>MPExpression</code> class. <code>MPExpression</code> class.
@param elements @param elements
The elements that should be added to the expression. Every The elements that should be added to the expression. Every
element must conform to the <code>MPExpressionElement</code> element must conform to the <code>@link
protocol. Each element is copied and the copy is then added to MPExpressionElement@/link</code> protocol. Each element is copied
the expression. The object in the <code>elements</code> array is and the copy is then added to the expression. The object in the
not modified. <code>elements</code> array is not modified.
@return An expression containing <code>elements</code>. @return An expression containing <code>elements</code>.
*/ */
@@ -233,13 +291,15 @@ typedef enum {
/*! /*!
@property parent @property parent
@brief The receiver's parent. @abstract The receiver's parent.
@discussion The receiver's parent is the function in the expression tree that @discussion The receiver's parent is the function in the expression tree that
contains the receiver. contains the receiver.
@warning You should never set this property manually. If you are @warning You should never set this property manually. If you are
implementing a custom subclass of <code>MPFunction</code> use the implementing a custom subclass of <code>@link
<code>MPFunctionAccessorImplementation</code> macro. //apple_ref/occ/cl/MPFunction@/link</code> use the <code>@link
//apple_ref/occ/macro/MPFunctionAccessorImplementation@/link</code>
macro.
@return The parent of the receiver or <code>nil</code> if the receiver is @return The parent of the receiver or <code>nil</code> if the receiver is
the root expression. the root expression.
@@ -249,7 +309,7 @@ typedef enum {
/*! /*!
@method rootExpression @method rootExpression
@brief Returns the root expression from the receiver's expression tree. @abstract Returns the root expression from the receiver's expression tree.
@discussion The root expression is the ultimate parent of all expressions and @discussion The root expression is the ultimate parent of all expressions and
functions in the expression tree. A root expression does not have functions in the expression tree. A root expression does not have
@@ -262,7 +322,7 @@ typedef enum {
/*! /*!
@method indexPath @method indexPath
@brief Returns the index path of the receiver in the expression tree. @abstract Returns the index path of the receiver in the expression tree.
@discussion The index path contains the indexes (starting from the root @discussion The index path contains the indexes (starting from the root
expression of the receiver's expression tree) that lead to the expression of the receiver's expression tree) that lead to the
@@ -276,7 +336,7 @@ typedef enum {
/*! /*!
@method countItemsInReferenceFrame: @method countItemsInReferenceFrame:
@brief Returns the number of items in the receiver in the specified @abstract Returns the number of items in the receiver in the specified
<code>referenceFrame</code>. <code>referenceFrame</code>.
@param referenceFrame @param referenceFrame
@@ -290,10 +350,11 @@ typedef enum {
/*! /*!
@method itemAtIndex:referenceFrame: @method itemAtIndex:referenceFrame:
@brief Returns the item at <code>anIndex</code>. @abstract Returns the item at <code>anIndex</code>.
@discussion The item is not copied before it is returned. So be aware that @discussion The item is not copied before it is returned. So be aware that
if you mutate a <code>MPFunction</code> instance returned from if you mutate a <code>@link
//apple_ref/occ/cl/MPFunction@/link</code> instance returned from
this function the receiver's expression tree will be updated to this function the receiver's expression tree will be updated to
reflect the change. reflect the change.
@@ -314,7 +375,7 @@ typedef enum {
/*! /*!
@method elementAtIndex:referenceFrame: @method elementAtIndex:referenceFrame:
@brief Returns the element at the specified index. @abstract Returns the element at the specified index.
@discussion An element is either a string or a function. If @discussion An element is either a string or a function. If
<code>anIndex</code> identifies a position inside a string <code>anIndex</code> identifies a position inside a string
@@ -322,7 +383,7 @@ typedef enum {
This method always returns elements. To query items in the This method always returns elements. To query items in the
specified reference frame use specified reference frame use
<code>-itemAtIndex:referenceFrame:</code>. <code>@link itemAtIndex:referenceFrame:@/link</code>.
@param anIndex @param anIndex
The index of the element. The index of the element.
@@ -337,7 +398,7 @@ typedef enum {
/*! /*!
@method indexOfElement: @method indexOfElement:
@brief Returns the index of <code>element</code> or @abstract Returns the index of <code>element</code> or
<code>NSNotFound</code> if it was not found. <code>NSNotFound</code> if it was not found.
@param element @param element
@@ -351,7 +412,7 @@ typedef enum {
/*! /*!
@method itemsInRange:referenceFrame: @method itemsInRange:referenceFrame:
@brief Returns an array of the items that are located in the specified @abstract Returns an array of the items that are located in the specified
range. range.
@discussion The objects in the returned array are copied before they are @discussion The objects in the returned array are copied before they are
@@ -376,7 +437,7 @@ typedef enum {
/*! /*!
@method allItemsInReferenceFrame: @method allItemsInReferenceFrame:
@brief Returns an array of all items in the receiver for the specified @abstract Returns an array of all items in the receiver for the specified
reference frame. reference frame.
@discussion The elements in the returned array are not copied before they are @discussion The elements in the returned array are not copied before they are
@@ -391,15 +452,16 @@ typedef enum {
/*! /*!
@method elementAtIndexPath: @method elementAtIndexPath:
@brief Returns the element at the specified index path. @abstract Returns the element at the specified index path.
@discussion This method finds the elements at the respective indexes starting @discussion This method finds the elements at the respective indexes starting
at the root expression from the receiver's expression tree. at the root expression from the receiver's expression tree.
The returned object can be a <code>NSString</code>, a The returned object can be a <code>NSString</code>, a
<code>MPFunction</code> or an <code>MPExpression</code> instance <code>@link //apple_ref/occ/cl/MPFunction@/link</code> or a
depending on the specified <code>indexPath</code>. If any of the <code>MPExpression</code> instance depending on the specified
indexes exceed the bounds of the respective receiver a <code>indexPath</code>. If any of the indexes exceed the bounds
<code>NSRangeException</code> is raised. of the respective receiver a <code>NSRangeException</code> is
raised.
If the index path does not contain any indexes the receiver If the index path does not contain any indexes the receiver
itself is returned. itself is returned.
@@ -418,11 +480,12 @@ typedef enum {
/*! /*!
@method convertIndex:fromReferenceFrame:toReferenceFrame: @method convertIndex:fromReferenceFrame:toReferenceFrame:
@brief Converts an index from one reference frame to another. @abstract Converts an index from one reference frame to another.
@discussion This method ignores any offsets into items the conversion between @discussion This method ignores any offsets into items the conversion between
reference frames can cause. If you are interested in the offset reference frames can cause. If you are interested in the offset
use <code>-convertIndex:fromReferenceFrame:toReferenceFrame:offset:</code> use <code>@link
convertIndex:fromReferenceFrame:toReferenceFrame:offset:@/link</code>
instead. instead.
@param anIndex @param anIndex
@@ -446,7 +509,7 @@ typedef enum {
/*! /*!
@method convertIndex:fromReferenceFrame:toReferenceFrame:offset: @method convertIndex:fromReferenceFrame:toReferenceFrame:offset:
@brief Converts an index from one reference frame to another. @abstract Converts an index from one reference frame to another.
@discussion If <code>anIndex</code> identifies a location inside an item in @discussion If <code>anIndex</code> identifies a location inside an item in
the <code>toReferenceFrame</code> the index of the corresponding the <code>toReferenceFrame</code> the index of the corresponding
@@ -481,18 +544,20 @@ typedef enum {
/*! /*!
@method convertRange:fromReferenceFrame:toReferenceFrame: @method convertRange:fromReferenceFrame:toReferenceFrame:
@brief Converts a range from one reference frame to another. @abstract Converts a range from one reference frame to another.
@discussion This method just converts the location and target of the range @discussion This method just converts the location and target of the range
separately using separately using
<code>-convertIndex:fromReferenceFrame:toReferenceFrame:</code>. <code>@link
convertIndex:fromReferenceFrame:toReferenceFrame:@/link</code>.
It ensures that the returned range definitely includes all items It ensures that the returned range definitely includes all items
that were specified by <code>aRange</code>. that were specified by <code>aRange</code>.
The possibility that the returned range may The possibility that the returned range may
include more symbols than <code>aRange</code> is ignored. If you include more symbols than <code>aRange</code> is ignored. If you
need that information use need that information use
<code>-convertRange:fromReferenceFrame:toReferenceFrame:leadingOffset:trailingOffset:</code>. <code>@link
convertRange:fromReferenceFrame:toReferenceFrame:leadingOffset:trailingOffset:@/link</code>.
@param aRange @param aRange
The range to be converted. The range to be converted.
@@ -513,11 +578,12 @@ typedef enum {
/*! /*!
@method convertRange:fromReferenceFrame:toReferenceFrame:leadingOffset:trailingOffset: @method convertRange:fromReferenceFrame:toReferenceFrame:leadingOffset:trailingOffset:
@brief Converts a range from one reference frame to another. @abstract Converts a range from one reference frame to another.
@discussion This method just converts the location and target of the range @discussion This method just converts the location and target of the range
separately using separately using
<code>-convertIndex:fromReferenceFrame:toReferenceFrame:</code>. <code>@link
convertIndex:fromReferenceFrame:toReferenceFrame:@/link</code>.
It ensures that the returned range definitely includes all items It ensures that the returned range definitely includes all items
that were specified by <code>aRange</code>. that were specified by <code>aRange</code>.
@@ -538,8 +604,8 @@ typedef enum {
The offset of the last index in the range in respect to the last The offset of the last index in the range in respect to the last
index of <code>aRange</code>. index of <code>aRange</code>.
@return A range in the <code>toReferenceFrame</code> that includes the the items @return A range in the <code>toReferenceFrame</code> that includes the
specified by <code>aRange</code>. the items specified by <code>aRange</code>.
*/ */
- (NSRange)convertRange:(NSRange)aRange - (NSRange)convertRange:(NSRange)aRange
fromReferenceFrame:(MPReferenceFrame)fromReferenceFrame fromReferenceFrame:(MPReferenceFrame)fromReferenceFrame
@@ -556,7 +622,7 @@ typedef enum {
/*! /*!
@method replaceItemsInRange:referenceFrame:withElements: @method replaceItemsInRange:referenceFrame:withElements:
@brief Replaces the elements in the specified range with the contents of @abstract Replaces the elements in the specified range with the contents of
the <code>elements</code> array. the <code>elements</code> array.
@discussion This is the most primitive mutation method of @discussion This is the most primitive mutation method of
@@ -567,8 +633,9 @@ typedef enum {
is restored. That basically means that subsequent strings are is restored. That basically means that subsequent strings are
joined and empty strings removed. After restoring integrity the joined and empty strings removed. After restoring integrity the
receiver sends a receiver sends a
<code>-changedElementsInIndexedRangePath:replacementLength:</code> <code>@link
to itself. For more information see the documentation on that changedElementsInRangePath:replacementLength:@/link</code> to
itself. For more information see the documentation on that
method. method.
@param aRange @param aRange
@@ -588,16 +655,16 @@ typedef enum {
/*! /*!
@method changedElementsInRangePath:replacementLength: @method changedElementsInRangePath:replacementLength:
@brief This is a notification message that is sent from the receiver to @abstract This is a notification message that is sent from the receiver to
itself after it has been mutated. itself after it has been mutated.
@discussion This method does nothing more than notify it's parent that it has @discussion This method does nothing more than notify it's parent that it has
been mutated at the respective range path. If you want to get been mutated at the respective range path. If you want to get
notified about changes in an expression you should override this notified about changes in an expression you should override this
method instead of method instead of <code>@link
<code>-replaceSymbolsInRange:withElements:</code> because this replaceItemsInRange:referenceFrame:withElements:@/link</code>
method gives you information about the elements that changed because this method gives you information about the elements that
during the mutation. changed during the mutation.
@param rangePath @param rangePath
The range path at which the receiver was changed starting at the The range path at which the receiver was changed starting at the
@@ -615,7 +682,7 @@ typedef enum {
/*! /*!
@method subexpressionFromIndex:referenceFrame: @method subexpressionFromIndex:referenceFrame:
@brief Creates an expression from the items in the receiver from the @abstract Creates an expression from the items in the receiver from the
specified index to the end. specified index to the end.
@discussion The items from the receiver are copied. Mutations to the returned @discussion The items from the receiver are copied. Mutations to the returned
@@ -636,7 +703,7 @@ typedef enum {
/*! /*!
@method subexpressionToIndex:referenceFrame: @method subexpressionToIndex:referenceFrame:
@brief Creates an expression from the items in the receiver from the @abstract Creates an expression from the items in the receiver from the
first to the specified item. first to the specified item.
@discussion The items from the receiver are copied. Mutations to the returned @discussion The items from the receiver are copied. Mutations to the returned
@@ -658,7 +725,7 @@ typedef enum {
/*! /*!
@method subexpressionWithRange:referenceFrame: @method subexpressionWithRange:referenceFrame:
@brief Creates an expression from the items in the receiver within the @abstract Creates an expression from the items in the receiver within the
specified range. specified range.
@discussion The items from the receiver are copied. Mutations to the returned @discussion The items from the receiver are copied. Mutations to the returned
@@ -685,10 +752,10 @@ typedef enum {
/*! /*!
@method parse: @method parse:
@brief Parses the receiver. @abstract Parses the receiver.
@discussion This is a convenience method that calls @discussion This is a convenience method that calls <code>@link
<code>-parseExpectingVariable:errors:</code> with <code>NO</code> parseExpectingVariable:errors:@/link</code> with <code>NO</code>
as the first argument. as the first argument.
@param errors @param errors
@@ -698,17 +765,18 @@ typedef enum {
set to an empty array. Pass <code>NULL</code> if you are not set to an empty array. Pass <code>NULL</code> if you are not
interested in any errors that might occur. interested in any errors that might occur.
@return A <code>MPParsedExpression</code> instance that represents the @return A <code>@link //apple_ref/occ/cl/MPParsedExpression@/link</code>
receiver and can be evaluated or <code>nil</code> if an error instance that represents the receiver and can be evaluated or
occurs. In that case the <code>errors</code> parameter is set to <code>nil</code> if an error occurs. In that case the
an array containing at least one <code>NSError</code> instance. <code>errors</code> parameter is set to an array containing at
least one <code>NSError</code> instance.
*/ */
- (MPParsedExpression *)parse:(NSArray *__autoreleasing *)errors; - (MPParsedExpression *)parse:(NSArray *__autoreleasing *)errors;
/*! /*!
@method parseExpectingVariable:errors: @method parseExpectingVariable:errors:
@brief Parses the receiver. @abstract Parses the receiver.
@param flag @param flag
If <code>YES</code> the receiver must (exept for whitespaces) If <code>YES</code> the receiver must (exept for whitespaces)
@@ -723,10 +791,11 @@ typedef enum {
set to an empty array. Pass <code>NULL</code> if you are not set to an empty array. Pass <code>NULL</code> if you are not
interested in any errors that might occur. interested in any errors that might occur.
@return A <code>MPParsedExpression</code> instance that represents the @return A <code>@link //apple_ref/occ/cl/MPParsedExpression@/link</code>
receiver and can be evaluated or <code>nil</code> if an error instance that represents the receiver and can be evaluated or
occurs. In that case the <code>errors</code> parameter is set to <code>nil</code> if an error occurs. In that case the
an array containing at least one <code>NSError</code> instance. <code>errors</code> parameter is set to an array containing at
least one <code>NSError</code> instance.
*/ */
- (MPParsedExpression *)parseExpectingVariable:(BOOL)flag - (MPParsedExpression *)parseExpectingVariable:(BOOL)flag
errors:(NSArray *__autoreleasing *)errors; errors:(NSArray *__autoreleasing *)errors;
@@ -737,7 +806,7 @@ typedef enum {
/*! /*!
@category MPExpression (MPExpressionConvenience) @category MPExpression (MPExpressionConvenience)
@brief This category defines convenience methods for the @abstract This category defines convenience methods for the
<code>MPExpression</code> class. <code>MPExpression</code> class.
@discussion All convenience methods are completely defined in terms of other @discussion All convenience methods are completely defined in terms of other
@@ -753,7 +822,7 @@ typedef enum {
/*! /*!
@method countElements @method countElements
@brief Returns the number of elements in the receiver. @abstract Returns the number of elements in the receiver.
@return The number of elements in the receiver expressed in the element @return The number of elements in the receiver expressed in the element
reference frame. reference frame.
@@ -763,7 +832,7 @@ typedef enum {
/*! /*!
@method countSymbols @method countSymbols
@brief Returns the number of symbols in the receiver. @abstract Returns the number of symbols in the receiver.
@return The number of symbols in the receiver expressed in the symbol @return The number of symbols in the receiver expressed in the symbol
reference frame. reference frame.
@@ -773,7 +842,7 @@ typedef enum {
/*! /*!
@method countTokens @method countTokens
@brief Returns the number of tokens in the receiver. @abstract Returns the number of tokens in the receiver.
@return The number of tokens in the receiver expressed in the token @return The number of tokens in the receiver expressed in the token
reference frame. reference frame.
@@ -783,7 +852,7 @@ typedef enum {
/*! /*!
@method elementAtIndex: @method elementAtIndex:
@brief Returns the element at the specified index. @abstract Returns the element at the specified index.
@param anIndex @param anIndex
The index of the element specified in the element reference The index of the element specified in the element reference
@@ -796,7 +865,7 @@ typedef enum {
/*! /*!
@method symbolAtIndex: @method symbolAtIndex:
@brief Returns the symbol at the specified index. @abstract Returns the symbol at the specified index.
@param anIndex @param anIndex
The index of the symbol specified in the symbol reference frame. The index of the symbol specified in the symbol reference frame.
@@ -808,7 +877,7 @@ typedef enum {
/*! /*!
@method tokenAtIndex: @method tokenAtIndex:
@brief Returns the token at the specified index. @abstract Returns the token at the specified index.
@param anIndex @param anIndex
The index of the token specified in the token reference frame. The index of the token specified in the token reference frame.
@@ -826,7 +895,7 @@ typedef enum {
/*! /*!
@method appendElement: @method appendElement:
@brief Appends <code>anElement</code> to the receiver. @abstract Appends <code>anElement</code> to the receiver.
@param anElement @param anElement
The element to append to the receiver. The element to append to the receiver.
@@ -836,12 +905,12 @@ typedef enum {
/*! /*!
@method appendElements: @method appendElements:
@brief Appends the objects from <code>elements</code> to the receiver. @abstract Appends the objects from <code>elements</code> to the receiver.
@discussion All objects in the <code>elements</code> array must conform to @discussion All objects in the <code>elements</code> array must conform to
the <code>MPExpressionElement</code> protocol. If at least one the <code>@link MPExpressionElement@/link</code> protocol. If at
element does not conform to that protocol a least one element does not conform to that protocol a <code>@link
<code>MPIllegalElementException</code> is raised. MPIllegalElementException@/link</code> is raised.
@param elements @param elements
The elements to append to the receiver. The elements to append to the receiver.
@@ -851,7 +920,7 @@ typedef enum {
/*! /*!
@method insertElement:atIndex:referenceFrame: @method insertElement:atIndex:referenceFrame:
@brief Inserts <code>anElement</code> at the specified index. @abstract Inserts <code>anElement</code> at the specified index.
@param anElement @param anElement
The element to be inserted. The element to be inserted.
@@ -869,12 +938,12 @@ typedef enum {
/*! /*!
@method insertElements:atIndex:referenceFrame: @method insertElements:atIndex:referenceFrame:
@brief Inserts <code>elements</code> at the specified index. @abstract Inserts <code>elements</code> at the specified index.
@discussion All objects in the <code>elements</code> array must conform to @discussion All objects in the <code>elements</code> array must conform to
the <code>MPExpressionElement</code> protocol. If at least one the <code>@link MPExpressionElement@/link</code> protocol. If at
element does not conform to that protocol a least one element does not conform to that protocol a <code>@link
<code>MPIllegalElementException</code> is raised. MPIllegalElementException@/link</code> is raised.
@param elements @param elements
The elements to be inserted. The elements to be inserted.
@@ -891,8 +960,8 @@ typedef enum {
/*! /*!
@method deleteElementsInRange: @method deleteElementsInRange:referenceFrame:
@brief Removes the elements identified by <code>range</code> from the @abstract Removes the elements identified by <code>range</code> from the
receiver. receiver.
@discussion If <code>range</code> exceeds the receiver's bounds a @discussion If <code>range</code> exceeds the receiver's bounds a

View File

@@ -8,7 +8,7 @@
#import "MPExpression.h" #import "MPExpression.h"
#import "MPExpressionElement.h" #import "MPExpression.h"
#import "MPFunction.h" #import "MPFunction.h"
#import "MPRangePath.h" #import "MPRangePath.h"
@@ -32,7 +32,7 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio
/*! /*!
@method tokens @method tokens
@brief Private method. Returns an array containing all tokens from the @abstract Private method. Returns an array containing all tokens from the
receiver. receiver.
@return All items in the <code>MPTokenReferenceFrame</code>. @return All items in the <code>MPTokenReferenceFrame</code>.
@@ -42,7 +42,7 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio
/*! /*!
@method validateElements: @method validateElements:
@brief Private method. Checks whether all objects in the specified array @abstract Private method. Checks whether all objects in the specified array
are valid expression elements. are valid expression elements.
@discussion If an object is not valid a @discussion If an object is not valid a
@@ -56,7 +56,7 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio
/*! /*!
@method fixElements @method fixElements
@brief Private method. Restores consistency in the receiver after a @abstract Private method. Restores consistency in the receiver after a
change was made. change was made.
*/ */
- (void)fixElements; - (void)fixElements;
@@ -64,7 +64,7 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio
/*! /*!
@method _replaceSymbolsInRange:withElements: @method _replaceSymbolsInRange:withElements:
@brief Private method. Replaces the symbols in the specified range with @abstract Private method. Replaces the symbols in the specified range with
the elements from the <code>elements</code> array. the elements from the <code>elements</code> array.
@discussion This is the most primitive mutation method of the @c MPExpression @discussion This is the most primitive mutation method of the @c MPExpression
@@ -85,7 +85,7 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio
/*! /*!
@method _splitElementsAtLocation:insertionIndex: @method _splitElementsAtLocation:insertionIndex:
@brief Splits the receiver's elements at the specified @abstract Splits the receiver's elements at the specified
<code>location</code>. <code>location</code>.
@discussion The split location can be inside a string element. In that case @discussion The split location can be inside a string element. In that case

View File

@@ -1,57 +0,0 @@
//
// MPExpressionElement.h
// MathPad
//
// Created by Kim Wittenburg on 10.08.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
/*!
@protocol MPExpressionElement
@brief This protocol defines the functionality an element in an
expression must have.
*/
@protocol MPExpressionElement <NSObject, NSCopying, NSCoding>
/*!
@method isString
@brief Returns wether the receiver is a string.
@discussion A string is defined by being an instance of @c NSString. If this
method returns @c YES you can be sure it is an @c NSString
instance.
@return @c YES if the receiver is a string, @c NO otherwise.
*/
- (BOOL)isString;
/*!
@method isFunction
@brief Returns wether the receiver is a function.
@discussion A function is defined by being an instance of @c MPFunction. If
this method returns @c YES you can be sure it is a @c MPFunction
instance.
@return @c YES if the receiver is a function, @c NO otherwise.
*/
- (BOOL)isFunction;
/*!
@method length
@brief Calculates the length of the receiver.
@discussion The length of a @c MPExpressionElement is the number of symbols
it consists of. For strings this is the number of characters in
it. Functions have a length of @c 1.
@return The receiver's length.
*/
- (NSUInteger)length;
@end

View File

@@ -9,7 +9,7 @@
#import "MPExpressionLayout.h" #import "MPExpressionLayout.h"
#import "MPExpression.h" #import "MPExpression.h"
#import "MPExpressionElement.h" #import "MPExpression.h"
#import "MPPowerFunction.h" #import "MPPowerFunction.h"
#import "MPFunctionLayout.h" #import "MPFunctionLayout.h"

View File

@@ -7,17 +7,139 @@
// //
/*!
@header
The <code>MPExpressionParser</code> converts a <code>@link
MPExpression@/link</code> instance into a <code>@link
//apple_ref/occ/cl/MPParsedExpression@/link</code> instance. The rules that are
used for parsing expressions are consistent with general math rules. For example
operator precedence and parenthesis are regarded. However there may still be
ambiguous input. The parser solves them by using the following rules:
1. Powers and factorials apply to the value that <b>directly</b> precedes them.
It is invalid if a power or factorial symbol is preceded by a space.
2. Powers and factorials chained behind each other apply to the value before the
first power or factorial symbol in the chain (provided that rule 1 is
satisfied). All powers and factorials apply to that value in the order of
occurence. For example <code>2³!</code> is valid and equal to
<code>(2³)!</code>.
3. Elementary functions like <code>sin</code>, <code>cos</code> or
<code>ln</code> can be chained. <code>sincos(2)</code> is equal to
<code>sin(cos(2))</code>.
4. Subsequent elementary functions with values are implicitly multiplied.
<code>sin3cos2</code> is equal to <code>sin(3)⋅cos(2)</code>.
5. The value of an elementary function is either exactly one generic function
(instances of a <code>@link MPFunction@/link</code> subclass) or a group of
numbers and variables that does not contain a multiplication, plus or minus
sign. <code>sin2a⋅3</code> is equal to <code>(sin(2a))⋅3</code>.
Besides the rules above the parser accepts inputs containing the following
constructs:
1. Chained plus and minus signs (e.g. <code>++-+--3</code> is equal to
<code>-3</code>).
2. Implicit multiplication. <code>2a3</code> is equal to <code>2⋅a⋅3</code>.
*/
@class MPExpressionParser, MPExpression, MPParsedExpression; @class MPExpressionParser, MPExpression, MPParsedExpression;
/*!
@class MPExpressionParser
@abstract An instance of this class can parse an expression.
@discussion Parsing an expression means converting it into a <code>@link
//apple_ref/occ/cl/MPParsedExpression@/link</code> instance. One
parser can only process one expression. After the parser has been
constructed it should start processing the expression before it
is mutated. For the same reason parsers should not be recycled
but instead recreated when needed.
*/
@interface MPExpressionParser : NSObject @interface MPExpressionParser : NSObject
/*!
@property expression
@abstract The receiver's expression.
*/
@property (readonly, nonatomic, strong) MPExpression *expression; @property (readonly, nonatomic, strong) MPExpression *expression;
- (instancetype)initWithExpression:(MPExpression *)expression;
/*!
@method initWithExpression:
@abstract Initializes a new <code>MPExpressionParser</code>.
@discussion After this method returns the parser is ready to parse the given
<code>expression</code>. If the expression is mutated between the
creation of the parser and the actual parsing process unexpected
behaviour may occur.
This is the designated initializer for the
<code>MPExpressionParser</code> class.
@param expression
The expression that is supposed to be parsed.
@return A newly initialized expression parser.
*/
- (instancetype)initWithExpression:(MPExpression *)expression; /* designated initializer */
/*!
@method parse:
@abstract Parses the receiver's expression.
@discussion If the expression contains any syntax errors they will be
returned indirectly through the <code>errors</code> parameter. In
that case <code>nil</code> is returned. If no errors occur it is
not modified.
This is a convenience method that calls <code>@link
parseExpectingVariableDefinition:errors:@/link</code> with
<code>NO</code> as the first argument.
@param errors
If the parsed expression contains syntax errors this parameter
will be set to an array containing at least one
<code>NSError</code> instance. This parameter is never set to an
empty array.
If you are not interested in errors, pass <code>NULL</code>.
@return The parsed expression or <code>nil</code> if the parsed
expression contains syntax errors.
*/
- (MPParsedExpression *)parse:(NSArray *__autoreleasing *)errors; - (MPParsedExpression *)parse:(NSArray *__autoreleasing *)errors;
/*!
@method parseExpectingVariableDefinition:errors:
@abstract Parses the receiver's expression.
@discussion If the expression contains any syntax errors they will be
returned indirectly through the <code>errors</code> parameter. In
that case <code>nil</code> is returned. If no errors occur it is
not modified.
@param flag
If set to <code>YES</code> the parser expects the expression to
begin with a variable definition, that is a single letter
followed by an equals sign (exept for spaces). If set to
<code>NO</code> there must not be a variable definition.
@param errors
If the parsed expression contains syntax errors this parameter
will be set to an array containing at least one
<code>NSError</code> instance. This parameter is never set to an
empty array.
If you are not interested in errors, pass <code>NULL</code>.
@return The parsed expression or <code>nil</code> if the parsed
expression contains syntax errors.
*/
- (MPParsedExpression *)parseExpectingVariableDefinition:(BOOL)flag - (MPParsedExpression *)parseExpectingVariableDefinition:(BOOL)flag
errors:(NSArray *__autoreleasing *)errors; errors:(NSArray *__autoreleasing *)errors;

View File

@@ -13,24 +13,28 @@
/*! /*!
@class MPExpressionTokenizer @class MPExpressionTokenizer
@brief The expression tokenizer class convers an @c MPExpression @abstract The expression tokenizer class convers an <code>@link
instance into an array of tokens. MPExpression@/link</code> instance into an array of tokens.
*/ */
@interface MPExpressionTokenizer : NSObject @interface MPExpressionTokenizer : NSObject
/*! /*!
@method tokenizeExpression: @method tokenizeExpression:
@brief Converts an @c MPExpression instance into an array of tokens. @abstract Converts an <code>@link MPExpression@/link</code> instance into
an array of tokens.
@discussion The objects in the returned array all conform to the @c MPToken @discussion The objects in the returned array all conform to the <code>@link
protocol. Function tokens are not copied from the @c expression //apple_ref/occ/intf/MPToken@/link</code> protocol. Function
so they can still be mutated. tokens are not copied from the <code>expression</code> so they
can still be mutated.
This method can be safely called from multiple threads.
@param expression @param expression
The expression to be tokenized. The expression to be tokenized.
@return An array of objects that conform to the @c MPToken protocol. @return An array of objects that conform to the <code>@link
//apple_ref/occ/intf/MPToken@/link</code> protocol.
*/ */
+ (NSArray *)tokenizeExpression:(MPExpression *)expression; + (NSArray *)tokenizeExpression:(MPExpression *)expression;

View File

@@ -9,7 +9,7 @@
#import "MPExpressionTokenizer.h" #import "MPExpressionTokenizer.h"
#import "MPExpression.h" #import "MPExpression.h"
#import "MPExpressionElement.h" #import "MPExpression.h"
#import "MPToken.h" #import "MPToken.h"

View File

@@ -13,10 +13,35 @@
@class MPFactorialTerm; @class MPFactorialTerm;
/*!
@class MPFactorialTerm
@abstract A factorial term implements the factorial function.
@discussion Because the factorial function is only defined for whole numbers,
actually the gamma function is used. The gamma function is
defined for all real numbers.
*/
@interface MPFactorialTerm : MPTerm @interface MPFactorialTerm : MPTerm
/*!
@method initWithTerm:
@abstract Initializes the receiver with the specified term.
@discussion The <code>term</code> is not copied.
@param term
The term to initialize the receiver. Must not be
<code>nil</code>.
@return A newly initialized factorial term.
*/
- (instancetype)initWithTerm:(MPTerm *)term; /* designated initializer */ - (instancetype)initWithTerm:(MPTerm *)term; /* designated initializer */
/*!
@property term
@abstract The receiver's term.
*/
@property (readonly, nonatomic, strong) MPTerm *term; @property (readonly, nonatomic, strong) MPTerm *term;
@end @end

View File

@@ -15,28 +15,31 @@
/*! /*!
@class MPFractionFunction @class MPFractionFunction
@brief This class represents a fraction. @abstract This class represents a fraction.
@discussion When a fraction is evaluated the nominator is divided by the @discussion A fraction has two children: the nominator and the denominator.
denominator. Typically it is displayed with a horizontal bar between the two
child expressions which are on top and below the bar
respectively. When a fraction is evaluated the nominator is
divided by the denominator.
*/ */
@interface MPFractionFunction : MPFunction @interface MPFractionFunction : MPFunction
/*! /*!
@property nominatorExpression @property nominatorExpression
@brief The receiver's nominator. @abstract The receiver's nominator.
@discussion The nominator must not define a variable. @discussion The nominator must not define a variable.
*/ */
@property (nonatomic, strong) MPExpression *nominatorExpression; @property (nonatomic, strong) MPExpression *nominatorExpression; /* Index 0 */
/*! /*!
@property denominatorExpression @property denominatorExpression
@brief The receiver's denominator. @abstract The receiver's denominator.
@discussion The denominator must not define a variable. @discussion The denominator must not define a variable.
*/ */
@property (nonatomic, strong) MPExpression *denominatorExpression; @property (nonatomic, strong) MPExpression *denominatorExpression; /* Index 1 */
@end @end

View File

@@ -13,8 +13,9 @@
/*! /*!
@category MPFunction (MPToken) @category MPFunction (MPToken)
@brief This category adds @c MPToken protocol conformance to the @c @abstract This category adds <code>@link
MPFunction class. //apple_ref/occ/intf/MPToken@/link</code> protocol conformance to
the <code>@link MPFunction@/link</code> class.
*/ */
@interface MPFunction (MPToken) <MPToken> @interface MPFunction (MPToken) <MPToken>

View File

@@ -6,14 +6,62 @@
// Copyright (c) 2014 Kim Wittenburg. All rights reserved. // Copyright (c) 2014 Kim Wittenburg. All rights reserved.
// //
#import "MPExpressionElement.h" #import "MPExpression.h"
/*!
@header
<code>MPFunction</code> is a half abstract class that is designed to be
subclassed. Subclasses of the <code>MPFunction</code> class (subsequently called
<i>functions</i>) need to regard the following guidelines:
1. In their header file functions should declare <code>readwrite,
nonatomic</code> properties for every child (subexpression) they have.
2. For every public child accessor there should be one use of the
<code>@link MPFunctionAccessorImplementation@/link</code> macro in the
implementation file. See the documentation on the macro for details.
3. Functions must override the <code>@link childrenAccessors@/link</code> method
returning the KVC compatible names of the publicly declared property accessors
4. Functions must also override the <code>@link functionTermClass@/link</code>
method returning a <code>Class</code> that can evaluate the function. See the
documentation on that method for details.
5. Optionally functions can implement
<code>@link expectsVariableDefinitionInChildAtIndex:@/link</code> if one of
its children is supposed to contain a variable definition.
6. Functions should also override the <code>NSObject</code> method
<code>description</code>. Although this is not a requirement it
is strongly recommended.
Functions play an important role in the <i>expression tree</i>. For details on
the that subject see the documentation for <code>@link
MPExpression@/link</code>.
@note
None of the children of a function may be <code>nil</code> at any time.
*/
/* Use this macro to implement a custom setter for children of custom MPFunction /*!
* subclasses. This is necessary to maintain the consistency of the expression @define MPFunctionAccessorImplementation
* tree. Not implementing a custom setter using this macro or a similar custom @abstract This macro implements the setter of a previously declared
* method will lead to unexpected behaviour. property of a <code>MPFunction</code> subclass.
@discussion Overriding the default setter implementation is necessary to
maintain the consistency of the expression tree. Not implementing
a custom setter using this macro or a similar custom method will
lead to unexpected behaviour. If you need to implement additional
custom behaviour in a property setter it is recommended that you
copy the content of the macro.
@param Accessor
The capitalized name of the property to be implemented. This is
used for the name of the method: <code>set...</code>.
@param variableName
The name of the instance variable that backs the property.
Normally this is the same as the name of the property prefixed
with an underscore.
*/ */
#define MPFunctionAccessorImplementation(Accessor, variableName) \ #define MPFunctionAccessorImplementation(Accessor, variableName) \
- (void)set##Accessor:(MPExpression *)value \ - (void)set##Accessor:(MPExpression *)value \
@@ -32,25 +80,15 @@
/*! /*!
@class MPFunction @class MPFunction
@brief The @c MPFunction class represents a mathematical function. @abstract The <code>MPFunction</code> class represents a mathematical function.
@discussion A mathematical function can be anything that exceeds the @discussion A mathematical function can be anything that exceeds the
graphical capability of text. graphical capability of text. Functions like <code>sin</code>,
<code>cos</code> or <code>ln</code> are not considered functions
in this context because they can be represented by text.
*/ */
@interface MPFunction : NSObject <NSCoding, NSCopying, MPExpressionElement> @interface MPFunction : NSObject <NSCoding, NSCopying, MPExpressionElement>
#pragma mark Properties
/* Subclasses should define readwrite properties for all child expressions they
* can have. In the implementation file the property setter should be overridden
* using the @c MPFunctionAccessorImplementation macro. The macro takes two
* parameters: The capitalized name of the property and the name of the
* property's backing variable (usually the property's name prefixed with an
* underscore.
*
* Note that none of the children may be nil at any time.
*/
#pragma mark Working With the Expression Tree #pragma mark Working With the Expression Tree
/*! /*!
@methodgroup Working With the Expression Tree @methodgroup Working With the Expression Tree
@@ -59,86 +97,85 @@
/*! /*!
@property parent @property parent
@brief The receiver's parent. @abstract The receiver's parent.
@discussion Expressions and functions are organized in a tree-like structure. @discussion Expressions and functions are organized in a tree-like structure.
Through this property a function's containing expression can be Through this property a function's containing expression can be
accessed. accessed.
@warning Do not set this property manually. It will automatically be set @warning Do not set this property manually. It will automatically be set
when the function is added to an expression. when the function is added to or removed from an expression.
@note If you need to know when a function is added to or removed from @note If you need to know when a function is added to or removed from
an expression you can observe this property. an expression you can observe this property using KVO.
@return The parent of the receiver or @c nil if the receiver does not @return The parent of the receiver or <code>nil</code> if the receiver
have a parent. does not have a parent.
*/ */
@property (nonatomic, weak) MPExpression *parent; @property (nonatomic, weak) MPExpression *parent;
/*! /*!
@method rootExpression @method rootExpression
@brief Returns the root expression from the receiver's expression tree. @abstract Returns the root expression from the receiver's expression tree.
@discussion The root expression is the ultimate parent of all expressions and @discussion The root expression is the ultimate parent of all expressions and
functions in the expression tree. A root expression does not have functions in the expression tree. A root expression does not have
a parent. a parent.
@return The root expression from the receiver's expression tree or @c nil @return The root expression from the receiver's expression tree or
if this function does not have a parent. <code>nil</code> if this function does not have a parent.
*/ */
- (MPExpression *)rootExpression; - (MPExpression *)rootExpression;
/*! /*!
@method indexPath @method indexPath
@brief Returns the index path of the receiver in the expression tree. @abstract Returns the index path of the receiver in the expression tree.
@discussion The index path is calculated by going up the expression tree @discussion The index path contains the indexes (starting from the root
collecting the respective index of the receiver. The indexes are expression of the receiver's expression tree) that lead to the
expressed in the element reference frame. If any of the indexes receiver. The indexes are expressed in the element reference
exceed the respective receiver's bounds a @c NSRangeException is frame.
raised.
@return The index path of the receiver in the expression tree or @c nil @return The index path of the receiver in the expression tree or
if this function does not have a parent. <code>nil</code> if this function does not have a parent.
*/ */
- (NSIndexPath *)indexPath; - (NSIndexPath *)indexPath;
/*! /*!
@method numberOfChildren @method numberOfChildren
@brief Returns the number of children the receiver has. @abstract Returns the number of children the receiver has.
@discussion The number of children must be equal to the number of child @return The number of children the receiving function has.
accessors as determined by the @c -childrenAccessors method.
@return The number of children of the receiving function.
*/ */
- (NSUInteger)numberOfChildren; - (NSUInteger)numberOfChildren;
/*! /*!
@method childAtIndex: @method childAtIndex:
@brief Returns the child at the specified index. @abstract Returns the child at the specified index.
@discussion The ordering of children is determined by the order of the @discussion The ordering of children is determined by the order of the
children returned from the @c -childrenAccessors method. child accessors as returned from the
<code>@link childrenAccessors@/link</code> method.
@param index @param index
The index of the requested child. The index of the requested child.
@return The expression that corresponds to the child at @c index. @return The expression that corresponds to the child at
<code>index</code>.
*/ */
- (MPExpression *)childAtIndex:(NSUInteger)index; - (MPExpression *)childAtIndex:(NSUInteger)index;
/*! /*!
@method setChild:atIndex: @method setChild:atIndex:
@brief Sets the child at the specified index. @abstract Sets the child at the specified index.
@discussion Although this method does @b not call the respective accessor @discussion Although this method does <b>not</b> call the respective accessor
methods it behaves exactly as the setter method implemented using methods it behaves exactly as the setter method implemented using
the @c MPFunctionAccessorImplementation macro. the <code>@link MPFunctionAccessorImplementation@/link</code>
macro.
@param child @param child
The child that should replace the previous one. The child that should replace the previous one.
@@ -152,10 +189,10 @@
/*! /*!
@method children @method children
@brief Returns the receiver's children. @abstract Returns the receiver's children.
@discussion The ordering of the children is the same as in the array returned @discussion The ordering of the children is the same as in the array returned
from @c -childrenAccessors. from <code>@link childrenAccessors@/link</code>.
@return An array containing all the function's children. @return An array containing all the function's children.
*/ */
@@ -164,27 +201,29 @@
/*! /*!
@method indexOfChild: @method indexOfChild:
@brief Returns the index of @c child in the receiver. @abstract Returns the index of <code>child</code> in the receiver.
@param child @param child
The child to be searched. The child to be searched.
@return The index of @c child or @c NSNotFound if none of the receiver's @return The index of <code>child</code> or <code>NSNotFound</code> if
children is equal to @c child. none of the receiver's children is equal to <code>child</code>.
*/ */
- (NSUInteger)indexOfChild:(MPExpression *)child; - (NSUInteger)indexOfChild:(MPExpression *)child;
/*! /*!
@method elementAtIndexPath: @method elementAtIndexPath:
@brief Returns the element at the specified index path. @abstract Returns the element at the specified index path.
@discussion This method @em walks down the expression tree (including other @discussion This method finds the elements at the respective indexes starting
functions) using the specified index path and finds the at the root expression from the receiver's expression tree.
corresponding element. The returned object can be an @c NSString, The returned object can be a <code>NSString</code>, a
a @c MPFunction or an @c MPExpression depending on the element @c <code>MPFunction</code> or a <code>@link
indexPath points to. If any of the indexes exceed the bounds of MPExpression@/link</code> instance depending on the specified
the respective receiver an @c NSRangeException is raised. <code>indexPath</code>. If any of the indexes exceed the bounds
of the respective receiver a <code>NSRangeException</code> is
raised.
If the index path does not contain any indexes the receiver If the index path does not contain any indexes the receiver
itself is returned. itself is returned.
@@ -193,9 +232,10 @@
The index path the required object is located at. The indexes are The index path the required object is located at. The indexes are
expressed in the element reference frame. expressed in the element reference frame.
@return The element located at @c indexPath. The element is not copied @return The element located at <code>indexPath</code>. The element is not
before it is returned. Be aware of the fact that any mutations copied before it is returned. Be aware of the fact that any
made to the returned object are reflected in the receiver. mutations made to the returned object will update the receiver's
expression tree to reflect the change.
*/ */
- (id)elementAtIndexPath:(NSIndexPath *)indexPath; - (id)elementAtIndexPath:(NSIndexPath *)indexPath;
@@ -208,11 +248,11 @@
/*! /*!
@method didChangeElementsInRangePath:replacementLength: @method didChangeElementsInRangePath:replacementLength:
@brief Notification method that is called if one of the children was @abstract This Notification message is sent automatically from the receiver
mutated. to itself if one of its children was mutated or changed.
@discussion This method is also called when one of the children is changed @discussion This method should also be called when one of the children is
via one of the accessor methods. changed via one of the accessor methods.
@param rangePath @param rangePath
The location of the change that happened. Because it may have The location of the change that happened. Because it may have
@@ -229,12 +269,13 @@
/*! /*!
@method didChangeChildAtIndex: @method didChangeChildAtIndex:
@brief Convenience method that calls @c @abstract Convenience method that calls
-didChangeElementsInRangePath:replacementLength: <code>@link
didChangeElementsInRangePath:replacementLength:@/link</code>
@discussion This method is automatically called when one of the children is @discussion This method is automatically called when one of the children is
changed using one of the accessor methods or @c changed using one of the accessor methods or
-setChild:atIndex:. <code>@link setChild:atIndex:@/link</code>.
@param index @param index
The index of the child that was changed. The index of the child that was changed.
@@ -250,20 +291,21 @@
/*! /*!
@method expectsVariableDefinitionInChildAtIndex: @method expectsVariableDefinitionInChildAtIndex:
@brief Returns whether the child at @c anIndex is supposed to contain a @abstract Returns whether the child at <code>anIndex</code> is supposed to
variable definition. contain a variable definition.
@discussion This method is automatically called during expression parsing. @discussion This method is automatically called during the parsing process.
You can override this method to opt into the default behaviour. You can override this method to opt into the default behaviour.
If you override this method you do not need to call super. If you override this method you do not need to call super.
The default implementation just returns @c NO for every index. The default implementation just returns <code>NO</code> for every
index.
@param anIndex @param anIndex
The index of the child to check. The index of the child to check.
@return @c YES if the child at @c anIndex is supposed to contain a @return <code>YES</code> if the child at <code>anIndex</code> is supposed
variable definition, @c NO otherwise. to contain a variable definition, <code>NO</code> otherwise.
*/ */
- (BOOL)expectsVariableDefinitionInChildAtIndex:(NSUInteger)anIndex; - (BOOL)expectsVariableDefinitionInChildAtIndex:(NSUInteger)anIndex;
@@ -272,22 +314,16 @@
/*! /*!
@category MPFunction (MPSubcalssOverride) @category MPFunction (MPSubclassOverride)
@brief The methods in this category must be implemented by any concrete @abstract The methods in this category must be implemented by any concrete
subclasses of @c MPFunction. subclasses of <code>MPFunction</code>.
@discussion @c MPFunction does not implement the functions itself but calls @discussion <code>MPFunction</code> does not implement the functions itself but calls
them at various points. If a subclass does not provide them at various points. If a subclass does not provide
implementations your app will most likely crash. implementations your app will most likely crash.
*/ */
@interface MPFunction (MPSubclassOverride) @interface MPFunction (MPSubclassOverride)
/* In Addition to the methods listed below MPFunction subclasses should also
* override the NSObject method -description.
* Also -expectsVariabledefinitionInChildAtIndex: can be overridden if one of the
* children should contain a variable definition.
*/
#pragma mark Working With the Expression Tree #pragma mark Working With the Expression Tree
/*! /*!
@methodgroup Working With the Expression Tree @methodgroup Working With the Expression Tree
@@ -296,11 +332,9 @@
/*! /*!
@method childrenAccessors @method childrenAccessors
@brief Returns the names of the children properties. @abstract Returns the names of the children properties as strings.
@discussion A @c MPFunction subclass should declare a public propertiy for @discussion All objects in the returned array must be strings.
every child it can have. This method should return the names as
they would be used for key-value-coding.
@return An array of strings describing the names of children a function @return An array of strings describing the names of children a function
has. has.
@@ -316,14 +350,18 @@
/*! /*!
@method functionTermClass @method functionTermClass
@brief Returns the class that represents the receiver's evaluation @abstract Returns the class that represents the receiver's evaluation
behaviour. behaviour.
@discussion The class returned must be a subclass of @c MPFunctionTerm. That @discussion Subclasses of <code>MPFunction</code> can (like
class must not implement a custom initializer. <code>@link MPExpression@/link</code>) not evaluate themselves.
Instead this method is called on every function. The returned
class must be a valid subclass of <code>@link
//apple_ref/occ/cl/MPFunctionTerm@/link</code>. It will be
instanciated using the <code>init</code> method.
@return The @c MPFunctionTerm subclass that can evaluate instances of the @return The <code>@link //apple_ref/occ/cl/MPFunctionTerm@/link</code>
receiver's class. subclass that can evaluate instances of the receiver's class.
*/ */
- (Class)functionTermClass; - (Class)functionTermClass;

View File

@@ -13,10 +13,30 @@
@class MPNegatedTerm; @class MPNegatedTerm;
/*!
@class MPNegatedTerm
@abstract A negated term is a term whose value is multiplied by
<code>-1</code>.
*/
@interface MPNegatedTerm : MPTerm @interface MPNegatedTerm : MPTerm
/*!
@method initWithTerm:
@abstract Initializes a new negated term.
@param term
The term the receiver is to be initialized with.
@return A new negated term.
*/
- (instancetype)initWithTerm:(MPTerm *)term; /* designated initializer */ - (instancetype)initWithTerm:(MPTerm *)term; /* designated initializer */
/*!
@property term
@abstract The receiver's term.
*/
@property (readonly, nonatomic, strong) MPTerm *term; @property (readonly, nonatomic, strong) MPTerm *term;
@end @end

View File

@@ -15,21 +15,21 @@
/*! /*!
@class MPParenthesisFunction @class MPParenthesisFunction
@brief A parenthesis function encapsulates a single expression and thus @abstract A parenthesis function encapsulates a single expression and thus
prioritizes it in evaluation. prioritizes it in evaluation.
@discussion Prioritizing the expression means that the complete expression @discussion Prioritizing the expression means that the complete expression
must be evaluated 'as is'. No part of it can be 'used' elsewhere must be evaluated <i>as is</i>. No part of it can be <i>used</i>
before the parenthesis function has been evaluated. elsewhere before the parenthesis function has been evaluated.
*/ */
@interface MPParenthesisFunction : MPFunction @interface MPParenthesisFunction : MPFunction
/*! /*!
@property expression @property expression
@brief The expression encapsulated by the parenthesis. @abstract The expression encapsulated by the parenthesis.
@discussion The expression must not define a variable. @discussion The expression must not define a variable.
*/ */
@property (nonatomic, strong) MPExpression *expression; @property (nonatomic, strong) MPExpression *expression; /* Index 0 */
@end @end

View File

@@ -13,24 +13,97 @@
/*! /*!
@const MPMathKitErrorDomain @const MPMathKitErrorDomain
@brief Predefined error domain for errors from the MathKit framework. @abstract Predefined error domain for errors from the MathKit framework.
@discussion Errors in MathKit can occur during parsing of expressions or @discussion Errors in MathKit can occur during parsing or evaluation of
during evaluation of expressions. These two can be distinguished expressions. These two can be distinguished by their respective
by the error code. Parsing errors have lower error codes. error codes. Parsing errors have error codes below
Evaluation errors (math errors) have error codes from @c 100 upwards. <code>100</code>. Evaluation errors (math errors) on the other
hand have error codes from <code>100</code> upwards.
*/ */
FOUNDATION_EXPORT NSString *const MPMathKitErrorDomain; FOUNDATION_EXPORT NSString *const MPMathKitErrorDomain;
/*!
@const MPPathToExpressionKey
@abstract Predefined key for the path to the expression that caused an error.
@discussion Parsing errors in the <code>MPMathKitErrorDomain</code> have a
value for this key in their <code>userInfo</code> dictionary. The
value is of type <code>NSIndexPath</code>. The root of that path
is also the root expression of the expression tree of the
expression that was parsed (which in turn caused an error).
*/
FOUNDATION_EXPORT NSString *const MPPathToExpressionKey; FOUNDATION_EXPORT NSString *const MPPathToExpressionKey;
/*!
@const MPErrorRangeKey
@abstract Predefined key for the range inside an expression that caused a
parsing error.
@discussion Parsing errors in the <code>MPMathKitErrorDomain</code> have a
value for this key in their <code>userInfo</code> dictionary. The
value is a <code>NSRange</code> value wrapped in a
<code>NSValue</code> object.
*/
FOUNDATION_EXPORT NSString *const MPErrorRangeKey; FOUNDATION_EXPORT NSString *const MPErrorRangeKey;
/*!
@class MPParsedExpression
@abstract A parsed expression represents an expression whose syntax is
mathematically valid and thus can be evaluated.
@discussion This class should not be instanciated directly. Instead you
should use the <code>parse...</code> methods from the <code>@link
//apple_ref/occ/cl/MPExpression@/link</code> class. A
successfully parsed expression can still fail to be evaluated if
it contains mathematically undefined expressions.
*/
@interface MPParsedExpression : NSObject @interface MPParsedExpression : NSObject
/*!
@property definedVariable
@abstract The variable defined by the expression, if any.
@discussion If a variable was defined this property is a string of length
<code>1</code> containing the name of that variable. If no
variable was defined this property is <code>nil</code>.
This property should not be set manually.
*/
@property (nonatomic, strong) NSString *definedVariable; @property (nonatomic, strong) NSString *definedVariable;
/*!
@property term
@abstract The receiver's evaluatable term.
@discussion The term may still contain mathematicall undefined expressions.
This property should not be set manually.
*/
@property (nonatomic, strong) MPTerm *term; @property (nonatomic, strong) MPTerm *term;
/*!
@method evaluate:
@abstract Evaluates the receiver.
@discussion This method is a convenience method for evaluating the receiver's
<code>@link
//apple_ref/occ/intfp/MPParsedExpression/term@/link</code>.
@param error
If an error occured during evaluation it will be returned
indirectly through this parameter. If you are not interested in
errors pass <code>NULL</code>.
@return A <code>NSDecimalNumber</code> containing the result of the
evaluation. Depending on the evaluated expression the result may
only be of double precision.
*/
- (NSDecimalNumber *)evaluate:(NSError *__autoreleasing *)error; - (NSDecimalNumber *)evaluate:(NSError *__autoreleasing *)error;
@end @end

View File

@@ -15,18 +15,18 @@
/*! /*!
@class MPPowerFunction @class MPPowerFunction
@brief This class represents a power. @abstract This class represents a power.
*/ */
@interface MPPowerFunction : MPFunction @interface MPPowerFunction : MPFunction
/*! /*!
@property exponentExpression @property exponentExpression
@brief The receiver's exponent. @abstract The receiver's exponent.
@discussion The base of the power can only be set during evaluation because @discussion The base of the power can only be set during evaluation because
it is not actually part of the function element. it is not actually part of the function element.
The exponent must not define a variable. The exponent must not define a variable.
*/ */
@property (nonatomic, strong) MPExpression *exponentExpression; @property (nonatomic, strong) MPExpression *exponentExpression; /* Index 0 */
@end @end

View File

@@ -13,10 +13,45 @@
@class MPProductTerm; @class MPProductTerm;
/*!
@class MPProductTerm
@abstract A product term consists of n terms that are multiplied together.
@discussion Although they are mutliplied in order of occurrence the child
terms should be considered having equal priority.
*/
@interface MPProductTerm : MPTerm @interface MPProductTerm : MPTerm
/*!
@method initWithFactors:
@abstract Initializes a new product term with the specified
<code>factors</code>.
@discussion There is very little checking performed during initialization.
All objects in the specified array must be valid instances of
subclasses of <code>@link //apple_ref/occ/cl/MPTerm@/link</code>.
The array must contain at least one object.
@param factors
The factors the product term should be initialized with. The
array must not be <code>nil</code> and must contain at least one
object. The contents of the array are not copied, the array
itself however is.
@return A new sum term.
*/
- (instancetype)initWithFactors:(NSArray *)factors; /* designated initializer */ - (instancetype)initWithFactors:(NSArray *)factors; /* designated initializer */
/*!
@property factors
@abstract The receiver's factors.
@discussion This property is guaranteed to be non <code>nil</code>. The
contents of the array are specified during initialization of the
receiver.
*/
@property (readonly, nonatomic, strong) NSArray *factors; @property (readonly, nonatomic, strong) NSArray *factors;
@end @end

View File

@@ -28,7 +28,7 @@
if (self) { if (self) {
NSAssert(factors != nil, @"factors must not be nil."); NSAssert(factors != nil, @"factors must not be nil.");
NSAssert(factors.count > 0, @"factors must not be empty."); NSAssert(factors.count > 0, @"factors must not be empty.");
_factors = factors; _factors = factors.copy;
} }
return self; return self;
} }

View File

@@ -9,8 +9,30 @@
#import "MPExpression.h" #import "MPExpression.h"
/*!
@header
The <code>MPRangePath</code> combines an <code>NSIndexPath</code> with a
<code>NSRange</code>. A range path is used in a tree structure to identify a
number of subsequent nodes. This is achieved by combining a range path that
stores the location of the first node in the tree with an integer that stores
the number of nodes that should be included in the range path.
*/
/// Convenience Constructor Macro
/*!
@define MPMakeRangePath
@abstract Creates a new <code>NSRangePath</code> instance with the given
location and length.
@param loc
The location of the first included item. This must be an
<code>NSIndexPath</code> instance.
@param len
The number of nodes to include in the range path.
@return A new range path.
*/
#define MPMakeRangePath(loc, len) [MPRangePath rangePathWithLocation:(loc) length:(len)] #define MPMakeRangePath(loc, len) [MPRangePath rangePathWithLocation:(loc) length:(len)]
@@ -19,19 +41,13 @@
/*! /*!
@class MPRangePath @class MPRangePath
@brief @c MPRangePath is like @c NSRange but with an @c NSIndexPath as @abstract A <code>MPRangePath</code> instance identifies a range of
location. subsequent nodes in a tree structure.
@discussion Range paths are intended to address a range (as defined by @c @discussion <code>MPRangePath</code> instances are immutable.
NSRange) that resides in a tree structure. Thus the @c location
property of a range path is a @c NSIndexPath.
@c MPRangePath instances are immutable.
*/ */
@interface MPRangePath : NSObject <NSCopying, NSCoding> @interface MPRangePath : NSObject <NSCopying, NSCoding>
#pragma mark Creation Methods #pragma mark Creation Methods
/*! /*!
@methodgroup Creation Methods @methodgroup Creation Methods
@@ -40,39 +56,40 @@
/*! /*!
@method init @method init
@brief Initializes an empty range path. @abstract Initializes an empty range path.
@discussion This method is a convenience initializer to create a range path with @discussion This method is a convenience initializer to create a range path
an empty location and a length of @c 0. with an empty location and a length of <code>0</code>.
@return A @c MPRangePath instance. @return A new <code>MPRangePath</code> instance.
*/ */
- (instancetype)init; - (instancetype)init;
/*! /*!
@method initWithRange: @method initWithRange:
@brief Initializes a newly created range path with the specified range. @abstract Initializes a newly created range path with the specified range.
@discussion This method is a convenience initializer to convert from a @c @discussion This method is a convenience initializer to convert from a
NSRange to a @c MPRangePath. The location of @c aRange is <code>NSRange</code> struct to a <code>MPRangePath</code>
translated into a location for the range path. instance. The location of the created range path is an index path
of length <code>1</code>.
@param aRange @param aRange
The range to be converted into a @c MPRangePath. The range to be converted into a <code>MPRangePath</code>.
@return A @c MPRangePath instance. @return A <code>MPRangePath</code> instance.
*/ */
- (instancetype)initWithRange:(NSRange)aRange; - (instancetype)initWithRange:(NSRange)aRange;
/*! /*!
@method initWithLocation:lenght: @method initWithLocation:lenght:
@brief Initializes a newly created range path with the specified location @abstract Initializes a newly created range path with the specified location
and length. and length.
@discussion The last index in the @c location should address the first item @discussion The last index in the <code>location</code> addresses the first
that is actually selected. item that is actually selected.
@param location @param location
The location of the first element that should be addressed by The location of the first element that should be addressed by
@@ -81,7 +98,7 @@
@param length @param length
The number of elements to be addressed by this range path. The number of elements to be addressed by this range path.
@return A @c MPRangePath instance. @return A <code>MPRangePath</code> instance.
*/ */
- (instancetype)initWithLocation:(NSIndexPath *)location - (instancetype)initWithLocation:(NSIndexPath *)location
length:(NSUInteger)length; /* designated initializer */ length:(NSUInteger)length; /* designated initializer */
@@ -89,36 +106,37 @@
/*! /*!
@method rangePath @method rangePath
@brief Allocates and initializes an empty @c NSRangePath instance. @abstract Allocates and initializes an empty <code>NSRangePath</code>
instance.
@discussion An empty range path's location has @c 0 indexes and a length of @discussion An empty range path's location has <code>0</code> indexes and a
@c 0. length of <code>0</code>.
@return A newly created @c MPRangePath instance. @return A newly created <code>MPRangePath</code> instance.
*/ */
+ (instancetype)rangePath; + (instancetype)rangePath;
/*! /*!
@method rangePathWithRange: @method rangePathWithRange:
@brief Allocates a new @c MPRangePath instance and initializes it with @abstract Allocates a new <code>MPRangePath</code> instance and initializes
the specified location and length. it with the specified location and length.
@discussion The location of @c aRange is translated into an index path for @discussion The location of <code>aRange</code> is translated into an index
the range path. path for the range path.
@param aRange @param aRange
The range to be converted into a range path. The range to be converted into a range path.
@return A newly created @c MPRangePath instance. @return A newly created <code>MPRangePath</code> instance.
*/ */
+ (instancetype)rangePathWithRange:(NSRange)aRange; + (instancetype)rangePathWithRange:(NSRange)aRange;
/*! /*!
@method rangePathWithLocation:length: @method rangePathWithLocation:length:
@brief Allocates a new @c MPRangePath instance and initializes it with @abstract Allocates a new <code>MPRangePath</code> instance and initializes
the specified location and length. it with the specified location and length.
@param location @param location
The location of the first element that should be addressed by the The location of the first element that should be addressed by the
@@ -128,7 +146,7 @@
The number of elements that should be addressed by the range The number of elements that should be addressed by the range
path. path.
@return A newly created @c MPRangePath instance. @return A newly created <code>MPRangePath</code> instance.
*/ */
+ (instancetype)rangePathWithLocation:(NSIndexPath *)location + (instancetype)rangePathWithLocation:(NSIndexPath *)location
length:(NSUInteger)length; length:(NSUInteger)length;
@@ -142,35 +160,36 @@
/*! /*!
@property location @property location
@brief The location of the first element addressed by the receiver. @abstract The location of the first element addressed by the receiver.
*/ */
@property (readonly, nonatomic, strong) NSIndexPath *location; @property (readonly, nonatomic, strong) NSIndexPath *location;
/*! /*!
@property length @property length
@brief The number of elements addressed by the receiver. The element @abstract The number of elements addressed by the receiver. The element
addressed by the last index of the location property plus the addressed by the last index of the location property plus the
length of the receiver is NOT considered inside of the range length of the receiver is <b>not</b> considered inside of the
path. range path.
*/ */
@property (readonly, nonatomic) NSUInteger length; @property (readonly, nonatomic) NSUInteger length;
/*! /*!
@method maxRangePath @method maxRangePath
@brief Similar to the @c NSRange method @c NSMaxRange this method @abstract Similar to the <code>NSRange</code> function
returns the first index after the receiving @c NSRangePath. <code>NSMaxRange</code> this method returns the first index after
the receiving <code>NSRangePath</code>.
@return The first index after the receiving @c NSRangePath. @return The first index after the receiving <code>NSRangePath</code>.
*/ */
- (NSIndexPath *)maxRangePath; - (NSIndexPath *)maxRangePath;
/*! /*!
@method rangeAtLastIndex @method rangeAtLastIndex
@brief Returns a @c NSRange constructed from the last index of the @abstract Returns a <code>NSRange</code> constructed from the last index of
receiver's location and the receiver's length. the receiver's location and the receiver's length.
@return The range identifying the elements at the last index in the @return The range identifying the elements at the last index in the
receiver's index path. receiver's index path.
@@ -186,57 +205,60 @@
/*! /*!
@method containsLocation: @method containsLocation:
@brief Checks wether the range path addressed by the receiver includes @abstract Checks wether the range path addressed by the receiver includes
@c location. <code>location</code>.
@discussion The index path is considered inside the receiver if the indexes @discussion The index path is considered inside the receiver if the indexes
in the receiver's @c location property are equal to the in the receiver's <code>location</code> property are equal to the
respective indexes index in @c location. For the last position of respective indexes index in <code>location</code>. For the last
the last index of the receiver's @c location it is also valid if position of the last index of the receiver's
the respective index is inside the range at the last index. <code>location</code> it is also valid if the respective index is
inside the range at the last index.
@param location @param location
The index path to check wether it is contained in the receiver. The index path to check wether it is contained in the receiver.
@return @c YES if the range path addressed by the receiver also contains @return <code>YES</code> if the range path addressed by the receiver also
@c location, @c NO otherwise. contains <code>location,</code> <code>NO</code> otherwise.
*/ */
- (BOOL)containsLocation:(NSIndexPath *)location; - (BOOL)containsLocation:(NSIndexPath *)location;
/*! /*!
@method containsRangePath: @method containsRangePath:
@brief Checks wether the receiver completely contains @c aRangePath. @abstract Checks wether the receiver completely contains
<code>aRangePath</code>.
@discussion A range path is contained by another range path if either the @discussion A range path is contained by another range path if either the
receiver's range at its last index contains the index at the receiver's range at its last index contains the index at the
respective location of the location path of @c aRangePath or (if respective location of the location path of
the locations are of the same length) the receiver's range at its <code>aRangePath</code> or (if the locations are of the same
last index contains the last index's range of @c aRangePath. length) the receiver's range at its last index contains the last
index's range of <code>aRangePath</code>.
@param aRangePath @param aRangePath
The range path to check wether it is contained in the receiver. The range path to check wether it is contained in the receiver.
@return @c YES if the range path addressed by the receiver also includes @return <code>YES</code> if the range path addressed by the receiver also
@c aRangePath, @c NO otherwise. includes <code>aRangePath,</code> <code>NO</code> otherwise.
*/ */
- (BOOL)containsRangePath:(MPRangePath *)aRangePath; - (BOOL)containsRangePath:(MPRangePath *)aRangePath;
/*! /*!
@method isEqualToRangePath: @method isEqualToRangePath:
@brief Checks wether the receiver and @c aRangePath are equal. @abstract Checks wether the receiver and <code>aRangePath</code> are equal.
@discussion If you know that you are comparing two range paths (that are not @discussion If you know that you are comparing two range paths (that are not
@c nil) you should use this method over @c -isEqual: because it <code>nil</code>) you should prefer this method over
is more performant. <code>isEqual:</code> because it is more performant.
@param aRangePath @param aRangePath
The range path to check for equality. If this parameter is @c nil The range path to check for equality. If this parameter is
this method may raise an exception. <code>nil</code> this method may raise an exception.
@return @c YES if the receiver is equal to @c aRangePath, @c NO @return <code>YES</code> if the receiver is equal to
otherwise. <code>aRangePath</code>, <code>NO</code> otherwise.
*/ */
- (BOOL)isEqualToRangePath:(MPRangePath *)aRangePath; - (BOOL)isEqualToRangePath:(MPRangePath *)aRangePath;
@@ -249,15 +271,15 @@
/*! /*!
@method subexpressionWithRangePath: @method subexpressionWithRangePath:
@brief Creates a new expression with the symbols in the specified range @abstract Creates a new expression with the symbols in the specified range
path. path.
@discussion The elements in the newly created expression are copied to the @discussion The elements in the newly created expression are copied to the
new exoression. The range path is specified in the length new exoression. The range path is specified in the length
reference frame. reference frame.
If the specified range exceeds the receiver's bounds a @c If the specified range exceeds the receiver's bounds a
NSRangeException is raised. <code>NSRangeException</code> is raised.
@param aRangePath @param aRangePath
The range path from which to create the new expression. The range path from which to create the new expression.
@@ -270,23 +292,30 @@
/*! /*!
@method replaceItemsInRangePath:referenceFrame:withElements: @method replaceItemsInRangePath:referenceFrame:withElements:
@brief Replaces the items in the specified range path with the contents @abstract Replaces the items in the specified range path with the contents
of @c elements. of <code>elements</code>.
@discussion All objects in the @c elements array must conform to the @c @discussion All objects in the <code>elements</code> array must conform to
MPExpressionElement protocol. If one or more objects do not the <code>@link
conform to the protocol a @c MPIllegalElementException will be //apple_ref/occ/intf/MPExpressionElement@/link</code> protocol.
If one or more objects do not conform to the protocol a
<code>@link
//apple_ref/c/data/MPIllegalElementException@/link</code> is
raised. raised.
@param rangePath @param rangePath
The range path to be replaced. The path of the range path is The range path to be replaced. The location of the range path
expressed in the element reference frame. The range of the range (except for the last index) is expressed in the element reference
path is expressed in the specified @c referenceFrame. frame. The range of the range path is expressed in the specified
<code>referenceFrame</code>.
@param referenceFrame @param referenceFrame
The reference frame to use. This only applies to the range at the The reference frame to use. This only applies to the range at the
last index of the range path. The path of the range path is last index of the range path. The path of the range path is
always expressed in the element reference frame. always expressed in the element reference frame.
@param elements
The elements replacing the ones in the specified range path.
*/ */
- (void)replaceItemsInRangePath:(MPRangePath *)rangePath - (void)replaceItemsInRangePath:(MPRangePath *)rangePath
referenceFrame:(MPReferenceFrame)referenceFrame referenceFrame:(MPReferenceFrame)referenceFrame

View File

@@ -6,13 +6,6 @@
// Copyright (c) 2014 Kim Wittenburg. All rights reserved. // Copyright (c) 2014 Kim Wittenburg. All rights reserved.
// //
/*!
@header
This is a description of the MPFunction class.
It has multiple lines.
*/
#import "MPFunction.h" #import "MPFunction.h"
@@ -22,7 +15,7 @@
/*! /*!
@class MPSumFunction @class MPSumFunction
@brief This class represents a sum function (generally noted using a @abstract This class represents a sum function (generally noted using a
capital sigma). capital sigma).
@discussion A sum function has a start and a target expression indicating how @discussion A sum function has a start and a target expression indicating how
@@ -30,28 +23,26 @@
the start expression and the target expressions are included in the start expression and the target expressions are included in
the iterations. the iterations.
Each iteration the sum value is incremented by @c 1. If the start Each iteration the sum value is incremented by <code>1</code>. If
and target expression evaluate to the same value the sum is the start and target expression evaluate to the same value the
evaluated once. sum is evaluated once.
*/ */
@interface MPSumFunction : MPFunction @interface MPSumFunction : MPFunction
/*! /*!
@property startExpression @property startExpression
@brief The value of the first iteration. @abstract The value of the first iteration.
@discussion The start expression must define a variable that may be used in @discussion The start expression must define a variable that may be used in
the sum expression. If the start expression does not define a the sum expression. If the start expression does not define a
variable the sum function will fail on validation. variable the sum function will fail on validation.
@code Some samples
*/ */
@property (nonatomic, strong) MPExpression *startExpression; /* Index 0 */ @property (nonatomic, strong) MPExpression *startExpression; /* Index 0 */
/*! /*!
@property targetExpression @property targetExpression
@brief The value if the last iteration. @abstract The value if the last iteration.
@discussion The target expression must not define a variable. @discussion The target expression must not define a variable.
*/ */
@@ -60,7 +51,7 @@
/*! /*!
@property sumExpression @property sumExpression
@brief The sum expression evaluated multiple times. @abstract The sum expression evaluated multiple times.
@discussion During evaluation of the sum expression the variable defined in @discussion During evaluation of the sum expression the variable defined in
the start expression is available. That variable always contains the start expression is available. That variable always contains

View File

@@ -13,11 +13,44 @@
@class MPSumTerm; @class MPSumTerm;
/*!
@class MPSumTerm
@abstract A sum term consists of n terms that are added together.
@discussion Although they are added in order of occurrence the child terms
should be considered having equal priority.
*/
@interface MPSumTerm : MPTerm @interface MPSumTerm : MPTerm
/*!
@method initWithSummands:
@abstract Initializes a new sum term with the specified <code>summands</code>.
@discussion There is very little checking performed during initialization.
All objects in the specified array must be valid instances of
subclasses of <code>@link //apple_ref/occ/cl/MPTerm@/link</code>.
The array must contain at least one object.
@param summands
The summands the sum term should be initialized with. The array
must not be <code>nil</code> and must contain at least one
object. The contents of the array are not copied, the array
itself however is.
@return A new sum term.
*/
- (instancetype)initWithSummands:(NSArray *)summands; /* designated initializer */ - (instancetype)initWithSummands:(NSArray *)summands; /* designated initializer */
@property (readonly, nonatomic, strong) NSArray *summands;
/*!
@property summands
@abstract The receiver's summands.
@discussion This property is guaranteed to be non <code>nil</code>. The
contents of the array are specified during initialization of the
receiver.
*/
@property (readonly, nonatomic, copy) NSArray *summands;
@end @end

View File

@@ -21,7 +21,7 @@
if (self) { if (self) {
NSAssert(summands != nil, @"summands must not be nil."); NSAssert(summands != nil, @"summands must not be nil.");
NSAssert(summands.count > 0, @"summands must not be empty."); NSAssert(summands.count > 0, @"summands must not be empty.");
_summands = summands; _summands = summands.copy;
} }
return self; return self;
} }

View File

@@ -6,23 +6,194 @@
// Copyright (c) 2014 Kim Wittenburg. All rights reserved. // Copyright (c) 2014 Kim Wittenburg. All rights reserved.
// //
/*!
@header
The <code>MPTerm</code> class is used to evaluate a mathematical expression. A
term is a purely mathematical representation of a part of an expression. A term
can be defined with three rules:
1. A number is a term.
2. A variable is a term.
3. A connection of terms with zero or more symbols is also a term.
Every mathematical operation (term) is defined in terms of a concrete subclass
of <code>MPTerm</code> and sub-terms (children). For example the expression
<code>2+3⋅4</code> would be a @link //apple_ref/occ/cl/MPSumTerm sum term@/link
with two children: A @link //apple_ref/occ/cl/MPNumber number@/link and a @link
//apple_ref/occ/cl/MPProductTerm product term@/link. The product term in turn
has two children which are both numbers.
Subclasses should do the following:
1. Subclasses must implement the <code>@link doEvaluation:@/link</code> method.
2. Subclasses should be immutable and thus define <code>readonly</code>
accessors for any children as well as an <code>init</code> method that
supplies the necessary values.
If a term has children that define variables to be used in one or more of the
other children <code>MPTerm</code> offers methods for defining, accessing and
undefining variable values. Because a term can not define variables that are
accessible in any of its sibling or parent terms all variables defined in a term
are automatically undefined when the term is finished evaluating.
*/
/*!
@define ReturnIfNil
@abstract This macro returns a <code>value</code> if a <code>test</code>
object is <code>nil</code>.
@param test
The object to be tested. If this parameter is <code>nil</code>
the macro returns <code>value</code>.
@param value
The value to be returned if <code>test</code> is
<code>nil</code>.
*/
#define ReturnIfNil(test, value) if (test == nil) return value #define ReturnIfNil(test, value) if (test == nil) return value
/*!
@define ReturnNilIfNil
@abstract This macro returns <code>nil</code> if a <code>test</code> object
is <code>nil</code>.
@param test
The object to be tested. If this parameter is <code>nil</code>
the macro returns <code>nil</code>.
*/
#define ReturnNilIfNil(test) if (test == nil) return nil #define ReturnNilIfNil(test) if (test == nil) return nil
@class MPTerm; @class MPTerm;
/*!
@class MPTerm
@abstract <code>MPTerm</code> is a half abstract class that is the base
class for representing an evaluatable mathematical expression.
@discussion <code>MPTerm</code> should not be instanciated directly. Instead
one of the concrete subclasses should be used.
*/
@interface MPTerm : NSObject @interface MPTerm : NSObject
/*!
@method evaluate:
@abstract Evaluates the receiver.
@discussion The result of the evaluation is up to the concrete subclass of
<code>MPTerm</code>. Note however that subclasses should
<b>not</b> override this method. To implement the custom
evaluation behaviour implement the <code>@link
doEvaluation:@/link</code> method. To evaluate a term (including
children of terms) do use this method.
@param error
If an error occurs during evaluation it is indirecly returned
through this parameter. If you are not interested in errors, pass
<code>NULL</code>.
@return A <code>NSDecimalNumber</code> containing the result of the
evaluation. Depending on the term this should be double precision
or higher.
*/
- (NSDecimalNumber *)evaluate:(NSError *__autoreleasing *)error; - (NSDecimalNumber *)evaluate:(NSError *__autoreleasing *)error;
/*!
@method doEvaluation:
@abstract Performs the actual evaluation of the receiver.
@discussion This method must be implemented by subclasses but should never be
called directly. Call <code>@link evaluate:@/link</code> instead.
@param error
If an error occurs during evaluation it is indirecly returned
through this parameter. If you are not interested in errors, pass
<code>NULL</code>.
@return A <code>NSDecimalNumber</code> containing the result of the
evaluation. Depending on the term this should be double precision
or higher.
*/
- (NSDecimalNumber *)doEvaluation:(NSError *__autoreleasing *)error; - (NSDecimalNumber *)doEvaluation:(NSError *__autoreleasing *)error;
/*!
@method defineVariable:value:error:
@abstract Defines a variable in the shared evaluation context.
@discussion A defined variable is available until it is either undefined or
the end of the <code>@link doEvaluation:@/link</code> method is
reached at which point all variables defined in that method are
undefined automatically. If the <code>variableName</code> has
already been defined in the same method this method overwrites
the value for the variable. If it has been defined in the
evaluation method of a parent term this method fails and returns
<code>NO</code>.
@param variableName
The variable to be defined.
@param value
The value for the variable.
@param error
If <code>variableName</code> has already been defined in a parent
term this parameter is set to an error object that informs the
user about a variable redefinition. If you are not interested in
errors, pass <code>NULL</code>.
@return <code>YES</code> if the variable could be defined,
<code>NO</code> if it has previously been declared in a parent
term of the currently evaluated one.
*/
- (BOOL)defineVariable:(NSString *)variableName - (BOOL)defineVariable:(NSString *)variableName
value:(NSDecimalNumber *)value value:(NSDecimalNumber *)value
error:(NSError *__autoreleasing *)error; error:(NSError *__autoreleasing *)error;
/*!
@method valueForVariable:
@abstract Returns the value for a variable from the shared evaluation
context.
@discussion If <code>variableName</code> is not defined this method returns
<code>nil</code>. Normally you do not need to call this method
yourself.
@param variableName
The variable whose value is requested.
@param error
If <code>variableName</code> is not defined this parameter is set
to an error object that informs the user about an undefined
variable. If you are not interested in errors, pass
<code>NULL</code>.
@return The value associated with <code>variableName</code> or
<code>nil</code> if it is undefined.
*/
- (NSDecimalNumber *)valueForVariable:(NSString *)variableName - (NSDecimalNumber *)valueForVariable:(NSString *)variableName
error:(NSError *__autoreleasing *)error; error:(NSError *__autoreleasing *)error;
- (void)undefineVariable:(NSString *)variableName; // Should rarely be needed, defined variables are automatically undefined at the end of evaluation.
/*!
@method undefineVariable:
@abstract Removes <code>variableName</code> from the shared evaluation
context.
@discussion The variable is only removed if it exists and was defined in the
same evaluation method. Variables defined by parent terms can not
be undefined. Normally you do not need to call this method
yourself since all variables defined during the evaluation of a
term are automatically undefined afterwards.
@param variableName
The name of the variable to be undefined.
*/
- (void)undefineVariable:(NSString *)variableName;
@end @end

View File

@@ -22,12 +22,6 @@
return result; return result;
} }
- (NSDecimalNumber *)doEvaluation:(NSError *__autoreleasing *)error
{
NSLog(@"%@", self.class);
return nil;
}
- (BOOL)defineVariable:(NSString *)variableName - (BOOL)defineVariable:(NSString *)variableName
value:(NSDecimalNumber *)value value:(NSDecimalNumber *)value
error:(NSError *__autoreleasing *)error error:(NSError *__autoreleasing *)error

View File

@@ -7,6 +7,28 @@
// //
/*!
@header
One way to represent a mathematical expression using the <code>@link
MPExpression@/link</code> class is a sequence of tokens. A token is a logical
unit of input. The different types of units are identified by a @link
MPTokenType token type@/link. In the context of mathematical expressions this
can be for example numbers, variables or parenthesis.
A special token type is the <code>@link MPEOFToken@/link</code>. This is not an
actual token that can be found in an expression. It is used to simplify working
with tokens. If a token is <code>nil</code> you can still query its <code>@link
tokenType@/link</code> and compare it against this special token type. For
example:
<pre>
@textblock
while ((token = [self nextToken]).tokenType != MPEOFToken) {
// ...
}
@/textblock
</pre>
*/
@class MPToken; @class MPToken;
@protocol MPToken; @protocol MPToken;
@@ -14,15 +36,14 @@
/*! /*!
@typedef MPTokenType @typedef MPTokenType
@brief The type of a <code>token</code> identifies its behaviour in a mathematical @abstract The type of a token identifies its behaviour in a mathematical
context. context.
@constant MPEOFToken @constant MPEOFToken
A token that represents the end of the input. This token should A token that represents the end of the input. This token should
not be used to create a @c MPToken instance. It exists so that not be used to create an instance of the <code>@link
you can safely send a @c tokenType message to @c nil without //apple_ref/occ/cl/MPToken@/link</code> class. A token with this
getting confusing results. A token with this token type should be token type should be interpreted as <i>no token</i>.
interpreted as 'no token'.
@constant MPMultiplicationSymbolToken @constant MPMultiplicationSymbolToken
A multiplication symbol. A multiplication symbol.
@@ -31,35 +52,39 @@
A list of operators (+ and - symbols). The token may be longer A list of operators (+ and - symbols). The token may be longer
than the number of operators if there are spaces between them. than the number of operators if there are spaces between them.
@constant MPElementaryFunction @constant MPElementaryFunctionToken
@em Most elementary functions are represented by this token type. <i>Most</i> elementary functions are represented by this token
Elementary functions not categorized as such are those that can type. Elementary functions not categorized as such are those that
not be represented as text (e.g. roots and powers). can not be represented as text (e.g. roots and powers).
@constant MPNumberToken @constant MPNumberToken
A number. This may be an integer or a floating point number. A number. This may be an integer or a floating point number.
Floating point numbers contain a @c NSLocaleDecimalSeparator. Floating point numbers contain a
<code>NSLocaleDecimalSeparator</code>.
@constant MPVariableToken @constant MPVariableToken
A variable. A variable is exactly one character long. A variable. A variable is exactly one character long.
@constant MPFactorialToken @constant MPFactorialToken
The factorial symbol (!). The factorial symbol (an exclamation mark).
@constant MPEqualsToken @constant MPEqualsToken
The equals sign. The equals sign.
@constant MPGenericFunctionToken @constant MPGenericFunctionToken
A function represented by the @c MPFunction class. A token with A function represented by the <code>@link MPFunction@/link</code>
this token type is guaranteed to be a @c MPFunction instance. class. A token with this token type is guaranteed to be an
instance of the <code>@link MPFunction@/link</code> class.
@constant MPWhitespaceToken @constant MPWhitespaceToken
A whitespace. This token can typically be ignored. A whitespace. This token can typically be ignored.
@constant MPUnidentifiedToken @constant MPUnidentifiedToken
Any symbol that does not match any other token. Any symbol that does not match any other token. If this token is
found inside an expression the expression should be considered
invalid.
*/ */
typedef NS_ENUM(NSUInteger, MPTokenType) { typedef enum {
MPEOFToken = 0, MPEOFToken = 0,
MPMultiplicationSymbolToken, MPMultiplicationSymbolToken,
MPOperatorListToken, MPOperatorListToken,
@@ -74,24 +99,23 @@ typedef NS_ENUM(NSUInteger, MPTokenType) {
MPWhitespaceToken, MPWhitespaceToken,
MPUnidentifiedToken, MPUnidentifiedToken,
}; } MPTokenType;
/*! /*!
@protocol MPToken @protocol MPToken
@brief Tokens represent logical units in an expresion. @abstract Tokens represent logical units in an expresion.
*/ */
@protocol MPToken <NSObject> @protocol MPToken <NSObject>
/*! /*!
@method tokenType @method tokenType
@brief Returns the receiver's token type. @abstract Returns the receiver's token type.
@discussion The token type identifies what kind of token the receiver is. For @discussion The token type identifies what kind of token the receiver is.
more information see the documentation on the <code>MPTokenType Possible values are described in the <code>@link
</code> enum. MPTokenType@/link</code> enumeration.
@return The receiver's token type. @return The receiver's token type.
*/ */
@@ -100,7 +124,7 @@ typedef NS_ENUM(NSUInteger, MPTokenType) {
/*! /*!
@method range @method range
@brief Returns the receiver's range. @abstract Returns the receiver's range.
@discussion The range identifies where the token is in the expression. It is @discussion The range identifies where the token is in the expression. It is
specified in the symbol reference frame. specified in the symbol reference frame.
@@ -113,12 +137,12 @@ typedef NS_ENUM(NSUInteger, MPTokenType) {
/*! /*!
@method stringValue @method stringValue
@brief The string that caused the token to be parsed. @abstract The string that caused the token to be parsed.
@discussion Depending on the type of the token the string value can have a @discussion Depending on the type of the token the string value can have a
fixed or variable length. For example the equals token always has fixed or variable length. For example the equals token always has
a length of @c 1 whereas a number or whitespace token can be much a length of <code>1</code> whereas a number or whitespace token
longer. can be much longer.
@return The receiver's string value. @return The receiver's string value.
*/ */
@@ -130,16 +154,16 @@ typedef NS_ENUM(NSUInteger, MPTokenType) {
/*! /*!
@class MPToken @class MPToken
@brief The @c MPToken class implements the functionality of the @c @abstract The <code>MPToken</code> class implements the functionality of
MPToken protocol. Most tokens are instances of the @c MPToken the <code>@link //apple_ref/occ/intf/MPToken@/link</code>
protocol. Most tokens are instances of the <code>MPToken</code>
class. class.
*/ */
@interface MPToken : NSObject <MPToken> @interface MPToken : NSObject <MPToken>
/*! /*!
@method initWithTokenType:range:stringValue: @method initWithTokenType:range:stringValue:
@brief Creates a new @c MPToken instance. @abstract Creates a new <code>MPToken</code> instance.
@param tokenType @param tokenType
The type of the token. The type of the token.

View File

@@ -7,7 +7,7 @@
// //
#import "MPExpression.h" #import "MPExpression.h"
#import "MPExpressionElement.h" #import "MPExpression.h"
#import "NSString+MPExpressionElement.h" #import "NSString+MPExpressionElement.h"
#import "MPFunction.h" #import "MPFunction.h"

View File

@@ -8,48 +8,53 @@
/*!
@category NSIndexPath (MPAdditions)
@abstract This category adds some methods for working with index paths to
the <code>NSIndexPath</code> class.
*/
@interface NSIndexPath (MPAdditions) @interface NSIndexPath (MPAdditions)
/*! /*!
@property firstIndex @property firstIndex
@brief The first index from the index path. @abstract The first index from the receiver.
@discussion If the index path is empty @c NSNotFound is returned. @discussion If the receiver is empty <code>NSNotFound</code> is returned.
*/ */
@property (readonly, nonatomic) NSUInteger firstIndex; @property (readonly, nonatomic) NSUInteger firstIndex;
/*! /*!
@property lastIndex @property lastIndex
@brief The last index from the index path. @abstract The last index from the receiver.
@discussion If the index path is empty @c NSNotFound is returned. @discussion If the receiver is empty <code>NSNotFound</code> is returned.
*/ */
@property (readonly, nonatomic) NSUInteger lastIndex; @property (readonly, nonatomic) NSUInteger lastIndex;
/*! /*!
@method indexPathByReplacingLastIndexWithIndex: @method indexPathByReplacingLastIndexWithIndex:
@brief Provides an index path with the index in the receiving index path @abstract Provides an index path with the indexes of the receiver where the
where the last one is replaced by @c index. last one is replaced by <code>anIndex</code>.
@discussion If the receiving index path is empty an index path of length @c 1 @discussion If the receiver is empty an index path of length <code>1</code>
is returned. The last index in the returned index path is @c is returned. The last index in the returned index path is
index. <code>anIndex</code>.
@param index @param anIndex
The index with which to replace the last index in the receiving The index with which to replace the last index in the receiving
index path. index path.
@return A new index path with @c index as its last index. @return A new index path with <code>anIndex</code> as its last index.
*/ */
- (NSIndexPath *)indexPathByReplacingLastIndexWithIndex:(NSUInteger)index; - (NSIndexPath *)indexPathByReplacingLastIndexWithIndex:(NSUInteger)anIndex;
/*! /*!
@method indexPathByRemovingFirstIndex @method indexPathByRemovingFirstIndex
@brief Provides an index path with the indexes in the receiving index @abstract Provides an index path with the indexes in the receiving index
path, excluding the first one. path, excluding the first one.
@discussion Returns an empty NSIndexPath instance if the receiving index @discussion Returns an empty NSIndexPath instance if the receiving index
@@ -63,90 +68,90 @@
/*! /*!
@method indexPathByPreceedingIndex: @method indexPathByPreceedingIndex:
@brief Provides an index path with the specified index followed by the @abstract Provides an index path with the specified index followed by the
indexes of the receiver. indexes of the receiver.
@discussion If the receiver does not contain any indexes the specified index @discussion If the receiver does not contain any indexes the specified index
is the only index contained in the returned index path. is the only index contained in the returned index path.
@param index @param anIndex
The index new index preceeding all others The index new index preceeding all others
@return A new index path with all the receiver's indexes preceeded by @c @return A new index path with all the receiver's indexes preceeded by
index. <code>anIndex</code>
*/ */
- (NSIndexPath *)indexPathByPreceedingIndex:(NSUInteger)index; - (NSIndexPath *)indexPathByPreceedingIndex:(NSUInteger)anIndex;
/*! /*!
@method indexPathByIncrementingLastIndex @method indexPathByIncrementingLastIndex
@brief Provides an index path with the indexes in the receiving index @abstract Provides an index path with the indexes in the receiving index
path where the last one is incremented by @c 1. path where the last one is incremented by <code>1</code>.
@discussion If the receiver does not contain any indexes an empty index path @discussion If the receiver does not contain any indexes an empty index path
is returned. is returned.
@return A new index path with all the receiver's indexes and the last one @return A new index path with all the receiver's indexes and the last one
incremented by @c 1. incremented by <code>1</code>.
*/ */
- (NSIndexPath *)indexPathByIncrementingLastIndex; - (NSIndexPath *)indexPathByIncrementingLastIndex;
/*! /*!
@method indexPathByDecrementingLastIndex @method indexPathByDecrementingLastIndex
@brief Provides an index path with the indexes in the receiving index @abstract Provides an index path with the indexes in the receiving index
path where the last one is decremented by @c 1. path where the last one is decremented by <code>1</code>.
@discussion If the receiver does not contain any indexes an empty index path @discussion If the receiver does not contain any indexes an empty index path
is returned. is returned.
@return A new index path with all the receiver's indexes and the last one @return A new index path with all the receiver's indexes and the last one
decremented by @c 1. decremented by <code>1</code>.
*/ */
- (NSIndexPath *)indexPathByDecrementingLastIndex; - (NSIndexPath *)indexPathByDecrementingLastIndex;
/*! /*!
@method indexPathByRemovingIndexesFrom: @method indexPathByRemovingIndexesFrom:
@brief Provides an index path with the indexes in the recieving index @abstract Provides an index path with the indexes in the recieving index
path up to the index at the specified position. path up to the index at the specified position.
@discussion If @c from is greater or equal to the number of indexes in the @discussion If <code>from</code> is greater or equal to the number of indexes
receiving index path only the indexes to the end of the receiver in the receiving index path only the indexes to the end of the
are removed. receiver are removed.
@param from @param from
The position of the first index to be excluded in the returned The position of the first index to be excluded in the returned
index path. index path.
@return An index path with all indexes from the receiver up to position @return An index path with all indexes from the receiver up to position
@c from. <code>from</code>.
*/ */
- (NSIndexPath *)indexPathByRemovingIndexesFrom:(NSUInteger)from; - (NSIndexPath *)indexPathByRemovingIndexesFrom:(NSUInteger)from;
/*! /*!
@method indexPathByRemovingIndexesTo: @method indexPathByRemovingIndexesTo:
@brief Provides an index path with the indexes in the receiving index @abstract Provides an index path with the indexes in the receiving index
path where the first indexes are removed. path where the first indexes are removed.
@discussion @c to specifies the number of indexes to be removed from the @discussion <code>to</code> specifies the number of indexes to be removed
front. Thus the index at position @c to will be included in the from the front. Thus the index at position <code>to</code> will
returned index path. be included in the returned index path.
@param to @param to
The number of indexes to remove from the front. The number of indexes to remove from the front.
@return A new index path with all the receiver's indexes exept the first @return A new index path with all the receiver's indexes exept the first
@c to ones. <code>to</code> ones.
*/ */
- (NSIndexPath *)indexPathByRemovingIndexesTo:(NSUInteger)to; - (NSIndexPath *)indexPathByRemovingIndexesTo:(NSUInteger)to;
/*! /*!
@method commonIndexPathWith: @method commonIndexPathWith:
@brief Provides an index path that contains the first indexes of the @abstract Provides an index path that contains the first indexes of the
receiver that are equal to the specified index path. receiver that are equal to the specified index path.
@discussion If one index path is completely included in the other a new index @discussion If one index path is completely included in the other a new index
@@ -156,7 +161,7 @@
The index path to compare the receiver against. The index path to compare the receiver against.
@return A new index path with the first indexes of the receiver that are @return A new index path with the first indexes of the receiver that are
also present in @c indexPath. also present in <code>indexPath</code>.
*/ */
- (NSIndexPath *)commonIndexPathWith:(NSIndexPath *)indexPath; - (NSIndexPath *)commonIndexPathWith:(NSIndexPath *)indexPath;

View File

@@ -25,9 +25,9 @@
} }
- (NSIndexPath *)indexPathByReplacingLastIndexWithIndex:(NSUInteger)index - (NSIndexPath *)indexPathByReplacingLastIndexWithIndex:(NSUInteger)anIndex
{ {
return [[self indexPathByRemovingLastIndex] indexPathByAddingIndex:index]; return [[self indexPathByRemovingLastIndex] indexPathByAddingIndex:anIndex];
} }
@@ -46,10 +46,10 @@
} }
- (NSIndexPath *)indexPathByPreceedingIndex:(NSUInteger)index - (NSIndexPath *)indexPathByPreceedingIndex:(NSUInteger)anIndex
{ {
NSUInteger newIndexes[self.length+1]; NSUInteger newIndexes[self.length+1];
newIndexes[0] = index; newIndexes[0] = anIndex;
for (NSUInteger i = 0; i < self.length; i++) { for (NSUInteger i = 0; i < self.length; i++) {
newIndexes[i+1] = [self indexAtPosition:i]; newIndexes[i+1] = [self indexAtPosition:i];
} }

View File

@@ -8,16 +8,21 @@
/*!
@category NSRegularExpression (MPParsingAdditions)
@abstract This category adds convenience methods for typical calls to
<code>firstMatchInString:options:range:</code>.
*/
@interface NSRegularExpression (MPParsingAdditions) @interface NSRegularExpression (MPParsingAdditions)
/*! /*!
@method firstMathInString: @method firstMathInString:
@brief Returns the first match of the regular expression within the @abstract Returns the first match of the regular expression within the
specified string. specified string.
@discussion This is a convenience method that calls @c @discussion This is a convenience method that calls
-firstMatchInString:options:range: <code>firstMatchInString:options:range:</code>.
@param string @param string
The string to search. The string to search.
@@ -25,19 +30,19 @@
@return An NSTextCheckingResult object. This result gives the overall @return An NSTextCheckingResult object. This result gives the overall
matched range via its range property, and the range of each matched range via its range property, and the range of each
individual capture group via its rangeAtIndex: method. The range individual capture group via its rangeAtIndex: method. The range
@c {NSNotFound, 0} is returned if one of the capture groups did <code>{NSNotFound, 0}</code> is returned if one of the capture
not participate in this particular match. groups did not participate in this particular match.
*/ */
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string; - (NSTextCheckingResult *)firstMatchInString:(NSString *)string;
/*! /*!
@method firstMathInString:fromIndex @method firstMathInString:fromIndex
@brief Returns the first match of the regular expression from the @abstract Returns the first match of the regular expression from the
specified index in the string. specified index in the string.
@discussion This is a convenience method that calls @c @discussion This is a convenience method that calls
-firstMatchInString:options:range: <code>firstMatchInString:options:range:</code>.
@param string @param string
The string to search. The string to search.
@@ -48,50 +53,50 @@
@return An NSTextCheckingResult object. This result gives the overall @return An NSTextCheckingResult object. This result gives the overall
matched range via its range property, and the range of each matched range via its range property, and the range of each
individual capture group via its rangeAtIndex: method. The range individual capture group via its rangeAtIndex: method. The range
@c {NSNotFound, 0} is returned if one of the capture groups did <code>{NSNotFound,</code> 0} is returned if one of the capture
not participate in this particular match. groups did not participate in this particular match.
*/ */
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string fromIndex:(NSUInteger)start; - (NSTextCheckingResult *)firstMatchInString:(NSString *)string fromIndex:(NSUInteger)start;
/*! /*!
@method firstMathInString:options: @method firstMathInString:options:
@brief Returns the first match of the regular expression within the @abstract Returns the first match of the regular expression within the
specified string. specified string.
@discussion This is a convenience method that calls @c @discussion This is a convenience method that calls
-firstMatchInString:options:range: <code>firstMatchInString:options:range:</code>.
@param string @param string
The string to search. The string to search.
@param options @param options
The matching options to use. See @c NSMatchingOptions for The matching options to use. See <code>NSMatchingOptions</code>
possible values. for possible values.
@return An NSTextCheckingResult object. This result gives the overall @return An NSTextCheckingResult object. This result gives the overall
matched range via its range property, and the range of each matched range via its range property, and the range of each
individual capture group via its rangeAtIndex: method. The range individual capture group via its rangeAtIndex: method. The range
@c {NSNotFound, 0} is returned if one of the capture groups did <code>{NSNotFound,</code> 0} is returned if one of the capture
not participate in this particular match. groups did not participate in this particular match.
*/ */
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options; - (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options;
/*! /*!
@method firstMathInString:fromIndex @method firstMathInString:options:fromIndex
@brief Returns the first match of the regular expression from the @abstract Returns the first match of the regular expression from the
specified index in the string. specified index in the string.
@discussion This is a convenience method that calls @c @discussion This is a convenience method that calls
-firstMatchInString:options:range: <code>firstMatchInString:options:range:</code>.
@param string @param string
The string to search. The string to search.
@param options @param options
The matching options to use. See @c NSMatchingOptions for The matching options to use. See <code>NSMatchingOptions</code>
possible values. for possible values.
@param start @param start
The index from which to start searching. The index from which to start searching.
@@ -99,8 +104,8 @@
@return An NSTextCheckingResult object. This result gives the overall @return An NSTextCheckingResult object. This result gives the overall
matched range via its range property, and the range of each matched range via its range property, and the range of each
individual capture group via its rangeAtIndex: method. The range individual capture group via its rangeAtIndex: method. The range
@c {NSNotFound, 0} is returned if one of the capture groups did <code>{NSNotFound,</code> 0} is returned if one of the capture
not participate in this particular match. groups did not participate in this particular match.
*/ */
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options fromIndex:(NSUInteger)start; - (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options fromIndex:(NSUInteger)start;

View File

@@ -6,14 +6,14 @@
// Copyright (c) 2014 Kim Wittenburg. All rights reserved. // Copyright (c) 2014 Kim Wittenburg. All rights reserved.
// //
#import "MPExpressionElement.h" #import "MPExpression.h"
/*! /*!
@category NSString (MPExpressionElement) @category NSString (MPExpressionElement)
@brief This category adds @c MPExpressionElement protocol conformance to @abstract This category adds <code>@link MPExpressionElement@/link</code>
the @c NSString class. protocol conformance to the <code>NSString</code> class.
*/ */
@interface NSString (MPExpressionElement) <MPExpressionElement> @interface NSString (MPExpressionElement) <MPExpressionElement>

View File

@@ -10,7 +10,6 @@
3B52CEC119BB9FA900CEDCFC /* MathKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B85830D19BB5E5500D76A8D /* MathKit.framework */; }; 3B52CEC119BB9FA900CEDCFC /* MathKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B85830D19BB5E5500D76A8D /* MathKit.framework */; };
3B6338351A3A4B5800698BFB /* MPExpression.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B6338321A3A4B5800698BFB /* MPExpression.h */; }; 3B6338351A3A4B5800698BFB /* MPExpression.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B6338321A3A4B5800698BFB /* MPExpression.h */; };
3B6338361A3A4B5800698BFB /* MPExpression.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B6338331A3A4B5800698BFB /* MPExpression.m */; }; 3B6338361A3A4B5800698BFB /* MPExpression.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B6338331A3A4B5800698BFB /* MPExpression.m */; };
3B6338371A3A4B5800698BFB /* MPExpressionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B6338341A3A4B5800698BFB /* MPExpressionElement.h */; };
3B63383A1A3A4B7600698BFB /* NSString+MPExpressionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B6338381A3A4B7600698BFB /* NSString+MPExpressionElement.h */; }; 3B63383A1A3A4B7600698BFB /* NSString+MPExpressionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B6338381A3A4B7600698BFB /* NSString+MPExpressionElement.h */; };
3B63383B1A3A4B7600698BFB /* NSString+MPExpressionElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B6338391A3A4B7600698BFB /* NSString+MPExpressionElement.m */; }; 3B63383B1A3A4B7600698BFB /* NSString+MPExpressionElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B6338391A3A4B7600698BFB /* NSString+MPExpressionElement.m */; };
3B63383E1A3A4B8500698BFB /* MPToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B63383C1A3A4B8500698BFB /* MPToken.h */; }; 3B63383E1A3A4B8500698BFB /* MPToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B63383C1A3A4B8500698BFB /* MPToken.h */; };
@@ -159,25 +158,24 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
3B0F69AB1902A82C00817707 /* MPExpressionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPExpressionTests.m; path = ../MathPadTests/MPExpressionTests.m; sourceTree = "<group>"; }; 3B0F69AB1902A82C00817707 /* MPExpressionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPExpressionTests.m; path = ../MathPadTests/MPExpressionTests.m; sourceTree = "<group>"; };
3B6338321A3A4B5800698BFB /* MPExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPExpression.h; path = MathKit/MPExpression.h; sourceTree = SOURCE_ROOT; }; 3B6338321A3A4B5800698BFB /* MPExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPExpression.h; path = MathKit/MPExpression.h; sourceTree = SOURCE_ROOT; };
3B6338331A3A4B5800698BFB /* MPExpression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPExpression.m; path = MathKit/MPExpression.m; sourceTree = SOURCE_ROOT; }; 3B6338331A3A4B5800698BFB /* MPExpression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = MPExpression.m; path = MathKit/MPExpression.m; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
3B6338341A3A4B5800698BFB /* MPExpressionElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPExpressionElement.h; path = MathKit/MPExpressionElement.h; sourceTree = SOURCE_ROOT; };
3B6338381A3A4B7600698BFB /* NSString+MPExpressionElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+MPExpressionElement.h"; path = "MathKit/NSString+MPExpressionElement.h"; sourceTree = SOURCE_ROOT; }; 3B6338381A3A4B7600698BFB /* NSString+MPExpressionElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+MPExpressionElement.h"; path = "MathKit/NSString+MPExpressionElement.h"; sourceTree = SOURCE_ROOT; };
3B6338391A3A4B7600698BFB /* NSString+MPExpressionElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+MPExpressionElement.m"; path = "MathKit/NSString+MPExpressionElement.m"; sourceTree = SOURCE_ROOT; }; 3B6338391A3A4B7600698BFB /* NSString+MPExpressionElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+MPExpressionElement.m"; path = "MathKit/NSString+MPExpressionElement.m"; sourceTree = SOURCE_ROOT; };
3B63383C1A3A4B8500698BFB /* MPToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPToken.h; path = MathKit/MPToken.h; sourceTree = SOURCE_ROOT; }; 3B63383C1A3A4B8500698BFB /* MPToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPToken.h; path = MathKit/MPToken.h; sourceTree = SOURCE_ROOT; };
3B63383D1A3A4B8500698BFB /* MPToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPToken.m; path = MathKit/MPToken.m; sourceTree = SOURCE_ROOT; }; 3B63383D1A3A4B8500698BFB /* MPToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPToken.m; path = MathKit/MPToken.m; sourceTree = SOURCE_ROOT; };
3B6338401A3A4B9500698BFB /* MPFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPFunction.h; path = MathKit/MPFunction.h; sourceTree = SOURCE_ROOT; }; 3B6338401A3A4B9500698BFB /* MPFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MPFunction.h; path = MathKit/MPFunction.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3B6338411A3A4B9500698BFB /* MPFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPFunction.m; path = MathKit/MPFunction.m; sourceTree = SOURCE_ROOT; }; 3B6338411A3A4B9500698BFB /* MPFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPFunction.m; path = MathKit/MPFunction.m; sourceTree = SOURCE_ROOT; };
3B6338441A3A4BA500698BFB /* MPExpressionTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPExpressionTokenizer.h; path = MathKit/MPExpressionTokenizer.h; sourceTree = SOURCE_ROOT; }; 3B6338441A3A4BA500698BFB /* MPExpressionTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MPExpressionTokenizer.h; path = MathKit/MPExpressionTokenizer.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3B6338451A3A4BA500698BFB /* MPExpressionTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPExpressionTokenizer.m; path = MathKit/MPExpressionTokenizer.m; sourceTree = SOURCE_ROOT; }; 3B6338451A3A4BA500698BFB /* MPExpressionTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPExpressionTokenizer.m; path = MathKit/MPExpressionTokenizer.m; sourceTree = SOURCE_ROOT; };
3B6338481A3A4BB300698BFB /* MPFunction+MPToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "MPFunction+MPToken.h"; path = "MathKit/MPFunction+MPToken.h"; sourceTree = SOURCE_ROOT; }; 3B6338481A3A4BB300698BFB /* MPFunction+MPToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "MPFunction+MPToken.h"; path = "MathKit/MPFunction+MPToken.h"; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3B6338491A3A4BB300698BFB /* MPFunction+MPToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "MPFunction+MPToken.m"; path = "MathKit/MPFunction+MPToken.m"; sourceTree = SOURCE_ROOT; }; 3B6338491A3A4BB300698BFB /* MPFunction+MPToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "MPFunction+MPToken.m"; path = "MathKit/MPFunction+MPToken.m"; sourceTree = SOURCE_ROOT; };
3B63384C1A3A4BD100698BFB /* MPParenthesisFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPParenthesisFunction.h; path = MathKit/MPParenthesisFunction.h; sourceTree = SOURCE_ROOT; }; 3B63384C1A3A4BD100698BFB /* MPParenthesisFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MPParenthesisFunction.h; path = MathKit/MPParenthesisFunction.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3B63384D1A3A4BD100698BFB /* MPParenthesisFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPParenthesisFunction.m; path = MathKit/MPParenthesisFunction.m; sourceTree = SOURCE_ROOT; }; 3B63384D1A3A4BD100698BFB /* MPParenthesisFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPParenthesisFunction.m; path = MathKit/MPParenthesisFunction.m; sourceTree = SOURCE_ROOT; };
3B63384E1A3A4BD100698BFB /* MPSumFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPSumFunction.h; path = MathKit/MPSumFunction.h; sourceTree = SOURCE_ROOT; }; 3B63384E1A3A4BD100698BFB /* MPSumFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPSumFunction.h; path = MathKit/MPSumFunction.h; sourceTree = SOURCE_ROOT; };
3B63384F1A3A4BD100698BFB /* MPSumFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPSumFunction.m; path = MathKit/MPSumFunction.m; sourceTree = SOURCE_ROOT; }; 3B63384F1A3A4BD100698BFB /* MPSumFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPSumFunction.m; path = MathKit/MPSumFunction.m; sourceTree = SOURCE_ROOT; };
3B6338541A3A4BE800698BFB /* MPFractionFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPFractionFunction.h; path = MathKit/MPFractionFunction.h; sourceTree = SOURCE_ROOT; }; 3B6338541A3A4BE800698BFB /* MPFractionFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MPFractionFunction.h; path = MathKit/MPFractionFunction.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3B6338551A3A4BE800698BFB /* MPFractionFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPFractionFunction.m; path = MathKit/MPFractionFunction.m; sourceTree = SOURCE_ROOT; }; 3B6338551A3A4BE800698BFB /* MPFractionFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPFractionFunction.m; path = MathKit/MPFractionFunction.m; sourceTree = SOURCE_ROOT; };
3B6338561A3A4BE800698BFB /* MPPowerFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPPowerFunction.h; path = MathKit/MPPowerFunction.h; sourceTree = SOURCE_ROOT; }; 3B6338561A3A4BE800698BFB /* MPPowerFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MPPowerFunction.h; path = MathKit/MPPowerFunction.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3B6338571A3A4BE800698BFB /* MPPowerFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPPowerFunction.m; path = MathKit/MPPowerFunction.m; sourceTree = SOURCE_ROOT; }; 3B6338571A3A4BE800698BFB /* MPPowerFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPPowerFunction.m; path = MathKit/MPPowerFunction.m; sourceTree = SOURCE_ROOT; };
3B63385C1A3A4C0700698BFB /* MPExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPExpressionParser.h; path = MathKit/MPExpressionParser.h; sourceTree = SOURCE_ROOT; }; 3B63385C1A3A4C0700698BFB /* MPExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPExpressionParser.h; path = MathKit/MPExpressionParser.h; sourceTree = SOURCE_ROOT; };
3B63385D1A3A4C0700698BFB /* MPExpressionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPExpressionParser.m; path = MathKit/MPExpressionParser.m; sourceTree = SOURCE_ROOT; }; 3B63385D1A3A4C0700698BFB /* MPExpressionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPExpressionParser.m; path = MathKit/MPExpressionParser.m; sourceTree = SOURCE_ROOT; };
@@ -187,7 +185,7 @@
3B6338631A3A4C2B00698BFB /* MPNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPNumber.m; path = MathKit/MPNumber.m; sourceTree = SOURCE_ROOT; }; 3B6338631A3A4C2B00698BFB /* MPNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPNumber.m; path = MathKit/MPNumber.m; sourceTree = SOURCE_ROOT; };
3B6338641A3A4C2B00698BFB /* MPParenthesisTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPParenthesisTerm.h; path = MathKit/MPParenthesisTerm.h; sourceTree = SOURCE_ROOT; }; 3B6338641A3A4C2B00698BFB /* MPParenthesisTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPParenthesisTerm.h; path = MathKit/MPParenthesisTerm.h; sourceTree = SOURCE_ROOT; };
3B6338651A3A4C2B00698BFB /* MPParenthesisTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPParenthesisTerm.m; path = MathKit/MPParenthesisTerm.m; sourceTree = SOURCE_ROOT; }; 3B6338651A3A4C2B00698BFB /* MPParenthesisTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPParenthesisTerm.m; path = MathKit/MPParenthesisTerm.m; sourceTree = SOURCE_ROOT; };
3B6338661A3A4C2B00698BFB /* MPParsedExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPParsedExpression.h; path = MathKit/MPParsedExpression.h; sourceTree = SOURCE_ROOT; }; 3B6338661A3A4C2B00698BFB /* MPParsedExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MPParsedExpression.h; path = MathKit/MPParsedExpression.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3B6338671A3A4C2B00698BFB /* MPParsedExpression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPParsedExpression.m; path = MathKit/MPParsedExpression.m; sourceTree = SOURCE_ROOT; }; 3B6338671A3A4C2B00698BFB /* MPParsedExpression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPParsedExpression.m; path = MathKit/MPParsedExpression.m; sourceTree = SOURCE_ROOT; };
3B6338681A3A4C2B00698BFB /* MPPowerTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPPowerTerm.h; path = MathKit/MPPowerTerm.h; sourceTree = SOURCE_ROOT; }; 3B6338681A3A4C2B00698BFB /* MPPowerTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPPowerTerm.h; path = MathKit/MPPowerTerm.h; sourceTree = SOURCE_ROOT; };
3B6338691A3A4C2B00698BFB /* MPPowerTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPPowerTerm.m; path = MathKit/MPPowerTerm.m; sourceTree = SOURCE_ROOT; }; 3B6338691A3A4C2B00698BFB /* MPPowerTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPPowerTerm.m; path = MathKit/MPPowerTerm.m; sourceTree = SOURCE_ROOT; };
@@ -213,7 +211,7 @@
3B6338991A3A4CE100698BFB /* MPSumFunctionTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPSumFunctionTerm.m; path = MathKit/MPSumFunctionTerm.m; sourceTree = SOURCE_ROOT; }; 3B6338991A3A4CE100698BFB /* MPSumFunctionTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPSumFunctionTerm.m; path = MathKit/MPSumFunctionTerm.m; sourceTree = SOURCE_ROOT; };
3B63389C1A3A4CEF00698BFB /* MPFractionTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPFractionTerm.h; path = MathKit/MPFractionTerm.h; sourceTree = SOURCE_ROOT; }; 3B63389C1A3A4CEF00698BFB /* MPFractionTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPFractionTerm.h; path = MathKit/MPFractionTerm.h; sourceTree = SOURCE_ROOT; };
3B63389D1A3A4CEF00698BFB /* MPFractionTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPFractionTerm.m; path = MathKit/MPFractionTerm.m; sourceTree = SOURCE_ROOT; }; 3B63389D1A3A4CEF00698BFB /* MPFractionTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPFractionTerm.m; path = MathKit/MPFractionTerm.m; sourceTree = SOURCE_ROOT; };
3B6338A01A3A4CFC00698BFB /* MPRangePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPRangePath.h; path = MathKit/MPRangePath.h; sourceTree = SOURCE_ROOT; }; 3B6338A01A3A4CFC00698BFB /* MPRangePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MPRangePath.h; path = MathKit/MPRangePath.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
3B6338A11A3A4CFC00698BFB /* MPRangePath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPRangePath.m; path = MathKit/MPRangePath.m; sourceTree = SOURCE_ROOT; }; 3B6338A11A3A4CFC00698BFB /* MPRangePath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPRangePath.m; path = MathKit/MPRangePath.m; sourceTree = SOURCE_ROOT; };
3B6338A41A3A4D1200698BFB /* Fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Fonts; sourceTree = "<group>"; }; 3B6338A41A3A4D1200698BFB /* Fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Fonts; sourceTree = "<group>"; };
3B6338A61A3A4D2600698BFB /* NSIndexPath+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSIndexPath+MPAdditions.h"; path = "MathKit/NSIndexPath+MPAdditions.h"; sourceTree = SOURCE_ROOT; }; 3B6338A61A3A4D2600698BFB /* NSIndexPath+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSIndexPath+MPAdditions.h"; path = "MathKit/NSIndexPath+MPAdditions.h"; sourceTree = SOURCE_ROOT; };
@@ -319,6 +317,18 @@
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
3B4EC2AC1A3F1400009ADA5E /* MPExpressionView Internal */ = {
isa = PBXGroup;
children = (
3B6338B61A3A4D9400698BFB /* MPFunctionsViewController.h */,
3B6338B71A3A4D9400698BFB /* MPFunctionsViewController.m */,
3B6338B81A3A4D9400698BFB /* MPFunctionsViewController.xib */,
3B6338B91A3A4D9400698BFB /* MPWhiteView.h */,
3B6338BA1A3A4D9400698BFB /* MPWhiteView.m */,
);
name = "MPExpressionView Internal";
sourceTree = "<group>";
};
3B7172E519C7112C00FEAA5B /* Resources */ = { 3B7172E519C7112C00FEAA5B /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -373,11 +383,12 @@
3B85833119BB5EC800D76A8D /* View */ = { 3B85833119BB5EC800D76A8D /* View */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3B6338AE1A3A4D6A00698BFB /* MPExpressionView.h */,
3B6338AF1A3A4D6A00698BFB /* MPExpressionView.m */,
3B6338B21A3A4D7900698BFB /* MPExpressionStorage.h */, 3B6338B21A3A4D7900698BFB /* MPExpressionStorage.h */,
3B6338B31A3A4D7900698BFB /* MPExpressionStorage.m */, 3B6338B31A3A4D7900698BFB /* MPExpressionStorage.m */,
3BB09ED819071C270080A5ED /* Private */, 3B6338AE1A3A4D6A00698BFB /* MPExpressionView.h */,
3B6338AF1A3A4D6A00698BFB /* MPExpressionView.m */,
3B4EC2AC1A3F1400009ADA5E /* MPExpressionView Internal */,
3BB09ED819071C270080A5ED /* Layout System */,
); );
name = View; name = View;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -419,14 +430,9 @@
name = Functions; name = Functions;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
3BB09ED819071C270080A5ED /* Private */ = { 3BB09ED819071C270080A5ED /* Layout System */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3B6338B61A3A4D9400698BFB /* MPFunctionsViewController.h */,
3B6338B71A3A4D9400698BFB /* MPFunctionsViewController.m */,
3B6338B81A3A4D9400698BFB /* MPFunctionsViewController.xib */,
3B6338B91A3A4D9400698BFB /* MPWhiteView.h */,
3B6338BA1A3A4D9400698BFB /* MPWhiteView.m */,
3B6338C01A3A4DA500698BFB /* MPLayout.h */, 3B6338C01A3A4DA500698BFB /* MPLayout.h */,
3B6338C11A3A4DA500698BFB /* MPLayout.m */, 3B6338C11A3A4DA500698BFB /* MPLayout.m */,
3B6338C41A3A4DB600698BFB /* MPExpressionLayout.h */, 3B6338C41A3A4DB600698BFB /* MPExpressionLayout.h */,
@@ -435,7 +441,7 @@
3B6338C91A3A4DC400698BFB /* MPFunctionLayout.m */, 3B6338C91A3A4DC400698BFB /* MPFunctionLayout.m */,
3BB09EE21907361C0080A5ED /* Function Layouts */, 3BB09EE21907361C0080A5ED /* Function Layouts */,
); );
name = Private; name = "Layout System";
path = ../MathPad; path = ../MathPad;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -468,7 +474,6 @@
children = ( children = (
3B6338321A3A4B5800698BFB /* MPExpression.h */, 3B6338321A3A4B5800698BFB /* MPExpression.h */,
3B6338331A3A4B5800698BFB /* MPExpression.m */, 3B6338331A3A4B5800698BFB /* MPExpression.m */,
3B6338341A3A4B5800698BFB /* MPExpressionElement.h */,
3B6338381A3A4B7600698BFB /* NSString+MPExpressionElement.h */, 3B6338381A3A4B7600698BFB /* NSString+MPExpressionElement.h */,
3B6338391A3A4B7600698BFB /* NSString+MPExpressionElement.m */, 3B6338391A3A4B7600698BFB /* NSString+MPExpressionElement.m */,
3B6338401A3A4B9500698BFB /* MPFunction.h */, 3B6338401A3A4B9500698BFB /* MPFunction.h */,
@@ -659,7 +664,6 @@
3B63388E1A3A4CBE00698BFB /* MPFunctionTerm.h in Headers */, 3B63388E1A3A4CBE00698BFB /* MPFunctionTerm.h in Headers */,
3B6338D41A3A4DE100698BFB /* MPFractionFunctionLayout.h in Headers */, 3B6338D41A3A4DE100698BFB /* MPFractionFunctionLayout.h in Headers */,
3B6338741A3A4C2B00698BFB /* MPPowerTerm.h in Headers */, 3B6338741A3A4C2B00698BFB /* MPPowerTerm.h in Headers */,
3B6338371A3A4B5800698BFB /* MPExpressionElement.h in Headers */,
3B6338BE1A3A4D9400698BFB /* MPWhiteView.h in Headers */, 3B6338BE1A3A4D9400698BFB /* MPWhiteView.h in Headers */,
3B6338A21A3A4CFC00698BFB /* MPRangePath.h in Headers */, 3B6338A21A3A4CFC00698BFB /* MPRangePath.h in Headers */,
3B63386E1A3A4C2B00698BFB /* MPNumber.h in Headers */, 3B63386E1A3A4C2B00698BFB /* MPNumber.h in Headers */,

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6250"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
</dependencies> </dependencies>
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/> <customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
@@ -338,6 +338,25 @@
</items> </items>
</menu> </menu>
</menuItem> </menuItem>
<menuItem title="Format" id="Pa3-yC-zjM">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="bKH-52-Ncj">
<items>
<menuItem title="Degrees" state="on" id="X07-F1-kEf">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="switchToDegrees:" target="-1" id="ef4-YF-Iph"/>
</connections>
</menuItem>
<menuItem title="Radians" id="Xhr-et-7Xe">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="switchToRadians:" target="-1" id="hD5-IC-vb5"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR"> <menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo"> <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">