public DynamicExpressionData(
            OperatorBuilder topOperator,
            ParameterExpression[] orderedParameters)
        {
            OgExpressionStringValue = topOperator.ToString();
            var builderQueue = new Queue <OperatorBuilder>();

            builderQueue.Enqueue(topOperator);

            while (builderQueue.Count > 0)
            {
                var nextNode = builderQueue.Dequeue();
                if (nextNode.type == OperatorType.CONSTANT_VALUE)
                {
                    definitionList.Add(new OperatorDefinition
                    {
                        operatorType = OperatorType.CONSTANT_VALUE,
                        nodeValue    = nextNode.nodeValue
                    });
                }
                else if (nextNode.type == OperatorType.PARAMETER_VALUE)
                {
                    var paramIndex = Array.IndexOf(orderedParameters, nextNode.parameter);
                    definitionList.Add(new OperatorDefinition
                    {
                        operatorType   = OperatorType.PARAMETER_VALUE,
                        parameterIndex = paramIndex
                    });
                }
                else if (nextNode.IsUnary)
                {
                    var rhsIndex = definitionList.Count + builderQueue.Count + 1;
                    definitionList.Add(new OperatorDefinition
                    {
                        operatorType = nextNode.type,
                        rhs          = (ushort)rhsIndex
                    });
                    builderQueue.Enqueue(nextNode.rhs);
                }
                else if (nextNode.IsBinary)
                {
                    var lhsIndex = definitionList.Count + builderQueue.Count + 1;
                    var rhsIndex = definitionList.Count + builderQueue.Count + 2;
                    definitionList.Add(new OperatorDefinition
                    {
                        operatorType = nextNode.type,
                        lhs          = (ushort)lhsIndex,
                        rhs          = (ushort)rhsIndex
                    });
                    builderQueue.Enqueue(nextNode.lhs);
                    builderQueue.Enqueue(nextNode.rhs);
                }
                else
                {
                    throw new Exception("unrecognized node type");
                }
            }
        }
 public static OperatorBuilder Unary(OperatorType opType, OperatorBuilder single)
 {
     if (opType != OperatorType.BOOLEAN_NOT && opType != OperatorType.NEGATE_UNARY)
     {
         throw new SyntaxException($"Unsupported Unary Operator {Enum.GetName(typeof(OperatorType), opType)}");
     }
     return(new OperatorBuilder
     {
         type = opType,
         rhs = single,
     });
 }
 public static OperatorBuilder Binary(OperatorType opType, OperatorBuilder lhs, OperatorBuilder rhs)
 {
     if (opType == OperatorType.BOOLEAN_NOT ||
         opType == OperatorType.NEGATE_UNARY ||
         opType == OperatorType.CONSTANT_VALUE ||
         opType == OperatorType.PARAMETER_VALUE)
     {
         throw new SyntaxException($"Unsupported Binary Operator {Enum.GetName(typeof(OperatorType), opType)}");
     }
     return(new OperatorBuilder
     {
         type = opType,
         rhs = rhs,
         lhs = lhs
     });
 }
Esempio n. 4
0
 /// <summary>
 /// assumes the open paren has already been consumed
 /// </summary>
 /// <param name="enumerator"></param>
 /// <returns></returns>
 private IEnumerable <TokenTarget> ParseToTokenExpressionTillNextParen(IEnumerator <Token> enumerator)
 {
     while (enumerator.MoveNext() && enumerator.Current.token != TokenType.RIGHT_PAREN)
     {
         var current   = enumerator.Current;
         var tokenType = current.token;
         if (tokenType == TokenType.LEFT_PAREN)
         {
             yield return(new TokenExpression(
                              ParseToTokenExpressionTillNextParen(enumerator).ToList(),
                              new CompilerContext(current.context, enumerator.Current.context)));
         }
         else if (expressions.HasFlag(tokenType))
         {
             if (tokenType == TokenType.CONSTANT)
             {
                 yield return(new TokenExpression(OperatorBuilder.ConstantValue(current.value), current.context));
             }
             else if (tokenType == TokenType.VARIABLE)
             {
                 if (!parameters.TryGetValue(current.name, out var parameterExp))
                 {
                     throw current.context.ExceptionHere($"no parameter found for '{current.name}'");
                 }
                 yield return(new TokenExpression(OperatorBuilder.ParameterReference(parameterExp), current.context));
             }
             else
             {
                 throw current.context.ExceptionHere($"Invalid Expression Token Type: '{Enum.GetName(typeof(TokenType), tokenType)}'");
             }
         }
         else
         {
             // the token must be an operator
             yield return(new TokenOperator(current.context)
             {
                 type = tokenType,
             });
         }
     }
 }
Esempio n. 5
0
        public OperatorBuilder CompileSelfToExpression()
        {
            if (!isTokenSeries)
            {
                return(compiledExpression);
            }

            // detect unaries
            int totalPrecedingOperators = 1;
            var unaryOperatorIndexes    = new List <int>();

            for (int i = 0; i < tokenSeries.Count; i++)
            {
                if (tokenSeries[i] is TokenOperator)
                {
                    totalPrecedingOperators++;
                    if (totalPrecedingOperators == 2)
                    {
                        unaryOperatorIndexes.Add(i);
                    }
                    else if (totalPrecedingOperators > 2)
                    {
                        throw tokenSeries[i].context.ExceptionHere(
                                  $"{totalPrecedingOperators} consecutive operators detected");
                    }
                }
                else
                {
                    totalPrecedingOperators = 0;
                }
            }

            foreach (var unaryIndex in ((IEnumerable <int>)unaryOperatorIndexes).Reverse())
            {
                var op = tokenSeries[unaryIndex] as TokenOperator;
                tokenSeries.RemoveAt(unaryIndex);
                if (tokenSeries.Count <= unaryIndex)
                {
                    throw op.context.ExceptionHere("Stranded Operator");
                }
                var value            = tokenSeries[unaryIndex] as TokenExpression;
                var valuesExpression = value.CompileSelfToExpression();
                switch (op.type)
                {
                case TokenType.SUBTRACT:
                    tokenSeries[unaryIndex] = new TokenExpression(OperatorBuilder.Unary(OperatorType.NEGATE_UNARY, valuesExpression), op.context);
                    break;

                case TokenType.BOOLEAN_NOT:
                    tokenSeries[unaryIndex] = new TokenExpression(OperatorBuilder.Unary(OperatorType.BOOLEAN_NOT, valuesExpression), op.context);
                    break;

                default:
                    throw op.context.ExceptionHere($"Unsupported unary operator: {Enum.GetName(typeof(TokenType), op.type)}");
                }
            }

            var operatorNodes   = new List <LinkedListNode <TokenTarget> >();
            var tokenLinkedList = new LinkedList <TokenTarget>(tokenSeries);
            var currentNode     = tokenLinkedList.First;

            do
            {
                if (currentNode.Value is TokenOperator op)
                {
                    operatorNodes.Add(currentNode);
                }
            } while ((currentNode = currentNode.Next) != null);

            operatorNodes.Sort((a, b) => Token.OPERATOR_PRECIDENCE[(a.Value as TokenOperator).type] - Token.OPERATOR_PRECIDENCE[(b.Value as TokenOperator).type]);

            foreach (var operatorNode in operatorNodes)
            {
                var firstVal  = operatorNode.Previous.Value as TokenExpression;
                var op        = operatorNode.Value as TokenOperator;
                var secondVal = operatorNode.Next.Value as TokenExpression;

                var newVal = new TokenExpression(
                    GetExpressionFromBinaryOperator(
                        firstVal.CompileSelfToExpression(),
                        op,
                        secondVal.CompileSelfToExpression()),
                    firstVal.context);
                tokenLinkedList.Remove(firstVal);
                operatorNode.Value = newVal;
                tokenLinkedList.Remove(secondVal);
            }

            //should be all compiled
            if (tokenLinkedList.Count != 1)
            {
                if (tokenLinkedList.Count > 0)
                {
                    throw tokenLinkedList.First.Value.context.ExceptionHere("Compilation error: token string could not compile to one expression");
                }
                else
                {
                    throw new SyntaxException("Compilation error: token string could not compile to one expression");
                }
            }

            // the final node could be uncompiled if this was a simple nested paren. call compile method just in case, rely on short-circuit if already compiled.
            return((tokenLinkedList.First.Value as TokenExpression).CompileSelfToExpression());
        }
Esempio n. 6
0
 public TokenExpression(OperatorBuilder expression, CompilerContext context) : base(context)
 {
     compiledExpression = expression;
     isTokenSeries      = false;
 }
Esempio n. 7
0
        private OperatorBuilder GetExpressionFromBinaryOperator(OperatorBuilder a, TokenOperator op, OperatorBuilder b)
        {
            OperatorType newOpType = default;

            switch (op.type)
            {
            case TokenType.MULTIPLY:
                newOpType = OperatorType.MULTIPLY;
                break;

            case TokenType.DIVIDE:
                newOpType = OperatorType.DIVIDE;
                break;

            case TokenType.REMAINDER:
                newOpType = OperatorType.REMAINDER;
                break;

            case TokenType.EXPONENT:
                newOpType = OperatorType.EXPONENT;
                break;

            case TokenType.ADD:
                newOpType = OperatorType.ADD;
                break;

            case TokenType.SUBTRACT:
                newOpType = OperatorType.SUBTRACT;
                break;

            case TokenType.GREATER_THAN:
                newOpType = OperatorType.GREATER_THAN;
                break;

            case TokenType.LESS_THAN:
                newOpType = OperatorType.LESS_THAN;
                break;

            case TokenType.GREATER_THAN_OR_EQ:
                newOpType = OperatorType.GREATER_THAN_OR_EQ;
                break;

            case TokenType.LESS_THAN_OR_EQ:
                newOpType = OperatorType.LESS_THAN_OR_EQ;
                break;

            case TokenType.EQUAL:
                newOpType = OperatorType.EQUAL;
                break;

            case TokenType.NOT_EQUAL:
                newOpType = OperatorType.NOT_EQUAL;
                break;

            case TokenType.BOOLEAN_AND:
                newOpType = OperatorType.BOOLEAN_AND;
                break;

            case TokenType.BOOLEAN_OR:
                newOpType = OperatorType.BOOLEAN_OR;
                break;

            default:
                throw op.context.ExceptionHere($"Invalid binary operator symbol: {Enum.GetName(typeof(TokenType), op.type)}");
            }
            return(OperatorBuilder.Binary(newOpType, a, b));
        }