Example #1
0
        /// <summary>
        /// Two parameters.
        /// </summary>
        /// <param name="function"></param>
        /// <returns></returns>
        public static QsSequenceElement FromDelegate(Func <int, QsValue, QsValue, QsValue> function)
        {
            QsSequenceElement el = new QsSequenceElement();

            el.ElementValue = function;
            return(el);
        }
Example #2
0
        /// <summary>
        /// Creates element from sequence.
        /// The element will return the target sequence with the same index.
        /// </summary>
        /// <param name="sequence"></param>
        /// <returns></returns>
        public static QsSequenceElement FromSequenceAccess(QsSequence sequence)
        {
            QsSequenceElement el = new QsSequenceElement();

            el.ElementValue = sequence;

            el.IndexEvaluation     = false;
            el.ParameterEvaluation = false;

            return(el);
        }
Example #3
0
        /// <summary>
        /// Creates element from quantity.
        /// </summary>
        /// <param name="quantity"></param>
        /// <returns></returns>
        public static QsSequenceElement FromQuantity(QsValue quantity)
        {
            QsSequenceElement el = new QsSequenceElement();

            el.ElementValue       = quantity;
            el.ElementDeclaration = quantity.ToString();

            el.IndexEvaluation     = false;
            el.ParameterEvaluation = false;

            return(el);
        }
Example #4
0
        /// <summary>
        /// Parse the element text and make the element point to delegate which evaluate the text if necessary.
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        public static QsSequenceElement Parse(string element, QsEvaluator qse, QsSequence sequence)
        {
            if (string.IsNullOrEmpty(element))
            {
                throw new QsException("Can't create element from empty string.");
            }

            //try direct quantity
            AnyQuantity <double> v;

            if (Unit.TryParseQuantity(element, out v))
            {
                var el = QsSequenceElement.FromQuantity(new QsScalar {
                    NumericalQuantity = v
                });
                el.ElementDeclaration = element;

                el.IndexEvaluation     = false;
                el.ParameterEvaluation = false;
                return(el);
            }
            else
            {
                QsSequenceElement se = new QsSequenceElement();

                //try one index delegate without parameters
                //Create the lambda function that will pass the index and parameters to the expression.
                SimpleLambdaBuilder lb = SimpleLambdaBuilder.Create(typeof(QsValue), "ElementValue");

                //add the index parameter
                lb.Parameter(typeof(int), sequence.SequenceIndexName);


                //find the index parameter in line to know if it will be evaluated or not
                if (element.IndexOf(sequence.SequenceIndexName) > -1)
                {
                    se.IndexEvaluation = true;
                }


                //make the sequence parameters.
                foreach (var seqParam in sequence.Parameters)
                {
                    lb.Parameter(typeof(QsValue), seqParam.Name);
                    if (element.IndexOf(seqParam.Name) > -1)
                    {
                        se.ParameterEvaluation = true;
                    }
                }

                QsVar pvar = new QsVar(qse, element, sequence, lb);

                lb.Body = pvar.ResultExpression;

                LambdaExpression le = lb.MakeLambda();

                se.ElementDeclaration = element;
                se.ElementExpression  = pvar.ResultExpression;
                se.ElementValue       = le.Compile();

                return(se);
            }

            throw new QsException("Check me in sequence element :( :( :( ");
        }
Example #5
0
        /// <summary>
        /// Parse the give sequence text and return <see cref="QsSequence"/> if succeeded
        /// otherwise return null reference.
        /// </summary>
        /// <param name="qse"></param>
        /// <param name="sequence">Sequence Text on the form S[i,j,k, ...]() ..> 40;50&lt;kg>; ..  </param>
        /// <returns></returns>
        public static QsSequence ParseSequence(QsEvaluator qse, string sequence)
        {
            if (sequence.IndexOf("..>") < 0)
            {
                // no forward operator
                if (sequence.IndexOf("<..") < 0)
                {
                    // no backward operator.
                    return(null);    //fast check because sequence have
                }
            }

            Token t = Token.ParseText(sequence);

            t = t.MergeTokens <MultipleSpaceToken>();

            t = t.MergeTokens <PositiveSequenceToken>();  //    ..>  start from 0 index to +ve
            t = t.MergeTokens <NegativeSequenceToken>();  //    <..  start from -1 index to -ve


            if (t.IndexOf(typeof(PositiveSequenceToken)) > -1)
            {
                t = t.RemoveTokenUntil(typeof(MultipleSpaceToken), typeof(PositiveSequenceToken));
            }
            else if (t.IndexOf(typeof(NegativeSequenceToken)) > -1)
            {
                t = t.RemoveTokenUntil(typeof(MultipleSpaceToken), typeof(PositiveSequenceToken));
            }
            else
            {
                return(null);
            }

            // the sequence full declaration syntax in future should look like this
            //   S[k=n->m, l=i->j] ..> k+l/((m-n)*(j-i))
            //   however I only support one index this time.

            t = t.MergeTokens <PointerOperatorToken>();
            t = t.MergeTokens <WordToken>();
            t = t.MergeTokens <NumberToken>();
            t = t.MergeTokens <UnitizedNumberToken>();

            t = t.MergeTokens <NamespaceToken>();

            t = t.MergeTokensInGroups(new ParenthesisGroupToken(), new SquareBracketsGroupToken());
            t = t.RemoveSpaceTokens();

            int nsidx = 0; // surve as a base for indexing token if there is namespace it will be 1 otherwise remain 0

            string declaredNamespace = string.Empty;


            foreach (var tok in t)
            {
                if (tok.TokenClassType == typeof(NamespaceToken))
                {
                    nsidx++;
                    declaredNamespace += tok.TokenValue;
                }
                else
                {
                    break;
                }
            }

            declaredNamespace = declaredNamespace.TrimEnd(':');


            if (t[nsidx + 0].TokenClassType == typeof(WordToken) &&
                (t.Count > 1 ? t[nsidx + 1].TokenClassType == typeof(SquareBracketsGroupToken) : false)        // test for second tokek to be [] group
                )
            {
                Type SequenceTokenType = null;

                int shift = 0;

                if ((nsidx + t.Count) > 2)
                {
                    //check for sequence operator
                    if (t[nsidx + 2].TokenClassType == typeof(PositiveSequenceToken) || t[nsidx + 2].TokenClassType == typeof(NegativeSequenceToken))
                    {
                        //reaching here means the sequence doesn't have parameters only indexers.
                        SequenceTokenType = t[nsidx + 2].TokenClassType;
                    }
                    else if ((nsidx + t.Count) > 4)
                    {
                        if (t[nsidx + 3].TokenClassType == typeof(PositiveSequenceToken) || t[nsidx + 3].TokenClassType == typeof(NegativeSequenceToken))
                        {
                            //reaching here means the sequence has parameterized arguments.
                            SequenceTokenType = t[nsidx + 3].TokenClassType;
                            //shift = nsidx + 1;
                            shift = 1;
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    return(null);
                }


                // s[]   found
                string sequenceName = t[nsidx + 0].TokenValue;


                // Specify the index area  [k=m->n, l=i->j]
                Token IndicesArea = t[nsidx + 1];
                IndicesArea = IndicesArea.RemoveSpaceTokens().TrimStart <LeftSquareBracketToken>().TrimEnd <RightSquareBracketToken>();

                List <string> indexes         = new List <string>();
                List <string> rangeStartNames = new List <string>();
                List <string> rangeEndNames   = new List <string>();

                if (!string.IsNullOrEmpty(IndicesArea.TokenValue))
                {
                    //
                    IndicesArea = IndicesArea.MergeAllBut <MergedToken>(new CommaToken());

                    // validate the syntax and extract the information
                    foreach (var m in IndicesArea)
                    {
                        if (m.Count == 1)
                        {
                            indexes.Add(m[0].TokenValue);
                            rangeStartNames.Add(string.Empty);
                            rangeEndNames.Add(string.Empty);
                        }
                        else
                        {
                            string SyntaxErrorMessage = "Sequence syntax error in indexer declaration: Correct Declaration looks like S[k] or S[k=m->n]";
                            if (m.Count == 5)
                            {
                                if (m[0].TokenClassType == typeof(WordToken) &&
                                    m[1].TokenClassType == typeof(EqualToken) &&
                                    m[2].TokenClassType == typeof(WordToken) &&
                                    m[3].TokenClassType == typeof(PointerOperatorToken) &&
                                    m[4].TokenClassType == typeof(WordToken))
                                {
                                    indexes.Add(m[0].TokenValue);
                                    rangeStartNames.Add(m[2].TokenValue);
                                    rangeEndNames.Add(m[4].TokenValue);
                                }
                                else
                                {
                                    throw new QsSyntaxErrorException(SyntaxErrorMessage);
                                }
                            }
                            else
                            {
                                throw new QsSyntaxErrorException(SyntaxErrorMessage);
                            }
                        }
                    }
                }
                else
                {
                    rangeStartNames.Add(string.Empty);
                    rangeEndNames.Add(string.Empty);
                }

                if (indexes.Count > 1)
                {
                    throw new QsException("Sequences with more than one index are not supported now");
                }


                // get parameters
                string[] parameters = {}; //array with zero count :)
                if (t[nsidx + 2].TokenClassType == typeof(ParenthesisGroupToken))
                {
                    parameters = (from c in t[nsidx + 2]
                                  where c.TokenClassType == typeof(WordToken)
                                  select c.TokenValue).ToArray();
                }


                //make all things between ';' be a whole word.

                t = t.MergeAllBut(nsidx + 3 + shift, typeof(SequenceElementToken), new SemiColonToken());

                QsSequence seqo = GetSequence(qse.Scope, declaredNamespace, FormSequenceSymbolicName(sequenceName, indexes.Count, parameters.Length));

                if (seqo == null)
                {
                    if (SequenceTokenType == typeof(NegativeSequenceToken))
                    {
                        throw new QsException("You can't initialize negative sequence elements without inititialize positive sequence element(s) first");
                    }

                    seqo = new QsSequence(indexes.Count > 0 ? indexes[0] : string.Empty, parameters)
                    {
                        SequenceSymbolicName   = sequenceName,
                        SequenceDeclaration    = t[nsidx + 0].TokenValue + t[nsidx + 1].TokenValue + t[nsidx + shift + 1].TokenValue, //(shift == nsidx + 1 ? t[nsidx + 2].TokenValue : ""),
                        SequenceNamespace      = declaredNamespace,
                        SequenceRangeStartName = rangeStartNames[0],
                        SequenceRangeEndName   = rangeEndNames[0]
                    };
                }
                else
                {
                    //sequence exist
                    if (SequenceTokenType == typeof(PositiveSequenceToken))
                    {
                        //it meanse I am defining the sequence again and overwrite the previous one

                        seqo = new QsSequence(indexes.Count > 0 ? indexes[0] : string.Empty, parameters)
                        {
                            SequenceSymbolicName = sequenceName,
                            SequenceDeclaration  = t[nsidx + 0].TokenValue + t[nsidx + 1].TokenValue + (shift == nsidx + 1 ? t[nsidx + 2].TokenValue : ""),

                            SequenceRangeStartName = rangeStartNames[0],
                            SequenceRangeEndName   = rangeEndNames[0]
                        };
                    }
                    else
                    {
                        seqo.CachedValues.Clear();  //clear all cache because we are defining extra elements.
                    }
                }

                //beginElement is zero index element in positive sequence and -1 index element in negative sequence.

                QsSequenceElement beginElement = QsSequenceElement.Parse(t[nsidx + 3 + shift].TokenValue, qse, seqo);

                if (SequenceTokenType == typeof(PositiveSequenceToken))
                {
                    seqo[0] = beginElement;
                }
                else
                {
                    seqo[-1] = beginElement;
                }

                // take the right side arguments to be added into the sequence.

                int seqoIndex = 5 + shift; // the argument with index 1

                int ix = 1;                //index of sequence.

                if (SequenceTokenType == typeof(NegativeSequenceToken))
                {
                    ix = -2;
                }

                while ((nsidx + seqoIndex) < t.Count)
                {
                    if (t[nsidx + seqoIndex].TokenClassType != typeof(SemiColonToken))
                    {
                        //assuming for now all entered values are quantities.
                        QsSequenceElement seqoElement = QsSequenceElement.Parse(t[nsidx + seqoIndex].TokenValue, qse, seqo);

                        seqo[ix] = seqoElement;  //-5 bacause I am starting from 1 index

                        if (SequenceTokenType == typeof(NegativeSequenceToken))
                        {
                            ix--;
                        }
                        else
                        {
                            ix++;
                        }
                    }
                    seqoIndex++;
                }

                return(seqo);
            }
            else
            {
                return(null);
            }
        }