Welcome to
aleprojects.com

Using parser - variables, properties, arrays and collections

Name of variable or property in expression must start with letter or '_' character and may have any Unicode alphanumeric character (including surrogates) optionally modified by diacritical marks or '_' character. Elements of arrays or collections are accessed by indexes or keys written in square brackets. Example of expression: "MyVar + myClass.SomeProperty + MyArray[0,1]". Here MyVar, myClass, MyArray are variables, SomeProperty is a property, MyArray[0,1] is an array element.

There are two actions with variables, properties and array/collection elements that may occur during evaluation: retrieving value and assigning value. These actions take place in delegates passed to the AleTerm.Evaluate method. Full syntax of AleTerm.Evaluate method is:

public bool Evaluate(out AleTermResult result, TermEvaluate userEvaluate = null, TermAssign userAssign = null)

Retrieving value takes place in userEvaluate delegate. Syntax of this delegate is:

public delegate void TermEvaluate(AleTerm term, AleTermEvaluateArgs e);

where term is AleTerm instance which has executed delegate. e parameter contains information about the object whose value is retrieved.

using AleProjects.AleLexer.AleParser;
using AleProjects.AleLexer;

...

string myVar = "some value";
int[,] matrix = new int[,] { { 10, 11, 12, 13 }, { 14, 15, 16, 20 }, { 27, 28, 29, 40 } }; 

private class MyClass 
{
	public string SomeProperty { get; set; }
}

MyClass myClass = new MyClass() { SomeProperty = "property value"; };

private void OnEvaluate(AleTerm term, AleTermEvaluateArgs e)
{
	/* VARIABLES
	* e.Instance is null
	* e.Name - name of variable (in uppercase when we ignore case)
	* e.NameHash - hash of e.Name (obtained by GetHashCode())
	* e.Indexes is null when we evaluate variable
	* e.Result - stores value of variable on exit
	*/
	if (e.Instance == null)
	{
		if (e.NameHash == -1770187129 && e.Name == "MYVAR") e.Result = myVar;
		else if (e.NameHash == -413117458 && e.Name == "MYCLASS") e.Result = myClass;
		else if (e.NameHash == 614904363 && e.Name == "MYARRAY")) e.Result = matrix;
		else
		{
			// error - no variable with such name
			e.SetError(AleTermResult.ERROR_UNKNOWNVARIABLE, term.Token.StartInOrigin);
		}

		return;
	}

	/* MEMBERS OF CLASSES (class operator '.')
	* e.Instance - instance of class.
	* e.Name - name of class property (in uppercase when we ignore case)
	* e.NameHash - hash of e.Name (obtained by GetHashCode())
	* e.Indexes is null when we evaluate class property
	* e.Result - stores value of property or result of method
	*/
	if (!String.IsNullOrEmpty(e.Name))
	{
		if (e.Instance is MyClass) 
		{
			MyClass _myClass = e.Instance as MyClass;
			if (e.NameHash = 1760601946 && e.Name == "SOMEPROPERTY") e.Result = _myClass.SomeProperty;
			else e.SetError(AleTermResult.ERROR_UNKNOWNPROPERTY, term.Token.StartInOrigin);
		}
		else e.SetError(AleTermResult.ERROR_UNKNOWNVARIABLE, term.Token.StartInOrigin);
		
		return;
	}

	/* ELEMENTS OF ARRAYS AND COLLECTIONS (index operator)
	* e.Instance - instance of array or collection.
	* e.Name == ""
	* e.NameHash == 0
	* e.Indexes is List<object> with indexes of array or keys of collection
	* e.Result - stores value of member
	*/
	Type typ = e.Instance.GetType();
	
	if (typ.IsArray && typ.FullName == "System.Int32[,]")
	{
		if (e.Indexes.Count != 2 && e.SetError(AleTermResult.ERROR_INVALIDINDEXES, term.Token.StartInOrigin)) return;
	
		int[,] _matrix = e.Instance as int[,];
		try
		{
			e.Result = _matrix[Convert.ToInt32(e.Indexes[0]), Convert.ToInt32(e.Indexes[1])];
		}
		catch
		{
			e.SetError(AleTermResult.ERROR_INVALIDINDEXES, term.Token.StartInOrigin);
		}
	}
	else e.SetError(AleTermResult.ERROR_UNKNOWNVARIABLE, term.Token.StartInOrigin);
}

...

AleExpressionParser AP = new AleExpressionParser();
AP.Options = AleExpressionParser.OPTION_IGNORECASE;
AP.InitOperations(AleExpressionParser.OPERATIONS_STANDARDSET);
AP.Text = "MyVar + myClass.SomeProperty + MyArray[0,1]";

AleTerm term = AP.Parse();
AleTermResult result;

if (term.Evaluate(out result, OnEvaluate)) .....
...

Assigning is initiated by assignment operators (=, +=, -=, ++, etc) and takes place in userAssign delegate. Syntax of this delegate is:

public delegate void TermAssign(AleTerm term, AleTermAssignArgs e);

where term is AleTerm instance which has executed delegate. e parameter contains information about the object the value is assigned to.

using AleProjects.AleLexer.AleParser;
using AleProjects.AleLexer;

...

string myVar = "some value";
int[,] matrix = new int[,] { { 10, 11, 12, 13 }, { 14, 15, 16, 20 }, { 27, 28, 29, 40 } }; 

private class MyClass 
{
	public string SomeProperty { get; set; }
}

MyClass myClass = new MyClass() { SomeProperty = "property value"; };

private void OnEvaluate(AleTerm term, AleTermEvaluateArgs e)
{
	// the same code as in example above
}

private void OnAssign(AleTerm term, AleTermAssignArgs e)
{
	/* VARIABLES
	* e.Instance is null.
	* e.Name - name of variable (in uppercase when we ignore case)
	* e.NameHash - hash of e.Name (obtained by GetHashCode())
	* e.Indexes is null
	* e.Value - value that we assign
	*/
	if (e.Instance == null)
	{
		if (e.NameHash == -1770187129 && e.Name == "MYVAR") myVar = e.Value.ToString();
		else if (e.NameHash == -413117458 && e.Name == "MYCLASS") myClass = e.Value as MyClass;
		else if (e.NameHash == 614904363 && e.Name == "MYARRAY")) matrix = e.Value as int[,];
		else
		{
			// error - no variable with such name
			e.SetError(AleTermResult.ERROR_UNKNOWNVARIABLE, term.Token.StartInOrigin);
		}

		return;
	}
	
	/* MEMBERS OF CLASSES (class operator '.')
	* e.Instance - instance of class.
	* e.Name - name of class property (in uppercase when we ignore case)
	* e.NameHash - hash of e.Name (obtained by GetHashCode())
	* e.Indexes is null
	* e.Value - value that we assign
	*/
	if (!String.IsNullOrEmpty(e.Name))
	{
		if (e.Instance is MyClass) 
		{
			MyClass _myClass = e.Instance as MyClass;
			if (e.NameHash = 1760601946 && e.Name == "SOMEPROPERTY") _myClass.SomeProperty = e.Value.ToString();
			else e.SetError(AleTermResult.ERROR_UNKNOWNPROPERTY, term.Token.StartInOrigin);
		}
		else e.SetError(AleTermResult.ERROR_UNKNOWNELEMENT, term.Token.StartInOrigin);

		return;
	}
	
	/* ELEMENTS OF ARRAYS AND COLLECTIONS (index operator)
	* e.Instance - instance of array or collection.
	* e.Name == ""
	* e.NameHash == 0
	* e.Indexes - list<object> with indexes or keys
	* e.Value - value that we assign
	*/

	Type typ = e.Instance.GetType();
	
	if (typ.IsArray && typ.FullName == "System.Int32[,]")
	{
		if (e.Indexes.Count != 2 && e.SetError(AleTermResult.ERROR_INVALIDINDEXES, term.Token.StartInOrigin)) return;
	
		int[,] _matrix = e.Instance as int[,];
		try
		{
			_matrix[Convert.ToInt32(e.Indexes[0]), Convert.ToInt32(e.Indexes[1])] = Convert.ToInt32(e.Value);
		}
		catch
		{
			e.SetError(AleTermResult.ERROR_INVALIDINDEXES, term.Token.StartInOrigin);
		}
	}
	else e.SetError(AleTermResult.ERROR_UNKNOWNELEMENT, term.Token.StartInOrigin);
}

...

AleExpressionParser AP = new AleExpressionParser();
AP.Options = AleExpressionParser.OPTION_IGNORECASE;
AP.InitOperations(AleExpressionParser.OPERATIONS_STANDARDSET);
AP.Text = "myClass.SomeProperty = \"text \" + (MyVar = \"value=\" + (MyArray[0,1] = 2))";

AleTerm term = AP.Parse();
AleTermResult result;

if (term.Evaluate(out result, OnEvaluate, OnAssign)) .....
...

Associative arrays and object constants

The syntax of associative array constant is: {key1=>value1, key2=>value2, ... }. Internally associative array is stored in the instance of Dictionary<object, object> type.

The syntax of object constant is: {"propertyName1": value1, "propertyName2": value2, ... }. Internally object is stored in the instance of Dictionary<string, object> type.

To disable associative array constants and object constants, set property InitListBrackets of the parser to empty string "" or null. Setting this property to '{}' enables constants. The first character is an opening bracket, the second is a closing one. Combining diacritical marks or surrogate pairs are not allowed.

using AleProjects.AleLexer.AleParser;
using AleProjects.AleLexer;

...

AleExpressionParser AP = new AleExpressionParser();
AP.InitListBrackets = ""; // disable 
..
AP.InitListBrackets = "{}"; // enable 

How to disable elements access

To disable elements access, set property ArrayBrackets of the parser to empty string "" or null. Setting this property to '[]' enables constants. The first character is an opening bracket, the second is a closing one. Combining diacritical marks or surrogate pairs are not allowed.

using AleProjects.AleLexer.AleParser;
using AleProjects.AleLexer;

...

AleExpressionParser AP = new AleExpressionParser();
AP.ArrayBrackets = ""; // disable 
..
AP.ArrayBrackets = "[]"; // enable