muparser - Fast Math Parser Library

Version 2.2.5

Defining parser operators

The parser is extensible with different kinds of operators: prefix operators, infix operators and binary operators. Operators can be applied to numerical values only (not to string constants).

Unary operators

Both postfix and infix operators take callback functions of type fun_type1 like the following:
value_type MyCallback(value_type fVal) 
  return fVal/1000.0;

For defining postfix operators and infix operators you need a valid parser instance, an identifier string, and an optional third parameter marking the operator as volatile (non optimizable). In the dll Interface the last parameter is not optional and represented by an integer (0 means do not optimize). The last parameter is merely a hint for the parser. It is not guaranteed that optimization will take place. If a function is marked as being optimizable function calls may be replaced with a precomputed result if the parser detects that the argument is a constant. This is safe for functions as long as they always return the same result when fed with the same input parameter. (An example where optimization is not desired is a function returning random numbers.)

[DLL interface]

// Define an infix operator
mupDefineInfixOprt(hParser, "!", MyCallback, 0);

// Define a postfix operators
mupDefinePostfixOprt(hParser, "M", MyCallback, 0);
See also:example2/example2.c.

[Parser class interface]

// Define an infix operator
parser.DefineInfixOprt("!", MyCallback, 0);

// Define a postfix operators
parser.DefinePostfixOprt("m", MyCallback, 0);
See also:example1/example1.cpp; src/muParserTest.cpp.

Binary operators

muParser has 15 Built in binary operators but sometimes it might be necessary to add additional custom binary operators. Examples are shl or shr, the "shift left" and "shift right" operators for integer numbers. You can bind any callback of type fun_type2 as a binary operator to muParser. The operator can then be defined by using the functions mupDefineOprt respectively DefineOprt:

[DLL interface]

mupDefineOprt(muParserHandle_t handle,
              const muChar_t ident,
              muFun2_t function, 
              muInt_t precedence,
              muInt_t associativity,
	      muBool_t optimizeable);
See also:example2/example2.c.

[Parser class interface]

ParserBase::DefineOprt(const string_type ident,
                       fun_type2 function,              
                       unsigned precedence,
                       EOprtAssociativity associativity,
	               bool optimizeable);
See also:example1/example1.cpp; src/muParserTest.cpp.

For the definition of binary operators the following Parameters are required:

This parameter exists only in the dll interface and must be a valid parser handle.
A string representing the operator identifier. By default muParser restricts the set of characters useable in operator identifiers. You can modify this set by using the function DefineOprtChars.
The second parameter is a function pointer to a static callback function of type fun_type2. This is the place were you have to implement your operator logic.
An integer value determining the operator precedence. When dealing with multiple operations involving binary operators without using brackets this value determines which operator is excuted first. The binary operator with the higher precedence values is executed first. For instance: In the expression 2 + 3 * 4 the result is 14 since the multiplication has a higher precedence value than the addition. For convenience muParser defines the enumeration EOprtPrecedence. This enumeration lists the precedence values used by muParsers internally defined operators. You can use the values listed there as reference when implementing custom operators but in order to not restrict the possible precedence values the function parameter itself is an integer value rather than an enumerator of type EOprtPrecedence
enum EOprtPrecedence
  // binary operators
  prLOR     = 1,
  prLAND    = 2,
  prLOGIC   = 3,  // logic operators
  prCMP     = 4,  // comparsion operators
  prADD_SUB = 5,  // addition
  prMUL_DIV = 6,  // multiplication/division
  prPOW     = 7,  // power operator priority (highest)
  // infix operators
  prINFIX   = 6,  // Signs have a higher priority than ADD_SUB, but lower than power operator
  prPOSTFIX = 6   // Postfix operator priority (currently unused)
The operator associativity determines how operators of the same precedence are grouped in the absence of parentheses. Operators can either be left or right associative. For instance consider the expression 5^4^3^2. Depending on the operator associativity this expression could either be interpreted as 5^(4^(3^2)) which correctly implements the power operator as a right associative operator or alternatively one could also evaluate: ((5^4)^3)^2 The parser defines the following enumeration to represent associativity values:
enum EOprtAssociativity
  oaLEFT  = 0,  // left associative operator
  oaRIGHT = 1   // right associative operator
(When using the dll interface you have to use the integer values instead of the enumerator)
This parameter determines whether the operator always returns the same result when fed with the same input. Normally this is the case so it should be true. There are very few scenarios where an operator does not always return the same values when fed with the same input (i.e. when random number generation is involved)

Finally i'd like to point out that if you encounter confilcts with built in operators or simply dont need the built in operators at all they can easily be deactivated using the EnableBuiltInOprt(bool) function. If you call this function you must add binary operators manually. After all without any operators you won't be able to parse anything useful. User defined operators come with approximately 10% decrease in parsing speed compared to built in operators. There is no way to avoid that. They cause an overhead when calling theeir callback functions. (This is the reason why there are built in operators)

// disable all built in operators

You might also like: