Beispiel #1
0
        private IOperator BuildFunction(string exp, Token token)
        {
            var nametk  = token.childs[0];
            var namestr = exp.Substring(nametk.range.begin, nametk.range.end - nametk.range.begin);

            if (FunctionTable.TryGetValue(namestr, out Func <double[], double> func))
            {
                var         argsLen = token.childs.Count - 1;
                IOperator[] ops     = new IOperator[argsLen];
                for (int i = 0; i < argsLen; i++)
                {
                    ops[i] = BuildExp(exp, token.childs[i + 1]);
                }
                return(new OpFun(ops, func));
            }
            return(null);
        }
Beispiel #2
0
 /// <summary>
 /// Lookup a ExpressionEvaluator (function) by name.
 /// </summary>
 /// <param name="functionName">function name.</param>
 /// <returns>ExpressionEvaluator.</returns>
 public static ExpressionEvaluator Lookup(string functionName) => Functions.TryGetValue(functionName, out var function) ? function : null;
Beispiel #3
0
        QilNode IXPathEnvironment.ResolveFunction(string prefix, string name, IList <QilNode> args, IFocus env)
        {
            Debug.Assert(!args.IsReadOnly, "Writable collection expected");
            if (prefix.Length == 0)
            {
                FunctionInfo?func;
                if (FunctionTable.TryGetValue(name, out func))
                {
                    func.CastArguments(args, name, _f);

                    switch (func.id)
                    {
                    case FuncId.Current:
                        if (!_allowCurrent)
                        {
                            throw new XslLoadException(SR.Xslt_CurrentNotAllowed);
                        }
                        // NOTE: This is the only place where the current node (and not the context node) must be used
                        return(((IXPathEnvironment)this).GetCurrent() !);

                    case FuncId.Key:
                        if (!_allowKey)
                        {
                            throw new XslLoadException(SR.Xslt_KeyNotAllowed);
                        }
                        return(CompileFnKey(args[0], args[1], env));

                    case FuncId.Document: return(CompileFnDocument(args[0], args.Count > 1 ? args[1] : null));

                    case FuncId.FormatNumber: return(CompileFormatNumber(args[0], args[1], args.Count > 2 ? args[2] : null));

                    case FuncId.UnparsedEntityUri: return(CompileUnparsedEntityUri(args[0]));

                    case FuncId.GenerateId: return(CompileGenerateId(args.Count > 0 ? args[0] : env.GetCurrent() !));

                    case FuncId.SystemProperty: return(CompileSystemProperty(args[0]));

                    case FuncId.ElementAvailable: return(CompileElementAvailable(args[0]));

                    case FuncId.FunctionAvailable: return(CompileFunctionAvailable(args[0]));

                    default:
                        Debug.Fail($"{func.id} is present in the function table, but absent from the switch");
                        return(null);
                    }
                }
                else
                {
                    throw new XslLoadException(SR.Xslt_UnknownXsltFunction, Compiler.ConstructQName(prefix, name));
                }
            }
            else
            {
                string ns = ResolvePrefixThrow(/*ignoreDefaultNs:*/ true, prefix);
                Debug.Assert(ns != null);
                if (ns == XmlReservedNs.NsMsxsl)
                {
                    if (name == "node-set")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(CompileMsNodeSet(args[0]));
                    }
                    else if (name == "string-compare")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 2, /*maxArg:*/ 4, name, args.Count);
                        return(_f.InvokeMsStringCompare(
                                   /*x:      */ _f.ConvertToString(args[0]),
                                   /*y:      */ _f.ConvertToString(args[1]),
                                   /*lang:   */ 2 < args.Count ? _f.ConvertToString(args[2]) : _f.String(string.Empty),
                                   /*options:*/ 3 < args.Count ? _f.ConvertToString(args[3]) : _f.String(string.Empty)
                                   ));
                    }
                    else if (name == "utc")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(_f.InvokeMsUtc(/*datetime:*/ _f.ConvertToString(args[0])));
                    }
                    else if (name == "format-date" || name == "format-time")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 3, name, args.Count);
                        return(_f.InvokeMsFormatDateTime(
                                   /*datetime:*/ _f.ConvertToString(args[0]),
                                   /*format:  */ 1 < args.Count ? _f.ConvertToString(args[1]) : _f.String(string.Empty),
                                   /*lang:    */ 2 < args.Count ? _f.ConvertToString(args[2]) : _f.String(string.Empty),
                                   /*isDate:  */ _f.Boolean(name == "format-date")
                                   ));
                    }
                    else if (name == "local-name")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(_f.InvokeMsLocalName(_f.ConvertToString(args[0])));
                    }
                    else if (name == "namespace-uri")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(_f.InvokeMsNamespaceUri(_f.ConvertToString(args[0]), env.GetCurrent() !));
                    }
                    else if (name == "number")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(_f.InvokeMsNumber(args[0]));
                    }
                }

                if (ns == XmlReservedNs.NsExsltCommon)
                {
                    if (name == "node-set")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(CompileMsNodeSet(args[0]));
                    }
                    else if (name == "object-type")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(EXslObjectType(args[0]));
                    }
                }

                // NOTE: If you add any function here, add it to IsFunctionAvailable as well

                // Ensure that all node-set parameters are DocOrderDistinct
                for (int i = 0; i < args.Count; i++)
                {
                    args[i] = _f.SafeDocOrderDistinct(args[i]);
                }

                if (_compiler.Settings.EnableScript)
                {
                    XmlExtensionFunction?scrFunc = _compiler.Scripts.ResolveFunction(name, ns, args.Count, (IErrorHelper)this);
                    if (scrFunc != null)
                    {
                        return(GenerateScriptCall(_f.QName(name, ns, prefix), scrFunc, args));
                    }
                }
                else
                {
                    if (_compiler.Scripts.ScriptClasses.ContainsKey(ns))
                    {
                        ReportWarning(SR.Xslt_ScriptsProhibited);
                        return(_f.Error(_lastScope !.SourceLine, SR.Xslt_ScriptsProhibited));
                    }
                }

                return(_f.XsltInvokeLateBound(_f.QName(name, ns, prefix), args));
            }
        }
Beispiel #4
0
        public virtual QilNode Function(string prefix, string name, IList <QilNode> args)
        {
            Debug.Assert(!args.IsReadOnly, "Writable collection expected");
            if (prefix.Length == 0)
            {
                FunctionInfo func;
                if (FunctionTable.TryGetValue(name, out func))
                {
                    func.CastArguments(args, name, _f);

                    switch (func.id)
                    {
                    case FuncId.Not: return(_f.Not(args[0]));

                    case FuncId.Last: return(GetLastPosition());

                    case FuncId.Position: return(GetCurrentPosition());

                    case FuncId.Count: return(_f.XsltConvert(_f.Length(_f.DocOrderDistinct(args[0])), T.DoubleX));

                    case FuncId.LocalName: return(args.Count == 0 ? _f.LocalNameOf(GetCurrentNode()) : LocalNameOfFirstNode(args[0]));

                    case FuncId.NamespaceUri: return(args.Count == 0 ? _f.NamespaceUriOf(GetCurrentNode()) : NamespaceOfFirstNode(args[0]));

                    case FuncId.Name: return(args.Count == 0 ? NameOf(GetCurrentNode()) : NameOfFirstNode(args[0]));

                    case FuncId.String: return(args.Count == 0 ? _f.XPathNodeValue(GetCurrentNode()) : _f.ConvertToString(args[0]));

                    case FuncId.Number: return(args.Count == 0 ? _f.XsltConvert(_f.XPathNodeValue(GetCurrentNode()), T.DoubleX) : _f.ConvertToNumber(args[0]));

                    case FuncId.Boolean: return(_f.ConvertToBoolean(args[0]));

                    case FuncId.True: return(_f.True());

                    case FuncId.False: return(_f.False());

                    case FuncId.Id: return(_f.DocOrderDistinct(_f.Id(GetCurrentNode(), args[0])));

                    case FuncId.Concat: return(_f.StrConcat(args));

                    case FuncId.StartsWith: return(_f.InvokeStartsWith(args[0], args[1]));

                    case FuncId.Contains: return(_f.InvokeContains(args[0], args[1]));

                    case FuncId.SubstringBefore: return(_f.InvokeSubstringBefore(args[0], args[1]));

                    case FuncId.SubstringAfter: return(_f.InvokeSubstringAfter(args[0], args[1]));

                    case FuncId.Substring:
                        return(args.Count == 2 ? _f.InvokeSubstring(args[0], args[1]) : _f.InvokeSubstring(args[0], args[1], args[2]));

                    case FuncId.StringLength:
                        return(_f.XsltConvert(_f.StrLength(args.Count == 0 ? _f.XPathNodeValue(GetCurrentNode()) : args[0]), T.DoubleX));

                    case FuncId.Normalize:
                        return(_f.InvokeNormalizeSpace(args.Count == 0 ? _f.XPathNodeValue(GetCurrentNode()) : args[0]));

                    case FuncId.Translate: return(_f.InvokeTranslate(args[0], args[1], args[2]));

                    case FuncId.Lang: return(_f.InvokeLang(args[0], GetCurrentNode()));

                    case FuncId.Sum: return(Sum(_f.DocOrderDistinct(args[0])));

                    case FuncId.Floor: return(_f.InvokeFloor(args[0]));

                    case FuncId.Ceiling: return(_f.InvokeCeiling(args[0]));

                    case FuncId.Round: return(_f.InvokeRound(args[0]));

                    default:
                        Debug.Fail(func.id + " is present in the function table, but absent from the switch");
                        return(null);
                    }
                }
            }

            return(_environment.ResolveFunction(prefix, name, args, (IFocus)this));
        }