📄 xquery.java
字号:
// Copyright (c) 2001, 2002, 2003 Per M.A. Bothner and Brainfood Inc.// This is free software; for terms and warranty disclaimer see ./COPYING.package gnu.xquery.lang;import gnu.mapping.*;import gnu.lists.*;import gnu.expr.*;import gnu.text.Char;import kawa.standard.Scheme;import gnu.bytecode.*;import gnu.kawa.lispexpr.LangPrimType;import gnu.xquery.util.*;import gnu.xml.*;import gnu.text.Lexer;import gnu.text.SourceMessages;import java.io.Reader;import java.util.Vector;import gnu.kawa.functions.ConstantFunction0;import gnu.kawa.reflect.ClassMethods;import gnu.math.IntNum;import gnu.kawa.xml.*;/** The XQuery language. */public class XQuery extends Language{ public static final String XQUERY_FUNCTION_NAMESPACE = "http://www.w3.org/2005/xpath-functions"; public static final String KAWA_FUNCTION_NAMESPACE = "http://kawa.gnu.org/"; public static final String QEXO_FUNCTION_NAMESPACE = "http://qexo.gnu.org/"; public static final String LOCAL_NAMESPACE = "http://www.w3.org/2005/xquery-local-functions"; public static final String SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema"; public static final String SCHEMA_INSTANCE_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance"; public static final String XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; public static final Namespace xqueryFunctionNamespace = Namespace.getInstance(XQUERY_FUNCTION_NAMESPACE); public static final Namespace kawaFunctionNamespace = Namespace.getInstance(KAWA_FUNCTION_NAMESPACE); public static final Namespace qexoFunctionNamespace = Namespace.getInstance(QEXO_FUNCTION_NAMESPACE); public static final Namespace[] defaultFunctionNamespacePath = { qexoFunctionNamespace, xqueryFunctionNamespace, Namespace.EmptyNamespace, kawaFunctionNamespace }; static boolean charIsInt = false; /** Pseudo-namespace "prefix" for the default element namespace. */ public static final String DEFAULT_ELEMENT_PREFIX = null; /** Pseudo-namespace "prefix" for the default function namespace. */ public static final String DEFAULT_FUNCTION_PREFIX = "(functions)"; Namespace defaultNamespace; public boolean hasSeparateFunctionNamespace() { return true; } public static gnu.math.Numeric asNumber(Object arg) { if (arg instanceof Char) return gnu.math.IntNum.make(((Char) arg).intValue()); return (gnu.math.Numeric) arg; } public static char asChar(Object x) { if (x instanceof Char) return ((Char) x).charValue(); int i; if (x instanceof gnu.math.Numeric) i = ((gnu.math.Numeric) x).intValue(); else i = -1; if (i < 0 || i > 0xffff) throw new ClassCastException("not a character value"); return (char) i; } public boolean isTrue(Object value) { return gnu.xquery.util.BooleanValue.booleanValue(value); } public gnu.text.Lexer getLexer(InPort inp, SourceMessages messages) { return new XQParser(inp, messages, this); } public Compilation getCompilation (Lexer lexer, SourceMessages messages) { return new Compilation(this, messages, ((XQParser) lexer).lexical); } /** Special parser flag used by <code>evalToFocusProc</code>. */ public static final int PARSE_WITH_FOCUS = 0x10000; public boolean parse (Compilation tr, int options) throws java.io.IOException, gnu.text.SyntaxException { ModuleExp mexp = tr.mainLambda; Compilation.defaultCallConvention = Compilation.CALL_WITH_CONSUMER; tr.mustCompileHere(); XQParser parser = (XQParser) tr.lexer; if (parser.isInteractive()) { Expression sexp = parser.parse(tr); if (sexp == null) return false; mexp.body = sexp; } else if ((options & PARSE_WITH_FOCUS) != 0) { LambdaExp lexp = new LambdaExp(3); Declaration dotDecl = lexp.addDeclaration(XQParser.DOT_VARNAME); dotDecl.setFlag(Declaration.IS_SINGLE_VALUE); dotDecl.noteValue (null); // Does not have a known value. lexp.addDeclaration(XQParser.POSITION_VARNAME, Type.int_type); lexp.addDeclaration(XQParser.LAST_VARNAME, Type.int_type); tr.push(lexp); lexp.body = parser.parse(tr); tr.pop(lexp); mexp.body = lexp; } else { Vector exps = new Vector(10); Expression sexp = mexp.body; if (sexp instanceof BeginExp) { BeginExp bexp = (BeginExp) sexp; int blen = bexp.getExpressionCount(); Expression[] bexps = bexp.getExpressions(); for (int i = 0; i < blen; i++) exps.addElement(bexps[i]); } else if (sexp != null && sexp != QuoteExp.voidExp) { exps.addElement(sexp); } for (;;) { sexp = parser.parse(tr); if (sexp == null) { if (parser.parseCount == 0 && !parser.isInteractive()) { parser.error('e', "empty module", "XPST0003"); return false; } break; } exps.addElement(sexp); } int nexps = exps.size(); if (nexps == 0) mexp.body = QuoteExp.voidExp; else if (nexps == 1) mexp.body = (Expression) exps.elementAt(0); else { Expression[] arr = new Expression[nexps]; exps.copyInto(arr); mexp.body = new BeginExp(arr); } } // It seems silly to pop all the declarations, and then push them // in resolveModule. The complication is that imported variable // declarations are pushed eagerly in the first pass. tr.pop(mexp); if (false) { OutPort dout = OutPort.outDefault(); dout.println ("[Before name-resolving \""+mexp.getName()+"\":"); mexp.print(dout); dout.println(']'); dout.flush(); } XQResolveNames resolver = new XQResolveNames(tr); resolver.functionNamespacePath = parser.functionNamespacePath; resolver.parser = parser; resolver.resolveModule(mexp); // FIXME should move to resolve(Compilation) tr.setState(Compilation.BODY_PARSED); return true; } public void resolve (Compilation comp) { } public static int namespaceForFunctions (int argCount) { return (argCount << 2) | FUNCTION_NAMESPACE; } public static final int VARIADIC_FUNCTION_NAMESPACE = (-1 << 2) | FUNCTION_NAMESPACE; public int getNamespaceOf(Declaration decl) { if (decl.isProcedureDecl()) { if (decl.getCode() < 0) return VARIADIC_FUNCTION_NAMESPACE; Expression value = decl.getValue(); if (value instanceof LambdaExp) { LambdaExp lexp = (LambdaExp) value; if (lexp.min_args == lexp.max_args) return namespaceForFunctions(lexp.min_args); } else if (value instanceof QuoteExp) { Object val = ((QuoteExp) value).getValue(); if (val instanceof Procedure) { Procedure proc = (Procedure) val; int min = proc.minArgs(); int max = proc.maxArgs(); if (min == max) return namespaceForFunctions(min); } } else if (value instanceof ReferenceExp) return getNamespaceOf(((ReferenceExp) value).getBinding()); // I believe we only get here after an error. return VARIADIC_FUNCTION_NAMESPACE; } return VALUE_NAMESPACE; } public boolean hasNamespace (Declaration decl, int namespace) { int dnspace = getNamespaceOf(decl); return (dnspace == namespace || (dnspace == VARIADIC_FUNCTION_NAMESPACE && (namespace & FUNCTION_NAMESPACE) != 0) || (namespace == VARIADIC_FUNCTION_NAMESPACE && (dnspace & FUNCTION_NAMESPACE) != 0)); } public Symbol getSymbol (String name) { return Symbol.make(defaultNamespace, name); } public void define(String name, Object value) { Symbol sym = Symbol.make(defaultNamespace, name); Object prop = value instanceof Procedure ? EnvironmentKey.FUNCTION : null; environ.define(sym, prop, value); } protected void define_method(String name, String cname, String mname) { Symbol sym = Symbol.make(defaultNamespace, name); // This does require eager loading of the class, which takes // extra time on startup. FIXME. ClassType ctype = ClassType.make(cname); Procedure proc = ClassMethods.apply(ctype, mname, '\0', this); proc.setSymbol(sym); environ.define(sym, EnvironmentKey.FUNCTION, proc); } public String getName() { return "XQuery"; } static int envCounter = 0; /** Environment of pre-defined non-standard Qexo/Kawa functions. */ public static Environment extensionsEnvEnv = Environment.getInstance(KAWA_FUNCTION_NAMESPACE); /** Call a procedure with a given focus (context). * @param proc a 3-operand <code>Procedure</code> as returned by * <code>evalToFocusProc</code> * @param item the context item, passed as the first argument to <code>proc</code> * @param position the context position, passed as the second argument * @param size the context size, passed as the second argument * @param out where to send the result of <code>proc</code> */ public void applyWithFocus (Procedure proc, Object item, int position, int size, Consumer out) throws Throwable { CallContext ctx = CallContext.getInstance(); proc.check3(item, IntNum.make(position),IntNum.make(size), ctx); Consumer save = ctx.consumer; try { ctx.consumer = out; ctx.runUntilDone(); } finally { ctx.consumer = save; } } /** Call a procedure with a given focus (context). * @param proc a 3-operand <code>Procedure</code> as returned by * <code>evalToFocusProc</code> * @param item the context item, passed as the first argument to <code>proc</code> * @param position the context position, passed as the second argument * @param size the context size, passed as the second argument * @return the result of applying <code>proc</code> */ public Object applyWithFocus (Procedure proc, Object item, int position, int size) throws Throwable { CallContext ctx = CallContext.getInstance(); int oldIndex = ctx.startFromContext(); try { proc.check3(item, IntNum.make(position),IntNum.make(size), ctx); return ctx.getFromContext(oldIndex); } catch (Throwable ex) { ctx.cleanupFromContext(oldIndex); throw ex; } } /** Call a procedure with each item in a sequence as the context item. * @param proc a 3-operand <code>Procedure</code> as returned by * <code>evalToFocusProc</code> * @param values a sequence. The <code>proc</code> is called once for each * item, with the item as the first argument, a 1-based index as the * second argument, and the sequence size as the third argument. * @param out where to send the result of <code>proc</code> */ public void applyWithFocus (Procedure proc, Object values, Consumer out) throws Throwable { CallContext ctx = CallContext.getInstance();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -