286N/A/*
286N/A * reserved comment block
286N/A * DO NOT REMOVE OR ALTER!
286N/A */
286N/A/*
286N/A * Copyright 1999-2004 The Apache Software Foundation.
286N/A *
286N/A * Licensed under the Apache License, Version 2.0 (the "License");
286N/A * you may not use this file except in compliance with the License.
286N/A * You may obtain a copy of the License at
286N/A *
286N/A * http://www.apache.org/licenses/LICENSE-2.0
286N/A *
286N/A * Unless required by applicable law or agreed to in writing, software
286N/A * distributed under the License is distributed on an "AS IS" BASIS,
286N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
286N/A * See the License for the specific language governing permissions and
286N/A * limitations under the License.
286N/A */
286N/A/*
286N/A * $Id: Compiler.java,v 1.2.4.1 2005/09/14 19:47:10 jeffsuttor Exp $
286N/A */
286N/Apackage com.sun.org.apache.xpath.internal.compiler;
286N/A
286N/Aimport javax.xml.transform.ErrorListener;
286N/Aimport javax.xml.transform.SourceLocator;
286N/Aimport javax.xml.transform.TransformerException;
286N/A
286N/Aimport com.sun.org.apache.xalan.internal.res.XSLMessages;
286N/Aimport com.sun.org.apache.xml.internal.dtm.Axis;
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTMFilter;
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTMIterator;
286N/Aimport com.sun.org.apache.xml.internal.utils.PrefixResolver;
286N/Aimport com.sun.org.apache.xml.internal.utils.QName;
286N/Aimport com.sun.org.apache.xml.internal.utils.SAXSourceLocator;
286N/Aimport com.sun.org.apache.xpath.internal.Expression;
286N/Aimport com.sun.org.apache.xpath.internal.axes.UnionPathIterator;
286N/Aimport com.sun.org.apache.xpath.internal.axes.WalkerFactory;
286N/Aimport com.sun.org.apache.xpath.internal.functions.FuncExtFunction;
286N/Aimport com.sun.org.apache.xpath.internal.functions.FuncExtFunctionAvailable;
286N/Aimport com.sun.org.apache.xpath.internal.functions.Function;
286N/Aimport com.sun.org.apache.xpath.internal.functions.WrongNumberArgsException;
286N/Aimport com.sun.org.apache.xpath.internal.objects.XNumber;
286N/Aimport com.sun.org.apache.xpath.internal.objects.XString;
286N/Aimport com.sun.org.apache.xpath.internal.operations.And;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Div;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Equals;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Gt;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Gte;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Lt;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Lte;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Minus;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Mod;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Mult;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Neg;
286N/Aimport com.sun.org.apache.xpath.internal.operations.NotEquals;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Operation;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Or;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Plus;
286N/Aimport com.sun.org.apache.xpath.internal.operations.UnaryOperation;
286N/Aimport com.sun.org.apache.xpath.internal.operations.Variable;
286N/Aimport com.sun.org.apache.xpath.internal.patterns.FunctionPattern;
286N/Aimport com.sun.org.apache.xpath.internal.patterns.NodeTest;
286N/Aimport com.sun.org.apache.xpath.internal.patterns.StepPattern;
286N/Aimport com.sun.org.apache.xpath.internal.patterns.UnionPattern;
286N/Aimport com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
286N/A
286N/A/**
286N/A * An instance of this class compiles an XPath string expression into
286N/A * a Expression object. This class compiles the string into a sequence
286N/A * of operation codes (op map) and then builds from that into an Expression
286N/A * tree.
286N/A * @xsl.usage advanced
286N/A */
286N/Apublic class Compiler extends OpMap
286N/A{
286N/A
286N/A /**
286N/A * Construct a Compiler object with a specific ErrorListener and
286N/A * SourceLocator where the expression is located.
286N/A *
286N/A * @param errorHandler Error listener where messages will be sent, or null
286N/A * if messages should be sent to System err.
286N/A * @param locator The location object where the expression lives, which
286N/A * may be null, but which, if not null, must be valid over
286N/A * the long haul, in other words, it will not be cloned.
286N/A * @param fTable The FunctionTable object where the xpath build-in
286N/A * functions are stored.
286N/A */
286N/A public Compiler(ErrorListener errorHandler, SourceLocator locator,
286N/A FunctionTable fTable)
286N/A {
286N/A m_errorHandler = errorHandler;
286N/A m_locator = locator;
286N/A m_functionTable = fTable;
286N/A }
286N/A
286N/A /**
286N/A * Construct a Compiler instance that has a null error listener and a
286N/A * null source locator.
286N/A */
286N/A public Compiler()
286N/A {
286N/A m_errorHandler = null;
286N/A m_locator = null;
286N/A }
286N/A
286N/A /**
286N/A * Execute the XPath object from a given opcode position.
286N/A * @param opPos The current position in the xpath.m_opMap array.
286N/A * @return The result of the XPath.
286N/A *
286N/A * @throws TransformerException if there is a syntax or other error.
286N/A * @xsl.usage advanced
286N/A */
286N/A public Expression compile(int opPos) throws TransformerException
286N/A {
286N/A
286N/A int op = getOp(opPos);
286N/A
286N/A Expression expr = null;
286N/A // System.out.println(getPatternString()+"op: "+op);
286N/A switch (op)
286N/A {
286N/A case OpCodes.OP_XPATH :
286N/A expr = compile(opPos + 2); break;
286N/A case OpCodes.OP_OR :
286N/A expr = or(opPos); break;
286N/A case OpCodes.OP_AND :
286N/A expr = and(opPos); break;
286N/A case OpCodes.OP_NOTEQUALS :
286N/A expr = notequals(opPos); break;
286N/A case OpCodes.OP_EQUALS :
286N/A expr = equals(opPos); break;
286N/A case OpCodes.OP_LTE :
286N/A expr = lte(opPos); break;
286N/A case OpCodes.OP_LT :
286N/A expr = lt(opPos); break;
286N/A case OpCodes.OP_GTE :
286N/A expr = gte(opPos); break;
286N/A case OpCodes.OP_GT :
286N/A expr = gt(opPos); break;
286N/A case OpCodes.OP_PLUS :
286N/A expr = plus(opPos); break;
286N/A case OpCodes.OP_MINUS :
286N/A expr = minus(opPos); break;
286N/A case OpCodes.OP_MULT :
286N/A expr = mult(opPos); break;
286N/A case OpCodes.OP_DIV :
286N/A expr = div(opPos); break;
286N/A case OpCodes.OP_MOD :
286N/A expr = mod(opPos); break;
286N/A// case OpCodes.OP_QUO :
286N/A// expr = quo(opPos); break;
286N/A case OpCodes.OP_NEG :
286N/A expr = neg(opPos); break;
286N/A case OpCodes.OP_STRING :
286N/A expr = string(opPos); break;
286N/A case OpCodes.OP_BOOL :
286N/A expr = bool(opPos); break;
286N/A case OpCodes.OP_NUMBER :
286N/A expr = number(opPos); break;
286N/A case OpCodes.OP_UNION :
286N/A expr = union(opPos); break;
286N/A case OpCodes.OP_LITERAL :
286N/A expr = literal(opPos); break;
286N/A case OpCodes.OP_VARIABLE :
286N/A expr = variable(opPos); break;
286N/A case OpCodes.OP_GROUP :
286N/A expr = group(opPos); break;
286N/A case OpCodes.OP_NUMBERLIT :
286N/A expr = numberlit(opPos); break;
286N/A case OpCodes.OP_ARGUMENT :
286N/A expr = arg(opPos); break;
286N/A case OpCodes.OP_EXTFUNCTION :
286N/A expr = compileExtension(opPos); break;
286N/A case OpCodes.OP_FUNCTION :
286N/A expr = compileFunction(opPos); break;
286N/A case OpCodes.OP_LOCATIONPATH :
286N/A expr = locationPath(opPos); break;
286N/A case OpCodes.OP_PREDICATE :
286N/A expr = null; break; // should never hit this here.
286N/A case OpCodes.OP_MATCHPATTERN :
286N/A expr = matchPattern(opPos + 2); break;
286N/A case OpCodes.OP_LOCATIONPATHPATTERN :
286N/A expr = locationPathPattern(opPos); break;
286N/A case OpCodes.OP_QUO:
286N/A error(XPATHErrorResources.ER_UNKNOWN_OPCODE,
286N/A new Object[]{ "quo" }); //"ERROR! Unknown op code: "+m_opMap[opPos]);
286N/A break;
286N/A default :
286N/A error(XPATHErrorResources.ER_UNKNOWN_OPCODE,
286N/A new Object[]{ Integer.toString(getOp(opPos)) }); //"ERROR! Unknown op code: "+m_opMap[opPos]);
286N/A }
286N/A// if(null != expr)
286N/A// expr.setSourceLocator(m_locator);
286N/A
286N/A return expr;
286N/A }
286N/A
286N/A /**
286N/A * Bottle-neck compilation of an operation with left and right operands.
286N/A *
286N/A * @param operation non-null reference to parent operation.
286N/A * @param opPos The op map position of the parent operation.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Operation} instance.
286N/A *
286N/A * @throws TransformerException if there is a syntax or other error.
286N/A */
286N/A private Expression compileOperation(Operation operation, int opPos)
286N/A throws TransformerException
286N/A {
286N/A
286N/A int leftPos = getFirstChildPos(opPos);
286N/A int rightPos = getNextOpPos(leftPos);
286N/A
286N/A operation.setLeftRight(compile(leftPos), compile(rightPos));
286N/A
286N/A return operation;
286N/A }
286N/A
286N/A /**
286N/A * Bottle-neck compilation of a unary operation.
286N/A *
286N/A * @param unary The parent unary operation.
286N/A * @param opPos The position in the op map of the parent operation.
286N/A *
286N/A * @return The unary argument.
286N/A *
286N/A * @throws TransformerException if syntax or other error occurs.
286N/A */
286N/A private Expression compileUnary(UnaryOperation unary, int opPos)
286N/A throws TransformerException
286N/A {
286N/A
286N/A int rightPos = getFirstChildPos(opPos);
286N/A
286N/A unary.setRight(compile(rightPos));
286N/A
286N/A return unary;
286N/A }
286N/A
286N/A /**
286N/A * Compile an 'or' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Or} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression or(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Or(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile an 'and' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.And} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression and(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new And(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '!=' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.NotEquals} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression notequals(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new NotEquals(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '=' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Equals} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression equals(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Equals(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '<=' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Lte} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression lte(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Lte(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '<' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Lt} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression lt(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Lt(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '>=' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Gte} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression gte(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Gte(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '>' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Gt} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression gt(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Gt(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '+' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Plus} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression plus(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Plus(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '-' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Minus} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression minus(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Minus(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a '*' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Mult} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression mult(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Mult(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a 'div' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Div} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression div(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Div(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a 'mod' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Mod} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression mod(int opPos) throws TransformerException
286N/A {
286N/A return compileOperation(new Mod(), opPos);
286N/A }
286N/A
286N/A /*
286N/A * Compile a 'quo' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Quo} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A// protected Expression quo(int opPos) throws TransformerException
286N/A// {
286N/A// return compileOperation(new Quo(), opPos);
286N/A// }
286N/A
286N/A /**
286N/A * Compile a unary '-' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Neg} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression neg(int opPos) throws TransformerException
286N/A {
286N/A return compileUnary(new Neg(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a 'string(...)' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.String} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression string(int opPos) throws TransformerException
286N/A {
286N/A return compileUnary(new com.sun.org.apache.xpath.internal.operations.String(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a 'boolean(...)' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Bool} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression bool(int opPos) throws TransformerException
286N/A {
286N/A return compileUnary(new com.sun.org.apache.xpath.internal.operations.Bool(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a 'number(...)' operation.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Number} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression number(int opPos) throws TransformerException
286N/A {
286N/A return compileUnary(new com.sun.org.apache.xpath.internal.operations.Number(), opPos);
286N/A }
286N/A
286N/A /**
286N/A * Compile a literal string value.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.objects.XString} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression literal(int opPos)
286N/A {
286N/A
286N/A opPos = getFirstChildPos(opPos);
286N/A
286N/A return (XString) getTokenQueue().elementAt(getOp(opPos));
286N/A }
286N/A
286N/A /**
286N/A * Compile a literal number value.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.objects.XNumber} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression numberlit(int opPos)
286N/A {
286N/A
286N/A opPos = getFirstChildPos(opPos);
286N/A
286N/A return (XNumber) getTokenQueue().elementAt(getOp(opPos));
286N/A }
286N/A
286N/A /**
286N/A * Compile a variable reference.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.operations.Variable} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression variable(int opPos) throws TransformerException
286N/A {
286N/A
286N/A Variable var = new Variable();
286N/A
286N/A opPos = getFirstChildPos(opPos);
286N/A
286N/A int nsPos = getOp(opPos);
286N/A java.lang.String namespace
286N/A = (OpCodes.EMPTY == nsPos) ? null
286N/A : (java.lang.String) getTokenQueue().elementAt(nsPos);
286N/A java.lang.String localname
286N/A = (java.lang.String) getTokenQueue().elementAt(getOp(opPos+1));
286N/A QName qname = new QName(namespace, localname);
286N/A
286N/A var.setQName(qname);
286N/A
286N/A return var;
286N/A }
286N/A
286N/A /**
286N/A * Compile an expression group.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to the contained expression.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression group(int opPos) throws TransformerException
286N/A {
286N/A
286N/A // no-op
286N/A return compile(opPos + 2);
286N/A }
286N/A
286N/A /**
286N/A * Compile a function argument.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to the argument expression.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression arg(int opPos) throws TransformerException
286N/A {
286N/A
286N/A // no-op
286N/A return compile(opPos + 2);
286N/A }
286N/A
286N/A /**
286N/A * Compile a location path union. The UnionPathIterator itself may create
286N/A * {@link com.sun.org.apache.xpath.internal.axes.LocPathIterator} children.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.axes.LocPathIterator} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression union(int opPos) throws TransformerException
286N/A {
286N/A locPathDepth++;
286N/A try
286N/A {
286N/A return UnionPathIterator.createUnionIterator(this, opPos);
286N/A }
286N/A finally
286N/A {
286N/A locPathDepth--;
286N/A }
286N/A }
286N/A
286N/A private int locPathDepth = -1;
286N/A
286N/A /**
286N/A * Get the level of the location path or union being constructed.
286N/A * @return 0 if it is a top-level path.
286N/A */
286N/A public int getLocationPathDepth()
286N/A {
286N/A return locPathDepth;
286N/A }
286N/A
286N/A /**
286N/A * Get the function table
286N/A */
286N/A FunctionTable getFunctionTable()
286N/A {
286N/A return m_functionTable;
286N/A }
286N/A
286N/A /**
286N/A * Compile a location path. The LocPathIterator itself may create
286N/A * {@link com.sun.org.apache.xpath.internal.axes.AxesWalker} children.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.axes.LocPathIterator} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A public Expression locationPath(int opPos) throws TransformerException
286N/A {
286N/A locPathDepth++;
286N/A try
286N/A {
286N/A DTMIterator iter = WalkerFactory.newDTMIterator(this, opPos, (locPathDepth == 0));
286N/A return (Expression)iter; // cast OK, I guess.
286N/A }
286N/A finally
286N/A {
286N/A locPathDepth--;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Compile a location step predicate expression.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return the contained predicate expression.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A public Expression predicate(int opPos) throws TransformerException
286N/A {
286N/A return compile(opPos + 2);
286N/A }
286N/A
286N/A /**
286N/A * Compile an entire match pattern expression.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.patterns.UnionPattern} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected Expression matchPattern(int opPos) throws TransformerException
286N/A {
286N/A locPathDepth++;
286N/A try
286N/A {
286N/A // First, count...
286N/A int nextOpPos = opPos;
286N/A int i;
286N/A
286N/A for (i = 0; getOp(nextOpPos) == OpCodes.OP_LOCATIONPATHPATTERN; i++)
286N/A {
286N/A nextOpPos = getNextOpPos(nextOpPos);
286N/A }
286N/A
286N/A if (i == 1)
286N/A return compile(opPos);
286N/A
286N/A UnionPattern up = new UnionPattern();
286N/A StepPattern[] patterns = new StepPattern[i];
286N/A
286N/A for (i = 0; getOp(opPos) == OpCodes.OP_LOCATIONPATHPATTERN; i++)
286N/A {
286N/A nextOpPos = getNextOpPos(opPos);
286N/A patterns[i] = (StepPattern) compile(opPos);
286N/A opPos = nextOpPos;
286N/A }
286N/A
286N/A up.setPatterns(patterns);
286N/A
286N/A return up;
286N/A }
286N/A finally
286N/A {
286N/A locPathDepth--;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Compile a location match pattern unit expression.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.patterns.StepPattern} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A public Expression locationPathPattern(int opPos)
286N/A throws TransformerException
286N/A {
286N/A
286N/A opPos = getFirstChildPos(opPos);
286N/A
286N/A return stepPattern(opPos, 0, null);
286N/A }
286N/A
286N/A /**
286N/A * Get a {@link org.w3c.dom.traversal.NodeFilter} bit set that tells what
286N/A * to show for a given node test.
286N/A *
286N/A * @param opPos the op map position for the location step.
286N/A *
286N/A * @return {@link org.w3c.dom.traversal.NodeFilter} bit set that tells what
286N/A * to show for a given node test.
286N/A */
286N/A public int getWhatToShow(int opPos)
286N/A {
286N/A
286N/A int axesType = getOp(opPos);
286N/A int testType = getOp(opPos + 3);
286N/A
286N/A // System.out.println("testType: "+testType);
286N/A switch (testType)
286N/A {
286N/A case OpCodes.NODETYPE_COMMENT :
286N/A return DTMFilter.SHOW_COMMENT;
286N/A case OpCodes.NODETYPE_TEXT :
286N/A// return DTMFilter.SHOW_TEXT | DTMFilter.SHOW_COMMENT;
286N/A return DTMFilter.SHOW_TEXT | DTMFilter.SHOW_CDATA_SECTION ;
286N/A case OpCodes.NODETYPE_PI :
286N/A return DTMFilter.SHOW_PROCESSING_INSTRUCTION;
286N/A case OpCodes.NODETYPE_NODE :
286N/A// return DTMFilter.SHOW_ALL;
286N/A switch (axesType)
286N/A {
286N/A case OpCodes.FROM_NAMESPACE:
286N/A return DTMFilter.SHOW_NAMESPACE;
286N/A case OpCodes.FROM_ATTRIBUTES :
286N/A case OpCodes.MATCH_ATTRIBUTE :
286N/A return DTMFilter.SHOW_ATTRIBUTE;
286N/A case OpCodes.FROM_SELF:
286N/A case OpCodes.FROM_ANCESTORS_OR_SELF:
286N/A case OpCodes.FROM_DESCENDANTS_OR_SELF:
286N/A return DTMFilter.SHOW_ALL;
286N/A default:
286N/A if (getOp(0) == OpCodes.OP_MATCHPATTERN)
286N/A return ~DTMFilter.SHOW_ATTRIBUTE
286N/A & ~DTMFilter.SHOW_DOCUMENT
286N/A & ~DTMFilter.SHOW_DOCUMENT_FRAGMENT;
286N/A else
286N/A return ~DTMFilter.SHOW_ATTRIBUTE;
286N/A }
286N/A case OpCodes.NODETYPE_ROOT :
286N/A return DTMFilter.SHOW_DOCUMENT | DTMFilter.SHOW_DOCUMENT_FRAGMENT;
286N/A case OpCodes.NODETYPE_FUNCTEST :
286N/A return NodeTest.SHOW_BYFUNCTION;
286N/A case OpCodes.NODENAME :
286N/A switch (axesType)
286N/A {
286N/A case OpCodes.FROM_NAMESPACE :
286N/A return DTMFilter.SHOW_NAMESPACE;
286N/A case OpCodes.FROM_ATTRIBUTES :
286N/A case OpCodes.MATCH_ATTRIBUTE :
286N/A return DTMFilter.SHOW_ATTRIBUTE;
286N/A
286N/A // break;
286N/A case OpCodes.MATCH_ANY_ANCESTOR :
286N/A case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
286N/A return DTMFilter.SHOW_ELEMENT;
286N/A
286N/A // break;
286N/A default :
286N/A return DTMFilter.SHOW_ELEMENT;
286N/A }
286N/A default :
286N/A // System.err.println("We should never reach here.");
286N/A return DTMFilter.SHOW_ALL;
286N/A }
286N/A }
286N/A
286N/Aprivate static final boolean DEBUG = false;
286N/A
286N/A /**
286N/A * Compile a step pattern unit expression, used for both location paths
286N/A * and match patterns.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A * @param stepCount The number of steps to expect.
286N/A * @param ancestorPattern The owning StepPattern, which may be null.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.patterns.StepPattern} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A protected StepPattern stepPattern(
286N/A int opPos, int stepCount, StepPattern ancestorPattern)
286N/A throws TransformerException
286N/A {
286N/A
286N/A int startOpPos = opPos;
286N/A int stepType = getOp(opPos);
286N/A
286N/A if (OpCodes.ENDOP == stepType)
286N/A {
286N/A return null;
286N/A }
286N/A
286N/A boolean addMagicSelf = true;
286N/A
286N/A int endStep = getNextOpPos(opPos);
286N/A
286N/A // int nextStepType = getOpMap()[endStep];
286N/A StepPattern pattern;
286N/A
286N/A // boolean isSimple = ((OpCodes.ENDOP == nextStepType) && (stepCount == 0));
286N/A int argLen;
286N/A
286N/A switch (stepType)
286N/A {
286N/A case OpCodes.OP_FUNCTION :
286N/A if(DEBUG)
286N/A System.out.println("MATCH_FUNCTION: "+m_currentPattern);
286N/A addMagicSelf = false;
286N/A argLen = getOp(opPos + OpMap.MAPINDEX_LENGTH);
286N/A pattern = new FunctionPattern(compileFunction(opPos), Axis.PARENT, Axis.CHILD);
286N/A break;
286N/A case OpCodes.FROM_ROOT :
286N/A if(DEBUG)
286N/A System.out.println("FROM_ROOT, "+m_currentPattern);
286N/A addMagicSelf = false;
286N/A argLen = getArgLengthOfStep(opPos);
286N/A opPos = getFirstChildPosOfStep(opPos);
286N/A pattern = new StepPattern(DTMFilter.SHOW_DOCUMENT |
286N/A DTMFilter.SHOW_DOCUMENT_FRAGMENT,
286N/A Axis.PARENT, Axis.CHILD);
286N/A break;
286N/A case OpCodes.MATCH_ATTRIBUTE :
286N/A if(DEBUG)
286N/A System.out.println("MATCH_ATTRIBUTE: "+getStepLocalName(startOpPos)+", "+m_currentPattern);
286N/A argLen = getArgLengthOfStep(opPos);
286N/A opPos = getFirstChildPosOfStep(opPos);
286N/A pattern = new StepPattern(DTMFilter.SHOW_ATTRIBUTE,
286N/A getStepNS(startOpPos),
286N/A getStepLocalName(startOpPos),
286N/A Axis.PARENT, Axis.ATTRIBUTE);
286N/A break;
286N/A case OpCodes.MATCH_ANY_ANCESTOR :
286N/A if(DEBUG)
286N/A System.out.println("MATCH_ANY_ANCESTOR: "+getStepLocalName(startOpPos)+", "+m_currentPattern);
286N/A argLen = getArgLengthOfStep(opPos);
286N/A opPos = getFirstChildPosOfStep(opPos);
286N/A int what = getWhatToShow(startOpPos);
286N/A // bit-o-hackery, but this code is due for the morgue anyway...
286N/A if(0x00000500 == what)
286N/A addMagicSelf = false;
286N/A pattern = new StepPattern(getWhatToShow(startOpPos),
286N/A getStepNS(startOpPos),
286N/A getStepLocalName(startOpPos),
286N/A Axis.ANCESTOR, Axis.CHILD);
286N/A break;
286N/A case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
286N/A if(DEBUG)
286N/A System.out.println("MATCH_IMMEDIATE_ANCESTOR: "+getStepLocalName(startOpPos)+", "+m_currentPattern);
286N/A argLen = getArgLengthOfStep(opPos);
286N/A opPos = getFirstChildPosOfStep(opPos);
286N/A pattern = new StepPattern(getWhatToShow(startOpPos),
286N/A getStepNS(startOpPos),
286N/A getStepLocalName(startOpPos),
286N/A Axis.PARENT, Axis.CHILD);
286N/A break;
286N/A default :
286N/A error(XPATHErrorResources.ER_UNKNOWN_MATCH_OPERATION, null); //"unknown match operation!");
286N/A
286N/A return null;
286N/A }
286N/A
286N/A pattern.setPredicates(getCompiledPredicates(opPos + argLen));
286N/A if(null == ancestorPattern)
286N/A {
286N/A // This is the magic and invisible "." at the head of every
286N/A // match pattern, and corresponds to the current node in the context
286N/A // list, from where predicates are counted.
286N/A // So, in order to calculate "foo[3]", it has to count from the
286N/A // current node in the context list, so, from that current node,
286N/A // the full pattern is really "self::node()/child::foo[3]". If you
286N/A // translate this to a select pattern from the node being tested,
286N/A // which is really how we're treating match patterns, it works out to
286N/A // self::foo/parent::node[child::foo[3]]", or close enough.
286N/A /* if(addMagicSelf && pattern.getPredicateCount() > 0)
286N/A {
286N/A StepPattern selfPattern = new StepPattern(DTMFilter.SHOW_ALL,
286N/A Axis.PARENT, Axis.CHILD);
286N/A // We need to keep the new nodetest from affecting the score...
286N/A XNumber score = pattern.getStaticScore();
286N/A pattern.setRelativePathPattern(selfPattern);
286N/A pattern.setStaticScore(score);
286N/A selfPattern.setStaticScore(score);
286N/A }*/
286N/A }
286N/A else
286N/A {
286N/A // System.out.println("Setting "+ancestorPattern+" as relative to "+pattern);
286N/A pattern.setRelativePathPattern(ancestorPattern);
286N/A }
286N/A
286N/A StepPattern relativePathPattern = stepPattern(endStep, stepCount + 1,
286N/A pattern);
286N/A
286N/A return (null != relativePathPattern) ? relativePathPattern : pattern;
286N/A }
286N/A
286N/A /**
286N/A * Compile a zero or more predicates for a given match pattern.
286N/A *
286N/A * @param opPos The position of the first predicate the m_opMap array.
286N/A *
286N/A * @return reference to array of {@link com.sun.org.apache.xpath.internal.Expression} instances.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A public Expression[] getCompiledPredicates(int opPos)
286N/A throws TransformerException
286N/A {
286N/A
286N/A int count = countPredicates(opPos);
286N/A
286N/A if (count > 0)
286N/A {
286N/A Expression[] predicates = new Expression[count];
286N/A
286N/A compilePredicates(opPos, predicates);
286N/A
286N/A return predicates;
286N/A }
286N/A
286N/A return null;
286N/A }
286N/A
286N/A /**
286N/A * Count the number of predicates in the step.
286N/A *
286N/A * @param opPos The position of the first predicate the m_opMap array.
286N/A *
286N/A * @return The number of predicates for this step.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A public int countPredicates(int opPos) throws TransformerException
286N/A {
286N/A
286N/A int count = 0;
286N/A
286N/A while (OpCodes.OP_PREDICATE == getOp(opPos))
286N/A {
286N/A count++;
286N/A
286N/A opPos = getNextOpPos(opPos);
286N/A }
286N/A
286N/A return count;
286N/A }
286N/A
286N/A /**
286N/A * Compiles predicates in the step.
286N/A *
286N/A * @param opPos The position of the first predicate the m_opMap array.
286N/A * @param predicates An empty pre-determined array of
286N/A * {@link com.sun.org.apache.xpath.internal.Expression}s, that will be filled in.
286N/A *
286N/A * @throws TransformerException
286N/A */
286N/A private void compilePredicates(int opPos, Expression[] predicates)
286N/A throws TransformerException
286N/A {
286N/A
286N/A for (int i = 0; OpCodes.OP_PREDICATE == getOp(opPos); i++)
286N/A {
286N/A predicates[i] = predicate(opPos);
286N/A opPos = getNextOpPos(opPos);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Compile a built-in XPath function.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.functions.Function} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A Expression compileFunction(int opPos) throws TransformerException
286N/A {
286N/A
286N/A int endFunc = opPos + getOp(opPos + 1) - 1;
286N/A
286N/A opPos = getFirstChildPos(opPos);
286N/A
286N/A int funcID = getOp(opPos);
286N/A
286N/A opPos++;
286N/A
286N/A if (-1 != funcID)
286N/A {
286N/A Function func = m_functionTable.getFunction(funcID);
286N/A
286N/A /**
286N/A * It is a trick for function-available. Since the function table is an
286N/A * instance field, insert this table at compilation time for later usage
286N/A */
286N/A
286N/A if (func instanceof FuncExtFunctionAvailable)
286N/A ((FuncExtFunctionAvailable) func).setFunctionTable(m_functionTable);
286N/A
286N/A func.postCompileStep(this);
286N/A
286N/A try
286N/A {
286N/A int i = 0;
286N/A
286N/A for (int p = opPos; p < endFunc; p = getNextOpPos(p), i++)
286N/A {
286N/A
286N/A // System.out.println("argPos: "+ p);
286N/A // System.out.println("argCode: "+ m_opMap[p]);
286N/A func.setArg(compile(p), i);
286N/A }
286N/A
286N/A func.checkNumberArgs(i);
286N/A }
286N/A catch (WrongNumberArgsException wnae)
286N/A {
286N/A java.lang.String name = m_functionTable.getFunctionName(funcID);
286N/A
286N/A m_errorHandler.fatalError( new TransformerException(
286N/A XSLMessages.createXPATHMessage(XPATHErrorResources.ER_ONLY_ALLOWS,
286N/A new Object[]{name, wnae.getMessage()}), m_locator));
286N/A //"name + " only allows " + wnae.getMessage() + " arguments", m_locator));
286N/A }
286N/A
286N/A return func;
286N/A }
286N/A else
286N/A {
286N/A error(XPATHErrorResources.ER_FUNCTION_TOKEN_NOT_FOUND, null); //"function token not found.");
286N/A
286N/A return null;
286N/A }
286N/A }
286N/A
286N/A // The current id for extension functions.
286N/A private static long s_nextMethodId = 0;
286N/A
286N/A /**
286N/A * Get the next available method id
286N/A */
286N/A synchronized private long getNextMethodId()
286N/A {
286N/A if (s_nextMethodId == Long.MAX_VALUE)
286N/A s_nextMethodId = 0;
286N/A
286N/A return s_nextMethodId++;
286N/A }
286N/A
286N/A /**
286N/A * Compile an extension function.
286N/A *
286N/A * @param opPos The current position in the m_opMap array.
286N/A *
286N/A * @return reference to {@link com.sun.org.apache.xpath.internal.functions.FuncExtFunction} instance.
286N/A *
286N/A * @throws TransformerException if a error occurs creating the Expression.
286N/A */
286N/A private Expression compileExtension(int opPos)
286N/A throws TransformerException
286N/A {
286N/A
286N/A int endExtFunc = opPos + getOp(opPos + 1) - 1;
286N/A
286N/A opPos = getFirstChildPos(opPos);
286N/A
286N/A java.lang.String ns = (java.lang.String) getTokenQueue().elementAt(getOp(opPos));
286N/A
286N/A opPos++;
286N/A
286N/A java.lang.String funcName =
286N/A (java.lang.String) getTokenQueue().elementAt(getOp(opPos));
286N/A
286N/A opPos++;
286N/A
286N/A // We create a method key to uniquely identify this function so that we
286N/A // can cache the object needed to invoke it. This way, we only pay the
286N/A // reflection overhead on the first call.
286N/A
286N/A Function extension = new FuncExtFunction(ns, funcName, String.valueOf(getNextMethodId()));
286N/A
286N/A try
286N/A {
286N/A int i = 0;
286N/A
286N/A while (opPos < endExtFunc)
286N/A {
286N/A int nextOpPos = getNextOpPos(opPos);
286N/A
286N/A extension.setArg(this.compile(opPos), i);
286N/A
286N/A opPos = nextOpPos;
286N/A
286N/A i++;
286N/A }
286N/A }
286N/A catch (WrongNumberArgsException wnae)
286N/A {
286N/A ; // should never happen
286N/A }
286N/A
286N/A return extension;
286N/A }
286N/A
286N/A /**
286N/A * Warn the user of an problem.
286N/A *
286N/A * @param msg An error msgkey that corresponds to one of the constants found
286N/A * in {@link com.sun.org.apache.xpath.internal.res.XPATHErrorResources}, which is
286N/A * a key for a format string.
286N/A * @param args An array of arguments represented in the format string, which
286N/A * may be null.
286N/A *
286N/A * @throws TransformerException if the current ErrorListoner determines to
286N/A * throw an exception.
286N/A */
286N/A public void warn(String msg, Object[] args) throws TransformerException
286N/A {
286N/A
286N/A java.lang.String fmsg = XSLMessages.createXPATHWarning(msg, args);
286N/A
286N/A if (null != m_errorHandler)
286N/A {
286N/A m_errorHandler.warning(new TransformerException(fmsg, m_locator));
286N/A }
286N/A else
286N/A {
286N/A System.out.println(fmsg
286N/A +"; file "+m_locator.getSystemId()
286N/A +"; line "+m_locator.getLineNumber()
286N/A +"; column "+m_locator.getColumnNumber());
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Tell the user of an assertion error, and probably throw an
286N/A * exception.
286N/A *
286N/A * @param b If false, a runtime exception will be thrown.
286N/A * @param msg The assertion message, which should be informative.
286N/A *
286N/A * @throws RuntimeException if the b argument is false.
286N/A */
286N/A public void assertion(boolean b, java.lang.String msg)
286N/A {
286N/A
286N/A if (!b)
286N/A {
286N/A java.lang.String fMsg = XSLMessages.createXPATHMessage(
286N/A XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
286N/A new Object[]{ msg });
286N/A
286N/A throw new RuntimeException(fMsg);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Tell the user of an error, and probably throw an
286N/A * exception.
286N/A *
286N/A * @param msg An error msgkey that corresponds to one of the constants found
286N/A * in {@link com.sun.org.apache.xpath.internal.res.XPATHErrorResources}, which is
286N/A * a key for a format string.
286N/A * @param args An array of arguments represented in the format string, which
286N/A * may be null.
286N/A *
286N/A * @throws TransformerException if the current ErrorListoner determines to
286N/A * throw an exception.
286N/A */
286N/A public void error(String msg, Object[] args) throws TransformerException
286N/A {
286N/A
286N/A java.lang.String fmsg = XSLMessages.createXPATHMessage(msg, args);
286N/A
286N/A
286N/A if (null != m_errorHandler)
286N/A {
286N/A m_errorHandler.fatalError(new TransformerException(fmsg, m_locator));
286N/A }
286N/A else
286N/A {
286N/A
286N/A // System.out.println(te.getMessage()
286N/A // +"; file "+te.getSystemId()
286N/A // +"; line "+te.getLineNumber()
286N/A // +"; column "+te.getColumnNumber());
286N/A throw new TransformerException(fmsg, (SAXSourceLocator)m_locator);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * The current prefixResolver for the execution context.
286N/A */
286N/A private PrefixResolver m_currentPrefixResolver = null;
286N/A
286N/A /**
286N/A * Get the current namespace context for the xpath.
286N/A *
286N/A * @return The current prefix resolver, *may* be null, though hopefully not.
286N/A */
286N/A public PrefixResolver getNamespaceContext()
286N/A {
286N/A return m_currentPrefixResolver;
286N/A }
286N/A
286N/A /**
286N/A * Set the current namespace context for the xpath.
286N/A *
286N/A * @param pr The resolver for prefixes in the XPath expression.
286N/A */
286N/A public void setNamespaceContext(PrefixResolver pr)
286N/A {
286N/A m_currentPrefixResolver = pr;
286N/A }
286N/A
286N/A /** The error listener where errors will be sent. If this is null, errors
286N/A * and warnings will be sent to System.err. May be null. */
286N/A ErrorListener m_errorHandler;
286N/A
286N/A /** The source locator for the expression being compiled. May be null. */
286N/A SourceLocator m_locator;
286N/A
286N/A /**
286N/A * The FunctionTable for all xpath build-in functions
286N/A */
286N/A private FunctionTable m_functionTable;
286N/A}