Exemple #1
0
 /// <summary>
 /// Get sequence object from the scope memory.
 /// </summary>
 /// <param name="scope"></param>
 /// <param name="qsNamespace"></param>
 /// <param name="sequenceName"></param>
 /// <returns></returns>
 public static QsSequence GetSequence(QsScope scope, string qsNamespace, string sequenceName)
 {
     if (string.IsNullOrEmpty(qsNamespace))
     {
         // no namespace included then it is from the local scope.
         var seq = (QsSequence)QsEvaluator.GetScopeValueOrNull(scope, qsNamespace, sequenceName);
         return(seq);
     }
     else
     {
         QsNamespace ns = QsNamespace.GetNamespace(scope, qsNamespace);
         return((QsSequence)ns.GetValueOrNull(sequenceName));
     }
 }
        public static QsFunction ParseFunction(QsEvaluator qse, string functionDeclaration)
        {
            if (functionDeclaration.StartsWith("@"))
            {
                return(null);
            }

            // fast check for function as = and ) before it.
            int eqIdx = functionDeclaration.IndexOf('=');

            if (eqIdx > 0)
            {
                // check if ')' exist before the equal '=' sign.
                while (eqIdx > 0)
                {
                    eqIdx--;
                    if (functionDeclaration[eqIdx] == ' ')
                    {
                        continue;                                      // ignore spaces.
                    }
                    if (functionDeclaration[eqIdx] == '\t')
                    {
                        continue;                                      // ignore tabs
                    }
                    if (functionDeclaration[eqIdx] == ')')
                    {
                        goto GoParseFunction;
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
            else
            {
                // equal sign exist.
                return(null);
            }

GoParseFunction:


            var functionToken = TokenizeFunction(functionDeclaration);

            return(ParseFunction(qse, functionDeclaration, functionToken));
        }
        /// <summary>
        /// Get the quantity from the parameter body on the form  ([namespace:]variable)  x:var or var
        /// </summary>
        public QsValue GetIndirectQuantity(QsScope scope)
        {
            try
            {
                var q = QsEvaluator.GetScopeQsValue(scope, NamespaceName, NamespaceVariableName);
                return(q);
            }
            catch (QsVariableNotFoundException e)
            {
                // add extra data to the exception about the parameter name itself.
                //  its like accumulating information on the same exception.

                e.ExtraData = ParameterRawText;

                // and throw it again
                throw e;
            }
        }
        /// <summary>
        /// Get the function that is stored in the scope.
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="realName"></param>
        /// <returns></returns>
        public static QsFunction GetFunction(QsScope scope, string qsNamespace, string functionName)
        {
            if (string.IsNullOrEmpty(qsNamespace))
            {
                // no namespace included then it is from the local scope.


                // I am adding the mathmatical functions in the root namespace
                // so I will test for the function namespace and

                QsFunction function = (QsFunction)MathNamespace.GetValueOrNull(functionName);

                // built int math functions will be overwrite any other functions
                if (function != null)
                {
                    return(function);
                }
                else
                {
                    function = (QsFunction)QsEvaluator.GetScopeValueOrNull(scope, qsNamespace, functionName);
                }

                return(function);
            }
            else
            {
                try
                {
                    QsNamespace ns = QsNamespace.GetNamespace(scope, qsNamespace);


                    return((QsFunction)ns.GetValue(functionName));
                }
                catch (QsVariableNotFoundException)
                {
                    return(null);
                }
            }
        }
Exemple #5
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 :( :( :( ");
        }
Exemple #6
0
        public override object Run(Scope scope)
        {
            string code = string.Empty;
            //try
            {
                if (SourceUnit.HasPath)
                {
                    if (File.Exists(SourceUnit.Path))
                    {
                        code = SourceUnit.GetReader().ReadToEnd();
                    }
                    else
                    {
                        throw new QsException("File Not Found");
                    }
                }
                else
                {
                    code = SourceUnit.GetReader().ReadToEnd();
                }
            }
            //catch(Exception xx)
            //{
            //    code = LastLine;   //workaround because Host have something weird in SourceTextReader that don't work linux mono
            //}

            QsEvaluator qs = QsEvaluator.CurrentEvaluator;

            //qs.Scope = scope;

            string[] lines = code.Split(Environment.NewLine.ToCharArray());

            object ret = null;

            foreach (string line in lines)
            {
                if (!string.IsNullOrEmpty(line))
                {
                    // test for directive like  %module  %unitdef gogo m/s^6
                    // hmmm
                    //  changed it to #module   .. who cares :P :P
                    //
                    if (line.TrimStart().StartsWith("#module"))
                    {
                        // this is a directive
                        var dir = line.TrimStart();
                        QsRoot.Root.LoadLibrary(dir.Substring(8).Trim());
                    }
                    else if (!line.StartsWith("#"))
                    {
                        //I want to exclude # if it was between parentthesis.
                        //  oo(ferwe#kd adflk ) #

                        // first pass (from left to right): find the # char which is the comment.
                        int pc = 0; // for ()

                        bool qcOpened = false;
                        int  ix       = 0;

                        StringBuilder sb = new StringBuilder();
                        while (ix < line.Length)
                        {
                            var c = line[ix];
                            if (c == '(')
                            {
                                pc++;
                            }

                            if (line[ix] == '"')
                            {
                                if (ix > 0)
                                {
                                    if (line[ix - 1] != '\\') // not escape charachter for qoutation mark
                                    {
                                        qcOpened = !qcOpened;
                                    }
                                }
                                else
                                {
                                    qcOpened = !qcOpened;
                                }
                            }

                            // is it a comment charachter.
                            if (c == '#')
                            {
                                if (pc == 0 && qcOpened == false)
                                {
                                    // found the comment
                                    //  break
                                    break;
                                }
                            }

                            if (c == ')')
                            {
                                pc--;
                            }

                            sb.Append(c);

                            ix++;
                        }

                        string l2 = sb.ToString().Trim();  // text without comment.

                        //check the last charachter
                        if (l2.EndsWith(";"))
                        {
                            //trim the ';' and silent evaluate the expression.
                            ret = qs.SilentEvaluate(l2.Trim(';'));
                        }
                        else
                        {
                            ret = qs.Evaluate(l2);
                        }
                    }
                }
            }

            return(ret);
        }
Exemple #7
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);
            }
        }
        public static QsFunction ParseFunction(QsEvaluator qse, string functionDeclaration, Token functionToken)
        {
            int nsidx = 0; // surve as a base for indexing token if there is namespace it will be 1 otherwise remain 0

            // specify the namespaces end token.
            string functionNamespace = "";

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

            if (
                functionToken[nsidx].TokenClassType == typeof(WordToken) &&
                (functionToken.Count > (nsidx + 1) ? functionToken[nsidx + 1].TokenClassType == typeof(ParenthesisGroupToken) : false) &&
                (functionToken.Count > (nsidx + 2) ? functionToken[nsidx + 2].TokenClassType == typeof(EqualToken) : false)
                )
            {
                //get function name
                // will be the first token after excluding namespace.

                string functionName = string.Empty;


                functionName = functionToken[nsidx].TokenValue;

                //remove the last : from namespace
                functionNamespace = functionNamespace.TrimEnd(':');

                List <string>      textParams = new List <string>();
                List <QsParamInfo> prms       = new List <QsParamInfo>();
                foreach (var c in functionToken[nsidx + 1])
                {
                    if (
                        c.TokenValue.StartsWith("(") ||
                        c.TokenValue.StartsWith(")") ||
                        c.TokenValue.StartsWith(",") ||
                        c.TokenClassType == typeof(MultipleSpaceToken)
                        )
                    {
                        //ignore these things.
                    }
                    else
                    {
                        if (char.IsLetter(c.TokenValue[0]))
                        {
                            textParams.Add(c.TokenValue);
                            prms.Add(new QsParamInfo {
                                Name = c.TokenValue, Type = QsParamType.Value
                            });
                        }
                        else
                        {
                            throw new QsSyntaxErrorException("Parameter name must statrt with a letter");
                        }
                    }
                }

                //declared for first time a default function.
                QsFunction qf = new QsFunction(functionDeclaration)
                {
                    FunctionNamespace = functionNamespace,
                    FunctionName      = functionName,
                    Parameters        = prms.ToArray()
                };


                //LambdaBuilder lb = Utils.Lambda(typeof(QsValue), functionName);
                SimpleLambdaBuilder lb = SimpleLambdaBuilder.Create(typeof(QsValue), functionName);

                foreach (QsParamInfo prm in prms)
                {
                    lb.Parameter(typeof(QsParameter), prm.Name);
                }

                List <Expression> statements = new List <Expression>();

                qf.FunctionBody = functionDeclaration.Substring(functionToken[nsidx + 2].IndexInText + functionToken[nsidx + 2].TokenValueLength).Trim();

                Token functionBodyTokens;
                QsVar qv = new QsVar(qse, qf.FunctionBody, qf, lb, out functionBodyTokens);

                statements.Add(qv.ResultExpression);   //making the variable expression itself make it the return value of the function.

                lb.Body = Expression.Block(statements);



                LambdaExpression lbe = lb.MakeLambda();

                qf.FunctionExpression = lbe;

                qf.FunctionBodyToken = functionBodyTokens;

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