//
// MPExpressionParser.h
// MathPad
//
// Created by Kim Wittenburg on 16.11.14.
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
/*!
@header
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