Skip to content

Defining parser variables

amomra edited this page Apr 28, 2015 · 5 revisions

Defining parser variables

Custom variables can be defined either explicit in the code by using the DefineVar function or implicit by the parser. Implicit declaration will call a variable factory function provided by the user. Unlike the muParser, the muParserNET is the owner of its variable. The reason behind this change is to provide a safer operation of the library since the .NET memory is managed by its garbage collector. The garbage collector may move one object from its memory position to another, causing the muParser variables to reference invalid memory addresses. To solve this, was created the class ParserVariable where the value have its memory 'pinned', which block the GC from moving the object. Only variables of type double are supported.

Explicitely defining variables

Explicitely in this context means you have to do add the variables manually it in your application code. So you must know in advance which variables you intend to use.

⚠️ Defining new Variables will reset the parser bytecode. Do not use this function just for changing the values of variables! It would dramatically reduce the parser performance! Once the variable is defined use the returned ParserVariable for changing the value.

parser.DefineVar("a", 0);
parser.DefineVar("b", new double[]{ 6, 7, 8, 9, 10});

Implicit creation of new variables

Implicit declaration of new variables is only possible by setting a factory function. Implicit creation means that everytime the parser finds an unknown token at a position where a variable could be located it creates a new variable with that name automatically. The necessary factory function must be of type:

ParserVariable FactoryFunction(string name, object userData)

The first argument to a factory function is the name of the variable found by the parser. The second is an object with user defined data. This object can be used to provide an object that implements the actual factory. By doing this it is possible to use custom factory classes depending on the variable name.

⚠️ Be aware of name conflicts! Please notice that recognizing the name of an undefined variable is the last step during parser token detection. If the potential variable name starts with identifiers that could be interpreted as a function or operator it will be detected as such most likely resulting in an syntax error.

The following code is an example of a factory function. The example does not use dynamic allocation for the new variables although this would be possible too. But when using dynamic allocation you must keep track of the variables allocated implicitely in order to free them later on.

ParserVariable AddVariable(string name, object userdata)
{
    // You can also use custom factory classes like for instance:
    // MyFactory factory = (MyFactory)userdata;
    // factory.CreateNewVariable(name);

    // the second parameter can be an array. If using bulk mode, the
    // variable must be created with an array with nBulk elements
    return new ParserVariable(name, 10.0);
}

In order to add a variable factory use the SetVarFactory functions. The first parameter is a factory function, the second parameter is optional and represents an object with user defined data. Without a variable factory each undefined variable will cause an undefined token error. Factory functions can be used to query the values of newly created variables directly from a database. If you emit errors from a factory function be sure to throw an exception of type ParserError all other exceptions will be caught internally and result in an internal error.

parser.SetVarFactory(AddVariable, userdata);

Querying parser variables

Keeping track of all variables can be a difficult task. For simplification the parser allows the user to query the variables defined in the parser.

// Get the map with the variables
var variables = p.Vars;
// Get the number of variables
Console.WriteLine(variables.Count);

// Query one variable
ParserVariable v = variables["varName"];

// Query the variables
foreach(var variable in variables)
    Console.WriteLine("Name: {0} | Value: {1}", variable.Key, variable.Value.Value);

Removing variables

Removing the variables can be done using the ClearVar and RemoveVar functions.

// remove all variables
parser.ClearVar();

// remove a single variable by name
parser.RemoveVar("a");
Clone this wiki locally