示例#1
0
        private static void EmitChild(ExpressionElement child, Type resultType, FleeILGenerator ilg, IServiceProvider services)
        {
            child.Emit(ilg, services);
            bool converted = ImplicitConverter.EmitImplicitConvert(child.ResultType, resultType, ilg);

            Debug.Assert(converted, "convert failed");
        }
示例#2
0
        /// <summary>
        /// Emit a short-circuited logical operation sequence
        /// The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom.
        /// For each operand, emit it and try to find an end point for when it short-circuits.  This means we go up through
        /// the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand)
        /// or we reach the root (emit a branch to a true/false).
        /// Repeat the process for all operands and then emit the true/false/last operand end cases.
        /// </summary>
        /// <param name="ilg"></param>
        /// <param name="info"></param>
        /// <param name="services"></param>
        private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services)
        {
            // We always have an end label
            info.Branches.GetLabel(OurEndLabelKey, ilg);

            // Populate our data structures
            this.PopulateData(info);

            // Emit the sequence
            EmitLogicalShortCircuit(ilg, info, services);

            // Get the last operand
            ExpressionElement terminalOperand = (ExpressionElement)info.Operands.Pop();

            // Emit it
            EmitOperand(terminalOperand, info, ilg, services);
            // And jump to the end
            Label endLabel = info.Branches.FindLabel(OurEndLabelKey);

            ilg.Emit(OpCodes.Br_S, endLabel);

            // Emit our true/false terminals
            EmitTerminals(info, ilg, endLabel);

            // Mark the end
            ilg.MarkLabel(endLabel);
        }
示例#3
0
        /// <summary>
        /// Emit elements into an array
        /// </summary>
        /// <param name="elements"></param>
        /// <param name="arrayElementType"></param>
        /// <param name="ilg"></param>
        /// <param name="services"></param>
        private static void EmitElementArrayLoad(ExpressionElement[] elements, Type arrayElementType, FleeILGenerator ilg, IServiceProvider services)
        {
            // Load the array length
            LiteralElement.EmitLoad(elements.Length, ilg);

            // Create the array
            ilg.Emit(OpCodes.Newarr, arrayElementType);

            // Store the new array in a unique local and remember the index
            LocalBuilder local           = ilg.DeclareLocal(arrayElementType.MakeArrayType());
            int          arrayLocalIndex = local.LocalIndex;

            Utility.EmitStoreLocal(ilg, arrayLocalIndex);

            for (int i = 0; i <= elements.Length - 1; i++)
            {
                // Load the array
                Utility.EmitLoadLocal(ilg, arrayLocalIndex);
                // Load the index
                LiteralElement.EmitLoad(i, ilg);
                // Emit the element (with any required conversions)
                ExpressionElement element = elements[i];
                element.Emit(ilg, services);
                ImplicitConverter.EmitImplicitConvert(element.ResultType, arrayElementType, ilg);
                // Store it into the array
                Utility.EmitArrayStore(ilg, arrayElementType);
            }

            // Load the array
            Utility.EmitLoadLocal(ilg, arrayLocalIndex);
        }
示例#4
0
        /// <summary>
        /// Emit a short-circuited logical operation sequence
        /// The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom.
        /// For each operand, emit it and try to find an end point for when it short-circuits.  This means we go up through
        /// the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand)
        /// or we reach the root (emit a branch to a true/false).
        /// Repeat the process for all operands and then emit the true/false/last operand end cases.
        /// </summary>
        /// <param name="ilg"></param>
        /// <param name="info"></param>
        /// <param name="services"></param>
        private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services)
        {
            // We always have an end label
            Label endLabel = ilg.DefineLabel();

            // Populate our data structures
            this.PopulateData(info);

            // Emit the sequence
            EmitLogicalShortCircuit(ilg, info, services);

            // Get the last operand
            ExpressionElement terminalOperand = (ExpressionElement)info.Operands.Pop();

            // Emit it
            EmitOperand(terminalOperand, info, ilg, services);

            // only 1-3 opcodes, always a short branch
            ilg.EmitBranch(endLabel);

            // Emit our true/false terminals
            EmitTerminals(info, ilg, endLabel);

            // Mark the end
            ilg.MarkLabel(endLabel);
        }
示例#5
0
        public override Node ExitInExpression(Production node)
        {
            IList childValues = this.GetChildValues(node);

            if (childValues.Count == 1)
            {
                this.AddFirstChildValue(node);
                return(node);
            }

            ExpressionElement operand = (ExpressionElement)childValues[0];

            childValues.RemoveAt(0);

            object    second = childValues[0];
            InElement op     = default(InElement);

            if ((second) is IList)
            {
                op = new InElement(operand, (IList)second);
            }
            else
            {
                InvocationListElement il = new InvocationListElement(childValues, _myServices);
                op = new InElement(operand, il);
            }

            node.AddValue(op);
            return(node);
        }
示例#6
0
        public ConditionalElement(ExpressionElement condition, ExpressionElement whenTrue, ExpressionElement whenFalse)
        {
            _myCondition = condition;
            _myWhenTrue  = whenTrue;
            _myWhenFalse = whenFalse;

            if ((!object.ReferenceEquals(_myCondition.ResultType, typeof(bool))))
            {
                base.ThrowCompileException(CompileErrorResourceKeys.FirstArgNotBoolean, CompileExceptionReason.TypeMismatch);
            }

            // The result type is the type that is common to the true/false operands
            if (ImplicitConverter.EmitImplicitConvert(_myWhenFalse.ResultType, _myWhenTrue.ResultType, null) == true)
            {
                _myResultType = _myWhenTrue.ResultType;
            }
            else if (ImplicitConverter.EmitImplicitConvert(_myWhenTrue.ResultType, _myWhenFalse.ResultType, null) == true)
            {
                _myResultType = _myWhenFalse.ResultType;
            }
            else
            {
                base.ThrowCompileException(CompileErrorResourceKeys.NeitherArgIsConvertibleToTheOther, CompileExceptionReason.TypeMismatch, _myWhenTrue.ResultType.Name, _myWhenFalse.ResultType.Name);
            }
        }
 protected Instruction(InstructionSet instructionSet, ExpressionElement argument, RealInstructionGetter realInstructionGetter)
 {
     if (realInstructionGetter != null)
     {
         RealInstruction = realInstructionGetter.GetRealInstruction(instructionSet, argument);
     }
 }
 StringFormatText(string formatText, ExpressionElement[] args, string front, string back)
 {
     _formatText = formatText;
     _args = args;
     _front = front;
     _back = back;
 }
示例#9
0
        public override IDeepCopyable CopyTo(IDeepCopyable other)
        {
            var dest = other as Expression;

            if (dest == null)
            {
                throw new ArgumentException("Can only copy to an object of the same type", "other");
            }

            base.CopyTo(dest);
            if (DescriptionElement != null)
            {
                dest.DescriptionElement = (Hl7.Fhir.Model.FhirString)DescriptionElement.DeepCopy();
            }
            if (NameElement != null)
            {
                dest.NameElement = (Hl7.Fhir.Model.Id)NameElement.DeepCopy();
            }
            if (LanguageElement != null)
            {
                dest.LanguageElement = (Hl7.Fhir.Model.Code)LanguageElement.DeepCopy();
            }
            if (ExpressionElement != null)
            {
                dest.ExpressionElement = (Hl7.Fhir.Model.FhirString)ExpressionElement.DeepCopy();
            }
            if (ReferenceElement != null)
            {
                dest.ReferenceElement = (Hl7.Fhir.Model.FhirUri)ReferenceElement.DeepCopy();
            }
            return(dest);
        }
示例#10
0
        // Try to fold a negated constant int32.  We have to do this so that parsing int32.MinValue will work
        public override Node ExitNegateExpression(Production node)
        {
            IList childValues = this.GetChildValues(node);

            // Get last child
            ExpressionElement childElement = (ExpressionElement)childValues[childValues.Count - 1];

            // Is it an signed integer constant?
            if (object.ReferenceEquals(childElement.GetType(), typeof(Int32LiteralElement)) & childValues.Count == 2)
            {
                ((Int32LiteralElement)childElement).Negate();
                // Add it directly instead of the negate element since it will already be negated
                node.AddValue(childElement);
            }
            else if (object.ReferenceEquals(childElement.GetType(), typeof(Int64LiteralElement)) & childValues.Count == 2)
            {
                ((Int64LiteralElement)childElement).Negate();
                // Add it directly instead of the negate element since it will already be negated
                node.AddValue(childElement);
            }
            else
            {
                // No so just add a regular negate
                this.AddUnaryOp(node, typeof(NegateElement));
            }

            return(node);
        }
示例#11
0
 private RuleModelLight GetRule(ExpressionElement expression, Dictionary <Langue, string> names, RuleType type, bool isEnable)
 => new RuleModelLight()
 {
     Expression = expression.Expression,
     Type       = type.ToString(),
     Name       = string.Join(" | ", names.Select(z => $"{z.Key.Description()} : {z.Value}")),
     IsEnable   = isEnable
 };
示例#12
0
 public static bool AreEqual(ExpressionElement first, ExpressionElement second)
 {
     if (!ExpressionComparer.AreEqual(first.Expression, second.Expression))
     {
         return(false);
     }
     return(true);
 }
示例#13
0
 internal void InitBoolOperator(ExpressionElement arg)
 {
     if (arg is BooleanLiteralElement)
     {
         var boolArg = (BooleanLiteralElement)arg;
         @operator = (boolArg.Value) ? "isTrue" : "isFalse";
     }
 }
示例#14
0
        // Initialize for between two expressions
        public BetweenElement(ExpressionElement operand, ExpressionElement from, ExpressionElement to)
        {
            _operand = operand;
            _from    = from;
            _to      = to;

            // TODO: Validate parameter types
        }
示例#15
0
        public BindingNode(ExpressionElement expressionElement, ILhsTupleExpression <object> compiledExpression, Type resultType, ITupleSource source)
        {
            ExpressionElement   = expressionElement;
            _compiledExpression = compiledExpression;
            ResultType          = resultType;
            Source = source;

            Source.Attach(this);
        }
示例#16
0
        // Initialize for searching a list of values
        public InElement(ExpressionElement operand, IList listElements)
        {
            _myOperand = operand;

            ExpressionElement[] arr = new ExpressionElement[listElements.Count];
            listElements.CopyTo(arr, 0);

            _myArguments = new List <ExpressionElement>(arr);
        }
示例#17
0
 public ILhsExpression <TResult> CompileLhsExpression <TResult>(ExpressionElement element, List <Declaration> declarations)
 {
     if (element.Imports.Count() == 1 &&
         Equals(element.Imports.Single(), declarations.Last()))
     {
         return(CompileLhsFactExpression <TResult>(element));
     }
     return(CompileLhsTupleFactExpression <TResult>(element, declarations));
 }
        private static bool AreParameterPositionsEqual(
            List <Declaration> firstDeclarations, ExpressionElement firstElement,
            List <Declaration> secondDeclarations, ExpressionElement secondElement)
        {
            var parameterMap1 = IndexMap.CreateMap(firstElement.Imports, firstDeclarations);
            var parameterMap2 = IndexMap.CreateMap(secondElement.Imports, secondDeclarations);

            return(Equals(parameterMap1, parameterMap2));
        }
示例#19
0
        public ILhsFactExpression <TResult> CompileLhsFactExpression <TResult>(ExpressionElement element)
        {
            var optimizedExpression = ExpressionOptimizer.Optimize <Func <Fact, TResult> >(
                element.Expression, IndexMap.Unit, tupleInput: false, factInput: true);
            var @delegate   = optimizedExpression.Compile();
            var argumentMap = new ArgumentMap(IndexMap.Unit, 1);
            var expression  = new LhsFactExpression <TResult>(element.Expression, @delegate, argumentMap);

            return(expression);
        }
示例#20
0
        // Initialize for searching a list of values
        public InElement(ExpressionElement operand, IList listElements)
        {
            MyOperand = operand;

            ExpressionElement[] arr = new ExpressionElement[listElements.Count];
            listElements.CopyTo(arr, 0);

            MyArguments = new List <ExpressionElement>(arr);
            this.ResolveForListSearch();
        }
示例#21
0
        public ILhsExpression <TResult> CompileLhsTupleFactExpression <TResult>(ExpressionElement element, List <Declaration> declarations)
        {
            var factMap             = IndexMap.CreateMap(element.Imports, declarations);
            var optimizedExpression = ExpressionOptimizer.Optimize <Func <Tuple, Fact, TResult> >(
                element.Expression, factMap, tupleInput: true, factInput: true);
            var @delegate   = ExpressionCompiler.Compile(optimizedExpression);
            var argumentMap = new ArgumentMap(factMap, element.Expression.Parameters.Count);
            var expression  = new LhsExpression <TResult>(element.Expression, @delegate, argumentMap);

            return(expression);
        }
        public override ParseResult Parse()
        {
            var element = new ExpressionElement();

            element
            .Add(ParseElement(ElementCategory.Term))
            .Add(ParseZeroOrMore(AdditionalTermParser.IsValid,
                                 ElementCategory.AdditionalExpressionTerm));

            return(new ParseResult(ConsumedTokensCount, element));
        }
示例#23
0
    // Evaluates value of group, e.g. (2+4*4) = 18
    // A group is an expression without any sub-groups (expressions in paretheses)
    float EvaluateGroup(List <ExpressionElement> groupElements, List <float> groupValues)
    {
        int valueIndex = 0;

        // resolve multiplication and division
        for (int i = 0; i < groupElements.Count; i++)
        {
            ExpressionElement element = groupElements[i];
            if (element == ExpressionElement.Value)
            {
                valueIndex++;
            }
            else if (element == ExpressionElement.Multiply || element == ExpressionElement.Divide)
            {
                float valueA    = groupValues[valueIndex - 1];
                float valueB    = groupValues[valueIndex];
                float result_dm = (element == ExpressionElement.Multiply) ? valueA * valueB : valueA / valueB;
                groupValues[valueIndex - 1] = result_dm;
                groupValues.RemoveAt(valueIndex);
                groupElements.RemoveRange(i - 1, 2);
                i--;
            }
        }

        // Sum up remaining terms
        valueIndex = 0;
        float result = 0;

        for (int i = 0; i < groupElements.Count; i++)
        {
            ExpressionElement element = groupElements[i];
            if (element == ExpressionElement.Value)
            {
                int sign = 1;
                // Backtrack through operators up to last value to figure out if should be addition or subtraction
                // This deals with multiple operators like x-(-y) = x+y
                for (int j = i - 1; j >= 0; j--)
                {
                    if (groupElements[j] == ExpressionElement.Value)
                    {
                        break;
                    }
                    if (groupElements[j] == ExpressionElement.Minus)
                    {
                        sign *= -1;
                    }
                }
                result += groupValues[valueIndex] * sign;
                valueIndex++;
            }
        }
        return(result);
    }
示例#24
0
        private static void EmitOperand(ExpressionElement operand, ShortCircuitInfo info, FleeILGenerator ilg, IServiceProvider services)
        {
            // Is this operand the target of a label?
            if (info.HasLabel(operand) == true)
            {
                // Yes, so mark it
                Label leftLabel = info.FindLabel(operand);
                ilg.MarkLabel(leftLabel);
            }

            // Emit the operand
            operand.Emit(ilg, services);
        }
示例#25
0
        private void SetupArrayIndexer()
        {
            _myIndexerElement = _myIndexerElements[0];

            if (_myIndexerElements.Count > 1)
            {
                base.ThrowCompileException(CompileErrorResourceKeys.MultiArrayIndexNotSupported, CompileExceptionReason.TypeMismatch);
            }
            else if (ImplicitConverter.EmitImplicitConvert(_myIndexerElement.ResultType, typeof(Int32), null) == false)
            {
                base.ThrowCompileException(CompileErrorResourceKeys.ArrayIndexersMustBeOfType, CompileExceptionReason.TypeMismatch, typeof(Int32).Name);
            }
        }
 private void DetachExpressionHandlers(ExpressionElement expressionBlock)
 {
     if (expressionBlock != null)
     {
         expressionBlock.PropertyChanged += ViewModel_PropertyChanged;
         if (expressionBlock is CompositeElement)
         {
             (expressionBlock as CompositeElement).Children.CollectionChanged       -= ViewModel_PropertyChanged;
             (expressionBlock as CompositeElement).HeaderElements.CollectionChanged -= ViewModel_PropertyChanged;
             (expressionBlock as CompositeElement).Children.ToList().ForEach(DetachExpressionHandlers);
             (expressionBlock as CompositeElement).HeaderElements.ToList().ForEach(DetachExpressionHandlers);
         }
     }
 }
示例#27
0
        /// <summary>
        ///  Emit the arguments to a regular method call
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="elements"></param>
        /// <param name="ilg"></param>
        /// <param name="services"></param>
        private void EmitRegularFunctionInternal(ParameterInfo[] parameters, ExpressionElement[] elements, FleeILGenerator ilg, IServiceProvider services)
        {
            Debug.Assert(parameters.Length == elements.Length, "argument count mismatch");

            // Emit each element and any required conversions to the actual parameter type
            for (int i = 0; i <= parameters.Length - 1; i++)
            {
                ExpressionElement element = elements[i];
                ParameterInfo     pi      = parameters[i];
                element.Emit(ilg, services);
                bool success = ImplicitConverter.EmitImplicitConvert(element.ResultType, pi.ParameterType, ilg);
                Debug.Assert(success, "conversion failed");
            }
        }
示例#28
0
        private void HandleFirstElement(IList elements, IServiceProvider services)
        {
            ExpressionElement first = (ExpressionElement)elements[0];

            // If the first element is not a member element, then we assume it is an expression and replace it with the correct member element
            if (!(first is MemberElement))
            {
                ExpressionMemberElement actualFirst = new ExpressionMemberElement(first);
                elements[0] = actualFirst;
            }
            else
            {
                this.ResolveNamespaces(elements, services);
            }
        }
示例#29
0
        private void BuildSelectionNode(ReteBuilderContext context, ExpressionElement element)
        {
            SelectionNode node = context.CurrentAlphaNode
                                 .ChildNodes.OfType <SelectionNode>()
                                 .FirstOrDefault(sn => ExpressionElementComparer.AreEqual(sn.ExpressionElement, element));

            if (node == null)
            {
                var compiledExpression = ExpressionCompiler.CompileLhsFactExpression <bool>(element);
                node = new SelectionNode(element, compiledExpression);
                context.CurrentAlphaNode.ChildNodes.Add(node);
            }
            node.NodeInfo.Add(context.Rule, element);
            context.CurrentAlphaNode = node;
        }
示例#30
0
 internal void InitStringValueOrSecondField(ExpressionElement arg)
 {
     if (arg is StringLiteralElement)
     {
         @value = ((StringLiteralElement)arg).Value;
     }
     else if (arg is InvocationListElement)
     {
         var invocation = ((InvocationListElement)arg).Tail;
         secondField = ((IdentifierElement)invocation).MemberName.Replace("_", "");
     }
     else
     {
         throw new NotImplementedException();
     }
 }
示例#31
0
        internal ExpressionElement Parse(string expression, IServiceProvider services)
        {
            lock (_mySyncRoot) {
                System.IO.StringReader sr     = new System.IO.StringReader(expression);
                ExpressionParser       parser = this.Parser;
                parser.Reset(sr);
                parser.Tokenizer.Reset(sr);
                FleeExpressionAnalyzer analyzer = (FleeExpressionAnalyzer)parser.Analyzer;

                analyzer.SetServices(services);

                Node rootNode = DoParse();
                analyzer.Reset();
                ExpressionElement topElement = (ExpressionElement)rootNode.Values[0];
                return(topElement);
            }
        }
 internal StringFormatText(string formatText, ExpressionElement[] args)
 {
     _formatText = formatText;
     _args = args;
 }
 internal DisableBracketsText(ExpressionElement core)
 {
     _core = core;
 }
        /// <summary>
        /// Associates the given tree elements.
        /// </summary>
        /// <param name="elements">The elements.</param>
        /// <param name="elementCount">The element count.</param>
        /// <returns></returns>
        private ExpressionTree AssociateElements(ExpressionElement[] elements, int elementCount)
        {
            if(elementCount == 2) {
                throw new Exception("Invalid expression element count");
            }

            // handle special case
            if(elementCount == 1) {
                if(elements[0].Type == ElementType.Implication) {
                    return null;
                }
                else if(elements[0].Type == ElementType.Tree) {
                    return (ExpressionTree)elements[0].Element;
                }
                else {
                    ExpressionTree tree = new ExpressionTree();
                    tree.Root = new FilterNode((FilterBase)elements[0].Element);
                    return tree;
                }
            }

            // normal case
            // middle element should be an Implication
            if(elements[1].Type != ElementType.Implication) {
                return null;
            }

            ExpressionTree parent = new ExpressionTree();
            ExpressionElement left = elements[0];
            ExpressionElement right = elements[2];
            FilterImplication implication = (FilterImplication)elements[1].Element;

            // build the tree
            if(left.Type == ElementType.Tree && right.Type == ElementType.Filter) {
                parent = ExpressionTreeBuilder.AssociateTreeWithFilter((ExpressionTree)left.Element,
                                                                       (FilterBase)right.Element,
                                                                        implication, TreeDirection.Left);
            }
            else if(left.Type == ElementType.Filter && right.Type == ElementType.Tree) {
                parent = ExpressionTreeBuilder.AssociateTreeWithFilter((ExpressionTree)right.Element,
                                                                       (FilterBase)left.Element,
                                                                        implication, TreeDirection.Right);
            }
            else if(left.Type == ElementType.Tree && right.Type == ElementType.Tree) {
                parent = ExpressionTreeBuilder.AssociateTrees((ExpressionTree)left.Element,
                                                              (ExpressionTree)right.Element,
                                                               implication);
            }
            else if(left.Type == ElementType.Filter && right.Type == ElementType.Filter) {
                parent = ExpressionTreeBuilder.AssociateFilters((FilterBase)left.Element,
                                                                (FilterBase)right.Element,
                                                                implication);
            }

            return parent;
        }
        /// <summary>
        /// Parses the expression.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="start">The start position.</param>
        /// <param name="tree">The tree.</param>
        /// <param name="expressionLength">Length of the expression.</param>
        /// <returns></returns>
        private bool ParseExpression(string expression, int start, out ExpressionTree tree, 
            out int expressionLength)
        {
            tree = null;
            expressionLength = 0;

            if(start < 0 || start >= expression.Length) {
                return false;
            }

            // get the end position
            int position = start;
            ExpressionElement[] elements = new ExpressionElement[3];
            int elementPosition = 0;
            int length = expression.Length;

            while(position < length) {
                // jump over spaces
                if(expression[position] == ' ' || expression[position] == ExpressionEndChar) {
                    position++;
                    continue;
                }

                bool positionChanged = false;

                if(expression[position] == ExpressionStartChar) {
                    ExpressionTree child;
                    int subexpressionLength;

                    // invalid expression
                    if(ParseExpression(expression, position + 1, out child, out subexpressionLength) == false) {
                        return false;
                    }

                    // invalid expression
                    if(elementPosition == 1) {
                        return false;
                    }

                    elements[elementPosition].Type = ElementType.Tree;
                    elements[elementPosition].Element = child;
                    elementPosition++;
                    position += subexpressionLength + 1;
                    positionChanged = true;
                }
                else {
                    // get the first substring
                    string[] components = expression.Substring(position).Split(ExpressionSeparators,
                                                                               StringSplitOptions.RemoveEmptyEntries);

                    // invalid expression
                    if(components.Length == 0) {
                        return false;
                    }

                    FilterImplication implication;
                    if(GetImplicationType(components[0], out implication)) {
                        // valid Implication
                        if(elementPosition != 1) {
                            // invalid expression
                            return false;
                        }

                        elements[elementPosition].Type = ElementType.Implication;
                        elements[elementPosition].Element = implication;
                        elementPosition++;
                    }
                    else {
                        // Filter name
                        if(elementPosition == 1) {
                            // invalid expression
                            return false;
                        }

                        FilterBase filter = GetFilter(components[0]);

                        // invalid expression
                        if(filter == null) {
                            return false;
                        }

                        elements[elementPosition].Type = ElementType.Filter;
                        elements[elementPosition].Element = filter;
                        elementPosition++;
                    }

                    position += components[0].Length + 1;
                    positionChanged = true;
                }

                if(positionChanged == false) {
                    position++;
                }

                if(position >= length || elementPosition >= 3) {
                    // end of expression, build evaluation tree
                    if(elementPosition == 2) {
                        // invalid expression
                        return false;
                    }

                    // build the tree
                    tree = AssociateElements(elements, elementPosition);
                    expressionLength = position - start;
                    return true;
                }
            }

            return false;
        }
 public IntegralExpressionElement(string value, ExpressionElement elementType, Operator @operator)
 {
     this.Value = value;
     this.ElementType = elementType;
     this.Operator = @operator;
 }