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


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

/*!
    @property   expression
    @abstract   The receiver's expression.
 */
@property (readonly, nonatomic, strong) 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;


/*!
    @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
                                                  errors:(NSArray *__autoreleasing *)errors;

@end
