Exemple #1
0
        /// <summary>
        /// Applies the token to the parsing state. Will pop the operator stack executing all the operators storing each of the operands
        /// When we reach an opening bracket it will pass the stored operands to the opening bracket to be processed.
        /// </summary>
        /// <param name="token">The token to apply.</param>
        /// <param name="state">The state to apply the token to.</param>
        /// <exception cref="OperandExpectedException">When there are delimeters but no operands between them.</exception>
        /// <exception cref="BracketUnmatchedException">When there was no matching closing bracket.</exception>
        public override void Apply(Token token, ParseState state)
        {
            Stack <Operand> bracketOperands   = new Stack <Operand>();
            StringSegment   previousSeperator = token.SourceMap;
            bool            hasSeperators     = false;

            while (state.Operators.Count > 0)
            {
                var currentOperator = state.Operators.Pop();
                if (BracketOpenDefinitions.Contains(currentOperator.Definition))
                {
                    var operand       = state.Operands.Count > 0 ? state.Operands.Peek() : null;
                    var firstSegment  = currentOperator.SourceMap;
                    var secondSegment = previousSeperator;
                    if (operand != null && operand.SourceMap.IsBetween(firstSegment, secondSegment))
                    {
                        bracketOperands.Push(state.Operands.Pop());
                    }
                    else if (hasSeperators && (operand == null || !operand.SourceMap.IsBetween(firstSegment, secondSegment)))
                    {
                        //if we have seperators then we should have something between the last seperator and the open bracket.
                        throw new OperandExpectedException(StringSegment.Between(firstSegment, secondSegment));
                    }

                    //pass our all bracket operands to the open bracket method, he will know
                    //what we should do.
                    var closeBracketOperator = new Operator(this, token.SourceMap, () => { });
                    ((BracketOpenDefinition)currentOperator.Definition).ApplyBracketOperands(
                        currentOperator,
                        bracketOperands,
                        closeBracketOperator,
                        state);
                    return;
                }
                else if (ListDelimeterDefinition != null && currentOperator.Definition == ListDelimeterDefinition)
                {
                    hasSeperators = true;
                    var operand = state.Operands.Pop();

                    //if our operator is not between two delimeters, then we are missing an operator
                    var firstSegment  = currentOperator.SourceMap;
                    var secondSegment = previousSeperator;
                    if (!operand.SourceMap.IsBetween(firstSegment, secondSegment))
                    {
                        throw new OperandExpectedException(StringSegment.Between(firstSegment, secondSegment));
                    }

                    bracketOperands.Push(operand);
                    previousSeperator = currentOperator.SourceMap;
                }
                else
                {
                    //regular operator, execute it
                    currentOperator.Execute();
                }
            }

            //We have pop'd through all the operators and not found an open bracket
            throw new BracketUnmatchedException(token.SourceMap);
        }
        /// <summary>
        /// Applies the bracket operands. Adds the evaluated operand within the bracket to the state.
        /// </summary>
        /// <param name="bracketOpen">The operator that opened the bracket.</param>
        /// <param name="bracketOperands">The list of operands within the brackets.</param>
        /// <param name="bracketClose">The operator that closed the bracket.</param>
        /// <param name="state">The current parse state.</param>
        /// <exception cref="OperandExpectedException">When brackets are empty.</exception>
        /// <exception cref="OperandUnexpectedException">When there is more than one element in the brackets</exception>
        public virtual void ApplyBracketOperands(Operator bracketOpen, Stack <Operand> bracketOperands, Operator bracketClose, ParseState state)
        {
            if (bracketOperands.Count == 0)
            {
                var insideBrackets = StringSegment.Between(bracketOpen.SourceMap, bracketClose.SourceMap);
                throw new OperandExpectedException(insideBrackets);
            }
            else if (bracketOperands.Count > 1)
            {
                var operandSpan = StringSegment.Encompass(bracketOperands.Skip(1).Select(x => x.SourceMap));
                throw new OperandUnexpectedException(operandSpan);
            }


            var bracketOperand = bracketOperands.Pop();
            var sourceMap      = StringSegment.Encompass(new[] { bracketOpen.SourceMap, bracketOperand.SourceMap, bracketClose.SourceMap });

            state.Operands.Push(new Operand(bracketOperand.Expression, sourceMap));
        }