// // MPExpressionParser.h // MathKit // // Created by Kim Wittenburg on 16.11.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // /*! @header This file contains the MPExpressionParser class. The MPExpressionParser converts a @link MPExpression@/link instance into a @link //apple_ref/occ/cl/MPParsedExpression@/link 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 directly 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 2³! is valid and equal to (2³)!. 3. Elementary functions like sin, cos or ln can be chained. sincos(2) is equal to sin(cos(2)). 4. Subsequent elementary functions with values are implicitly multiplied. sin3cos2 is equal to sin(3)⋅cos(2). 5. The value of an elementary function is either exactly one generic function (instances of a @link MPFunction@/link subclass) or a group of numbers and variables that does not contain a multiplication, plus or minus sign. sin2a⋅3 is equal to (sin(2a))⋅3. Besides the rules above the parser accepts inputs containing the following constructs: 1. Chained plus and minus signs (e.g. ++-+--3 is equal to -3). 2. Implicit multiplication. 2a3 is equal to 2⋅a⋅3. */ @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 @link //apple_ref/occ/cl/MPParsedExpression@/link 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 MPExpressionParser. @discussion After this method returns the parser is ready to parse the given expression. 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 MPExpressionParser 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 errors parameter. In that case nil is returned. If no errors occur it is not modified. This is a convenience method that calls @link parseExpectingVariableDefinition:errors:@/link with NO 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 NSError instance. This parameter is never set to an empty array. If you are not interested in errors, pass NULL. @return The parsed expression or nil 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 errors parameter. In that case nil is returned. If no errors occur it is not modified. @param flag If set to YES 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 NO 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 NSError instance. This parameter is never set to an empty array. If you are not interested in errors, pass NULL. @return The parsed expression or nil if the parsed expression contains syntax errors. */ - (MPParsedExpression *)parseExpectingVariableDefinition:(BOOL)flag errors:(NSArray *__autoreleasing *)errors; @end