Advertisement

muparser - Fast Math Parser Library

Version 2.2.5


Defining parser constants

Parser constants can either be values of type double or string. Constness refers to the bytecode. Constants will be stored by their value in the bytecode, not by a reference to their address. Thus accessing them is faster. They may be optimized away if this is possible. Defining new constants or changing old ones will reset the parser to string parsing mode thus resetting the bytecode.
The Names of user defined constants may contain only the following characters: 0-9, a-z, A-Z, _, and they may not start with a number. Violating this rule will raise a parser error.

[DLL interface]

// Define value constants _pi
mupDefineConst(hParser, "_pi", (double)PARSER_CONST_PI);  

// Define a string constant named strBuf
mupDefineStrConst("strBuf", "hello world");
See also: example2/example2.c.

[Parser class interface]

// Define value constant _pi
parser.DefineConst("_pi", (double)PARSER_CONST_PI);

// Define a string constant named strBuf
parser.DefineStrConst("strBuf", "hello world");
See also: example1/example1.cpp; src/muParserTest.cpp.

Querying parser constants

Querying parser constants is similar to querying variables and expression variables.

[DLL interface]

Due to the use of an temporary internal static buffer for storing the variable name in the DLL version this DLL-function is not thread safe.
int iNumVar = mupGetConstNum(a_hParser);

for (int i=0; i < iNumVar; ++i)
{
  const char_type *szName = 0;
  double fVal = 0;
  mupGetConst(a_hParser, i, &szName, fVal);
  std::cout << "  " << szName << " = " << fVal << "\n";
}
See also: example2/example2.c.

[Parser class interface]

The parser class provides you with the GetConst() member function that returns a map structure with all defined constants. The following code snippet shows how to use it:
mu::Parser::valmap_type cmap = parser.GetConst();
if (cmap.size())
{
  mu::Parser::valmap_type::const_iterator item = cmap.begin();
  for (; item!=cmap.end(); ++item)
    cout << "  " << item->first << " =  " << item->second << "\n";
}
See also: example1/example1.cpp.

Setting custom value recognition callbacks

The parser default implementation (muParser.cpp) scans expressions only for floating point values. Custom value recognition callbacks can be used in order to implement support for binary, hexadecimal or octal numbers. These functions are called during the string parsing step and allow client code to scan portions of the original expressions for special values. Their callback functions must be of the following type:
bool (*identfun_type)(const char_type*, int*, value_type*);

If the parser reaches an a position during string parsing that could represent a value token it tries to interpret it as such. If that fails the parser sucessively calls each of the external value recognition callbacks in order to give them a chance to make sense out of what has been found. If all of them fail the parser continues to check if it is a variable or another kind of token.

In order to perform the task of value recognition the callback functions take a const char pointer, a pointer to int and a pointer to double as their arguments. The const char pointer points to the current position in the expression string. The second argument is a pointer to an integer value representing the index of that position relative to the start of the expression string. This value must be increased by the length of the value entry if one has been found. In that case the value must be written to address pointed to by the third argument which is of type double. The return value is of type bool and indicates whether a value was found or not.

The following code snippet shows a sample implementation of a function that reads and interprets binary values from the expression string. For this sample to work binary numbers must be preceded with a # (i.e. #1000101).

bool ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)
{
  if (a_szExpr[0]!='#') 
    return false;

  unsigned iVal = 0, iBits = sizeof(iVal)*8;
  for (unsigned i=0; (a_szExpr[i+1]=='0'||a_szExpr[i+1]=='1')&& i<iBits; ++i)
  {
    iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);
  }

  if (i==0) 
    return false;

  if (i==iBits)
    throw mu::ParserError("Binary to integer conversion error (overflow).");

  *a_fVal = (unsigned)(iVal >> (iBits-i) );
  *a_iPos += i+1;

  return true;
}
Once you have the callback you must add it to the parser. This can be done with:

[DLL interface]

mupAddValIdent(hParser, IsBinVal);
See also: example2/example2.c.

[Parser class interface]

parser.AddValIdent(IsBinVal);
See also: ParserLib/muParserInt.cpp.

Removing variables or constants

Removing variables and constants can be done all at once using ClearVar and ClearConst. Additionally variables can be removed by name using RemoveVar. Since the parser never owns the variables you must take care of their release yourself (if they were dynamically allocated). If you need to browse all the variables have a look at the chapter explaining how to query parser variables.

[DLL interface]

// Remove all constants
mupClearConst(hParser);

// remove all variables
mupClearVar(hParser);

// remove a single variable by name
mupRemoveVar(hParser, "a"); 
See also: example2/example2.c

[Parser class interface]

// Remove all constants
parser.ClearConst();

// remove all variables
parser.ClearVar();

// remove a single variable by name
parser.RemoveVar("a");
See also: example1/example1.cpp
back      next

You might also like: