//
//  MPToken.h
//  MathKit
//
//  Created by Kim Wittenburg on 19.09.14.
//  Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//


/*!
 @header
 This file contains the <code>MPToken</code> class and protocol.
 
 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>
 */


/*!
    @typedef    MPTokenType
    @abstract   The type of a token identifies its behaviour in a mathematical
                context.
 
    @constant   MPEOFToken
                A token that represents the end of the input. This token should
                not be used to create an instance of the <code>@link
                //apple_ref/occ/cl/MPToken@/link</code> class. A token with this
                token type should be interpreted as <i>no token</i>.
 
    @constant   MPMultiplicationSymbolToken
                A multiplication symbol.
 
    @constant   MPOperatorListToken
                A list of operators (+ and - symbols). The token may be longer
                than the number of operators if there are spaces between them.

    @constant   MPElementaryFunctionToken
                <i>Most</i> elementary functions are represented by this token
                type. Elementary functions not categorized as such are those that
                can not be represented as text (e.g. roots and powers).
 
    @constant   MPNumberToken
                A number. This may be an integer or a floating point number.
                Floating point numbers contain a
                <code>NSLocaleDecimalSeparator</code>.
 
    @constant   MPVariableToken
                A variable. A variable is exactly one character long.
 
    @constant   MPFactorialToken
                The factorial symbol (an exclamation mark).
 
    @constant   MPEqualsToken
                The equals sign.
 
    @constant   MPGenericFunctionToken
                A function represented by the <code>@link MPFunction@/link</code>
                class. A token with this token type is guaranteed to be an
                instance of the <code>@link MPFunction@/link</code> class.
 
    @constant   MPWhitespaceToken
                A whitespace. This token can typically be ignored.

    @constant   MPUnidentifiedToken
                Any symbol that does not match any other token. If this token is
                found inside an expression the expression should be considered
                invalid.
 */
typedef enum {
    MPEOFToken = 0,
    MPMultiplicationSymbolToken,
    MPOperatorListToken,
    MPElementaryFunctionToken,
    MPNumberToken,
    MPDeformedNumberToken,
    MPVariableToken,
    MPEqualsToken,
    MPFactorialToken,
    MPPowerToken,
    MPGenericFunctionToken,
    
    MPWhitespaceToken,
    MPUnidentifiedToken,
} MPTokenType;



@class MPToken;
@protocol MPToken;


/*!
    @protocol   MPToken
    @abstract   Tokens represent logical units in an expresion.
 */
@protocol MPToken <NSObject>

/*!
    @method     tokenType
    @abstract   Returns the receiver's token type.
 
    @discussion The token type identifies what kind of token the receiver is.
                Possible values are described in the <code>@link
                MPTokenType@/link</code> enumeration.
 
    @return     The receiver's token type.
 */
- (MPTokenType)tokenType;


/*!
    @method     range
    @abstract   Returns the receiver's range.
 
    @discussion The range identifies where the token is in the expression. It is
                specified in the symbol reference frame.
 
    @return     The range the token occupies in the expression it was parsed
                from specified in the symbol reference frame.
 */
- (NSRange)range;


/*!
    @method     stringValue
    @abstract   The string that caused the token to be parsed.
 
    @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
                a length of <code>1</code> whereas a number or whitespace token
                can be much longer.
 
    @return     The receiver's string value.
 */
- (NSString *)stringValue;

@end



/*!
    @class      MPToken
    @abstract   The <code>MPToken</code> class implements the functionality of
                the <code>@link //apple_ref/occ/intf/MPToken@/link</code>
                protocol. Most tokens are instances of the <code>MPToken</code>
                class.
 */
@interface MPToken : NSObject <MPToken>

/*!
    @method     initWithTokenType:range:stringValue:
    @abstract   Creates a new <code>MPToken</code> instance.
 
    @param      tokenType
                The type of the token.
 
    @param      range
                The range of the token in the expression. Specified in the symbol
                reference frame.
 
    @param      input
                The string value of the token.
 
    @return     A newly initialized token.
 */
- (instancetype)initWithTokenType:(MPTokenType)tokenType
                            range:(NSRange)range
                      stringValue:(NSString *)input; /* designated initializer */

@end
