19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License.
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License.
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: XPathParser.java 468655 2006-10-28 07:12:06Z minchau $
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xpath.compiler;
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport javax.xml.transform.ErrorListener;
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport javax.xml.transform.TransformerException;
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xalan.res.XSLMessages;
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.PrefixResolver;
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.XPathProcessorException;
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.domapi.XPathStylesheetDOM3Exception;
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.objects.XNumber;
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.objects.XString;
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.res.XPATHErrorResources;
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/**
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Tokenizes and parses XPath expressions. This should really be named
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * XPathParserImpl, and may be renamed in the future.
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @xsl.usage general
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class XPathParser
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// %REVIEW% Is there a better way of doing this?
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// Upside is minimum object churn. Downside is that we don't have a useful
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// backtrace in the exception itself -- but we don't expect to need one.
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	static public final String CONTINUE_AFTER_FATAL_ERROR="CONTINUE_AFTER_FATAL_ERROR";
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The XPath to be processed.
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private OpMap m_ops;
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The next token in the pattern.
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  transient String m_token;
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The first char in m_token, the theory being that this
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * is an optimization because we won't have to do charAt(0) as
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * often.
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  transient char m_tokenChar = 0;
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The position in the token queue is tracked by m_queueMark.
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int m_queueMark = 0;
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Results from checking FilterExpr syntax
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected final static int FILTER_MATCH_FAILED     = 0;
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected final static int FILTER_MATCH_PRIMARY    = 1;
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected final static int FILTER_MATCH_PREDICATES = 2;
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The parser constructor.
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XPathParser(ErrorListener errorListener, javax.xml.transform.SourceLocator sourceLocator)
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_errorListener = errorListener;
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_sourceLocator = sourceLocator;
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The prefix resolver to map prefixes to namespaces in the OpMap.
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  PrefixResolver m_namespaceContext;
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given an string, init an XPath object for selections,
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * in order that a parse doesn't
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * have to be done each time the expression is evaluated.
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param compiler The compiler object.
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param expression A string conforming to the XPath grammar.
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param namespaceContext An object that is able to resolve prefixes in
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the XPath to namespaces.
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void initXPath(
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Compiler compiler, String expression, PrefixResolver namespaceContext)
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws javax.xml.transform.TransformerException
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops = compiler;
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_namespaceContext = namespaceContext;
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_functionTable = compiler.getFunctionTable();
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Lexer lexer = new Lexer(compiler, namespaceContext, this);
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    lexer.tokenize(expression);
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(0,OpCodes.OP_XPATH);
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH,2);
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// Patch for Christine's gripe. She wants her errorHandler to return from
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// a fatal error and continue trying to parse, rather than throwing an exception.
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// Without the patch, that put us into an endless loop.
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	//
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// %REVIEW% Is there a better way of doing this?
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// %REVIEW% Are there any other cases which need the safety net?
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	// 	(and if so do we care right now, or should we rewrite the XPath
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	//	grammar engine and can fix it at that time?)
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	try {
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Expr();
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null != m_token)
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        String extraTokens = "";
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        while (null != m_token)
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          extraTokens += "'" + m_token + "'";
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          nextToken();
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (null != m_token)
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            extraTokens += ", ";
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_EXTRA_ILLEGAL_TOKENS,
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              new Object[]{ extraTokens });  //"Extra illegal tokens: "+extraTokens);
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch (org.apache.xpath.XPathProcessorException e)
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  if(CONTINUE_AFTER_FATAL_ERROR.equals(e.getMessage()))
1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  {
1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		// What I _want_ to do is null out this XPath.
1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		// I doubt this has the desired effect, but I'm not sure what else to do.
1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		// %REVIEW%!!!
1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		initXPath(compiler, "/..",  namespaceContext);
1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  }
1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  else
1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		throw e;
1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    compiler.shrink();
1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given an string, init an XPath object for pattern matches,
1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * in order that a parse doesn't
1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * have to be done each time the expression is evaluated.
1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param compiler The XPath object to be initialized.
1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param expression A String representing the XPath.
1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param namespaceContext An object that is able to resolve prefixes in
1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the XPath to namespaces.
1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void initMatchPattern(
1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Compiler compiler, String expression, PrefixResolver namespaceContext)
1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws javax.xml.transform.TransformerException
1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops = compiler;
1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_namespaceContext = namespaceContext;
1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_functionTable = compiler.getFunctionTable();
1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Lexer lexer = new Lexer(compiler, namespaceContext, this);
1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    lexer.tokenize(expression);
1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(0, OpCodes.OP_MATCHPATTERN);
1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, 2);
1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    nextToken();
1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Pattern();
1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != m_token)
1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String extraTokens = "";
1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while (null != m_token)
2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        extraTokens += "'" + m_token + "'";
2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (null != m_token)
2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          extraTokens += ", ";
2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      error(XPATHErrorResources.ER_EXTRA_ILLEGAL_TOKENS,
2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            new Object[]{ extraTokens });  //"Extra illegal tokens: "+extraTokens);
2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Terminate for safety.
2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH)+1);
2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.shrink();
2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** The error listener where syntax errors are to be sent.
2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private ErrorListener m_errorListener;
2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** The source location of the XPath. */
2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  javax.xml.transform.SourceLocator m_sourceLocator;
2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** The table contains build-in functions and customized functions */
2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private FunctionTable m_functionTable;
2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Allow an application to register an error event handler, where syntax
2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * errors will be sent.  If the error listener is not set, syntax errors
2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * will be sent to System.err.
2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param handler Reference to error listener where syntax errors will be
2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *                sent.
2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void setErrorHandler(ErrorListener handler)
2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_errorListener = handler;
2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Return the current error listener.
2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The error listener, which should not normally be null, but may be.
2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public ErrorListener getErrorListener()
2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return m_errorListener;
2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Check whether m_token matches the target string.
2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param s A string reference or null.
2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return If m_token is null, returns false (or true if s is also null), or
2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * return true if the current token matches the string, else false.
2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  final boolean tokenIs(String s)
2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return (m_token != null) ? (m_token.equals(s)) : (s == null);
2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Check whether m_tokenChar==c.
2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param c A character to be tested.
2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return If m_token is null, returns false, or return true if c matches
2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *         the current token.
2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  final boolean tokenIs(char c)
2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return (m_token != null) ? (m_tokenChar == c) : false;
2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Look ahead of the current token in order to
2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * make a branching decision.
2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param c the character to be tested for.
2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param n number of tokens to look ahead.  Must be
2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * greater than 1.
2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return true if the next token matches the character argument.
2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  final boolean lookahead(char c, int n)
2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int pos = (m_queueMark + n);
2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean b;
2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if ((pos <= m_ops.getTokenQueueSize()) && (pos > 0)
2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            && (m_ops.getTokenQueueSize() != 0))
2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String tok = ((String) m_ops.m_tokenQueue.elementAt(pos - 1));
3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      b = (tok.length() == 1) ? (tok.charAt(0) == c) : false;
3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      b = false;
3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return b;
3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Look behind the first character of the current token in order to
3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * make a branching decision.
3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param c the character to compare it to.
3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param n number of tokens to look behind.  Must be
3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * greater than 1.  Note that the look behind terminates
3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * at either the beginning of the string or on a '|'
3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * character.  Because of this, this method should only
3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * be used for pattern matching.
3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return true if the token behind the current token matches the character
3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *         argument.
3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private final boolean lookbehind(char c, int n)
3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean isToken;
3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int lookBehindPos = m_queueMark - (n + 1);
3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (lookBehindPos >= 0)
3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String lookbehind = (String) m_ops.m_tokenQueue.elementAt(lookBehindPos);
3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (lookbehind.length() == 1)
3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        char c0 = (lookbehind == null) ? '|' : lookbehind.charAt(0);
3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        isToken = (c0 == '|') ? false : (c0 == c);
3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        isToken = false;
3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      isToken = false;
3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return isToken;
3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * look behind the current token in order to
3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * see if there is a useable token.
3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param n number of tokens to look behind.  Must be
3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * greater than 1.  Note that the look behind terminates
3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * at either the beginning of the string or on a '|'
3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * character.  Because of this, this method should only
3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * be used for pattern matching.
3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return true if look behind has a token, false otherwise.
3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private final boolean lookbehindHasToken(int n)
3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean hasToken;
3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if ((m_queueMark - n) > 0)
3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String lookbehind = (String) m_ops.m_tokenQueue.elementAt(m_queueMark - (n - 1));
3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      char c0 = (lookbehind == null) ? '|' : lookbehind.charAt(0);
3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      hasToken = (c0 == '|') ? false : true;
3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      hasToken = false;
3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return hasToken;
3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Look ahead of the current token in order to
3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * make a branching decision.
3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param s the string to compare it to.
3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param n number of tokens to lookahead.  Must be
3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * greater than 1.
3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return true if the token behind the current token matches the string
3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *         argument.
3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private final boolean lookahead(String s, int n)
3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean isToken;
4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if ((m_queueMark + n) <= m_ops.getTokenQueueSize())
4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String lookahead = (String) m_ops.m_tokenQueue.elementAt(m_queueMark + (n - 1));
4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      isToken = (lookahead != null) ? lookahead.equals(s) : (s == null);
4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      isToken = (null == s);
4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return isToken;
4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Retrieve the next token from the command and
4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * store it in m_token string.
4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private final void nextToken()
4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_queueMark < m_ops.getTokenQueueSize())
4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_token = (String) m_ops.m_tokenQueue.elementAt(m_queueMark++);
4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_tokenChar = m_token.charAt(0);
4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_token = null;
4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_tokenChar = 0;
4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Retrieve a token relative to the current token.
4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param i Position relative to current token.
4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The string at the given index, or null if the index is out
4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *         of range.
4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private final String getTokenRelative(int i)
4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String tok;
4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int relative = m_queueMark + i;
4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if ((relative > 0) && (relative < m_ops.getTokenQueueSize()))
4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      tok = (String) m_ops.m_tokenQueue.elementAt(relative);
4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      tok = null;
4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return tok;
4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Retrieve the previous token from the command and
4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * store it in m_token string.
4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private final void prevToken()
4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_queueMark > 0)
4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_queueMark--;
4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_token = (String) m_ops.m_tokenQueue.elementAt(m_queueMark);
4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_tokenChar = m_token.charAt(0);
4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_token = null;
4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_tokenChar = 0;
4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Consume an expected token, throwing an exception if it
4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * isn't there.
4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param expected The string to be expected.
4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private final void consumeExpected(String expected)
4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws javax.xml.transform.TransformerException
4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (tokenIs(expected))
4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      error(XPATHErrorResources.ER_EXPECTED_BUT_FOUND, new Object[]{ expected,
5019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                                     m_token });  //"Expected "+expected+", but found: "+m_token);
5029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // Patch for Christina's gripe. She wants her errorHandler to return from
5049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // this error and continue trying to parse, rather than throwing an exception.
5059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // Without the patch, that put us into an endless loop.
5069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		throw new XPathProcessorException(CONTINUE_AFTER_FATAL_ERROR);
5079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	}
5089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
5119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Consume an expected token, throwing an exception if it
5129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * isn't there.
5139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
5149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param expected the character to be expected.
5159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
5169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
5179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
5189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private final void consumeExpected(char expected)
5199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws javax.xml.transform.TransformerException
5209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
5219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (tokenIs(expected))
5239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
5259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
5279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      error(XPATHErrorResources.ER_EXPECTED_BUT_FOUND,
5299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            new Object[]{ String.valueOf(expected),
5309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                          m_token });  //"Expected "+expected+", but found: "+m_token);
5319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // Patch for Christina's gripe. She wants her errorHandler to return from
5339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // this error and continue trying to parse, rather than throwing an exception.
5349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // Without the patch, that put us into an endless loop.
5359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson		throw new XPathProcessorException(CONTINUE_AFTER_FATAL_ERROR);
5369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
5409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Warn the user of a problem.
5419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
5429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param msg An error msgkey that corresponds to one of the constants found
5439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *            in {@link org.apache.xpath.res.XPATHErrorResources}, which is
5449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *            a key for a format string.
5459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param args An array of arguments represented in the format string, which
5469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *             may be null.
5479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
5489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException if the current ErrorListoner determines to
5499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *                              throw an exception.
5509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
5519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void warn(String msg, Object[] args) throws TransformerException
5529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
5539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String fmsg = XSLMessages.createXPATHWarning(msg, args);
5559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    ErrorListener ehandler = this.getErrorListener();
5569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != ehandler)
5589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // TO DO: Need to get stylesheet Locator from here.
5609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      ehandler.warning(new TransformerException(fmsg, m_sourceLocator));
5619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
5639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Should never happen.
5659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      System.err.println(fmsg);
5669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
5709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Notify the user of an assertion error, and probably throw an
5719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * exception.
5729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
5739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param b  If false, a runtime exception will be thrown.
5749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param msg The assertion message, which should be informative.
5759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
5769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws RuntimeException if the b argument is false.
5779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
5789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private void assertion(boolean b, String msg)
5799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
5809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (!b)
5829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String fMsg = XSLMessages.createXPATHMessage(
5849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
5859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        new Object[]{ msg });
5869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      throw new RuntimeException(fMsg);
5889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
5929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Notify the user of an error, and probably throw an
5939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * exception.
5949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
5959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param msg An error msgkey that corresponds to one of the constants found
5969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *            in {@link org.apache.xpath.res.XPATHErrorResources}, which is
5979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *            a key for a format string.
5989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param args An array of arguments represented in the format string, which
5999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *             may be null.
6009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException if the current ErrorListoner determines to
6029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *                              throw an exception.
6039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
6049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void error(String msg, Object[] args) throws TransformerException
6059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
6069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String fmsg = XSLMessages.createXPATHMessage(msg, args);
6089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    ErrorListener ehandler = this.getErrorListener();
6099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    TransformerException te = new TransformerException(fmsg, m_sourceLocator);
6119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != ehandler)
6129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
6139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // TO DO: Need to get stylesheet Locator from here.
6149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      ehandler.fatalError(te);
6159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
6169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
6179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
6189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // System.err.println(fmsg);
6199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      throw te;
6209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
6219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
6229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
6249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * This method is added to support DOM 3 XPath API.
6259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
6269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * This method is exactly like error(String, Object[]); except that
6279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the underlying TransformerException is
6289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * XpathStylesheetDOM3Exception (which extends TransformerException).
6299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
6309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * So older XPath code in Xalan is not affected by this. To older XPath code
6319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the behavior of whether error() or errorForDOM3() is called because it is
6329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * always catching TransformerException objects and is oblivious to
6339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the new subclass of XPathStylesheetDOM3Exception. Older XPath code
6349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * runs as before.
6359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>
6369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * However, newer DOM3 XPath code upon catching a TransformerException can
6379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * can check if the exception is an instance of XPathStylesheetDOM3Exception
6389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * and take appropriate action.
6399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param msg An error msgkey that corresponds to one of the constants found
6419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *            in {@link org.apache.xpath.res.XPATHErrorResources}, which is
6429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *            a key for a format string.
6439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param args An array of arguments represented in the format string, which
6449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *             may be null.
6459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException if the current ErrorListoner determines to
6479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *                              throw an exception.
6489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
6499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void errorForDOM3(String msg, Object[] args) throws TransformerException
6509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
6519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	String fmsg = XSLMessages.createXPATHMessage(msg, args);
6539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	ErrorListener ehandler = this.getErrorListener();
6549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	TransformerException te = new XPathStylesheetDOM3Exception(fmsg, m_sourceLocator);
6569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	if (null != ehandler)
6579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	{
6589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // TO DO: Need to get stylesheet Locator from here.
6599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  ehandler.fatalError(te);
6609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	}
6619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	else
6629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	{
6639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  // System.err.println(fmsg);
6649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	  throw te;
6659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	}
6669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
6679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
6689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Dump the remaining token queue.
6699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Thanks to Craig for this.
6709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
6719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return A dump of the remaining token queue, which may be appended to
6729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *         an error message.
6739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
6749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected String dumpRemainingTokenQueue()
6759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
6769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int q = m_queueMark;
6789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    String returnMsg;
6799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (q < m_ops.getTokenQueueSize())
6819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
6829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String msg = "\n Remaining tokens: (";
6839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while (q < m_ops.getTokenQueueSize())
6859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
6869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        String t = (String) m_ops.m_tokenQueue.elementAt(q++);
6879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        msg += (" '" + t + "'");
6899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
6909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      returnMsg = msg + ")";
6929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
6939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
6949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
6959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      returnMsg = "";
6969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
6979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return returnMsg;
6999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
7009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
7029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Given a string, return the corresponding function token.
7039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param key A local name of a function.
7059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return   The function ID, which may correspond to one of the FUNC_XXX
7079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *    values found in {@link org.apache.xpath.compiler.FunctionTable}, but may
7089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *    be a value installed by an external module.
7099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
7109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  final int getFunctionToken(String key)
7119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
7129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int tok;
7149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Object id;
7169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    try
7189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
7199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // These are nodetests, xpathparser treats them as functions when parsing
7209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // a FilterExpr.
7219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      id = Keywords.lookupNodeTest(key);
7229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null == id) id = m_functionTable.getFunctionID(key);
7239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      tok = ((Integer) id).intValue();
7249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
7259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch (NullPointerException npe)
7269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
7279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      tok = -1;
7289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
7299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch (ClassCastException cce)
7309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
7319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      tok = -1;
7329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
7339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return tok;
7359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
7369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
7389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Insert room for operation.  This will NOT set
7399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the length value of the operation, but will update
7409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the length value for the total expression.
7419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param pos The position where the op is to be inserted.
7439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param length The length of the operation space in the op map.
7449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param op The op code to the inserted.
7459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
7469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void insertOp(int pos, int length, int op)
7479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
7489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int totalLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
7509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    for (int i = totalLen - 1; i >= pos; i--)
7529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
7539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(i + length, m_ops.getOp(i));
7549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
7559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(pos,op);
7579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH,totalLen + length);
7589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
7599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
7619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Insert room for operation.  This WILL set
7629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the length value of the operation, and will update
7639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the length value for the total expression.
7649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param length The length of the operation.
7669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param op The op code to the inserted.
7679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
7689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void appendOp(int length, int op)
7699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
7709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int totalLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
7729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(totalLen, op);
7749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(totalLen + OpMap.MAPINDEX_LENGTH, length);
7759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, totalLen + length);
7769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
7779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // ============= EXPRESSIONS FUNCTIONS =================
7799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
7819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Expr  ::=  OrExpr
7849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
7879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
7889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void Expr() throws javax.xml.transform.TransformerException
7899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
7909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    OrExpr();
7919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
7929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
7939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
7949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * OrExpr  ::=  AndExpr
7979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | OrExpr 'or' AndExpr
7989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
7999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
8019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
8029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void OrExpr() throws javax.xml.transform.TransformerException
8039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
8049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
8069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    AndExpr();
8089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if ((null != m_token) && tokenIs("or"))
8109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
8119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
8129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      insertOp(opPos, 2, OpCodes.OP_OR);
8139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      OrExpr();
8149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
8169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
8179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
8189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
8199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
8219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * AndExpr  ::=  EqualityExpr
8249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | AndExpr 'and' EqualityExpr
8259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
8289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
8299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void AndExpr() throws javax.xml.transform.TransformerException
8309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
8319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
8339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    EqualityExpr(-1);
8359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if ((null != m_token) && tokenIs("and"))
8379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
8389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
8399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      insertOp(opPos, 2, OpCodes.OP_AND);
8409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      AndExpr();
8419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
8439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
8449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
8459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
8469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
8489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @returns an Object which is either a String, a Number, a Boolean, or a vector
8509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * of nodes.
8519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * EqualityExpr  ::=  RelationalExpr
8539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | EqualityExpr '=' RelationalExpr
8549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param addPos Position where expression is to be added, or -1 for append.
8579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return the position at the end of the equality expression.
8599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
8609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
8619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
8629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected int EqualityExpr(int addPos) throws javax.xml.transform.TransformerException
8639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
8649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
8669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (-1 == addPos)
8689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      addPos = opPos;
8699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    RelationalExpr(-1);
8719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != m_token)
8739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
8749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('!') && lookahead('=', 1))
8759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
8769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
8779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
8789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(addPos, 2, OpCodes.OP_NOTEQUALS);
8799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
8819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = EqualityExpr(addPos);
8839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
8849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
8859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
8869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
8879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (tokenIs('='))
8889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
8899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
8909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(addPos, 2, OpCodes.OP_EQUALS);
8919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
8939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
8949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = EqualityExpr(addPos);
8959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
8969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
8979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
8989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
8999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
9009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return addPos;
9029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
9039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
9059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * .
9069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @returns an Object which is either a String, a Number, a Boolean, or a vector
9079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * of nodes.
9089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * RelationalExpr  ::=  AdditiveExpr
9109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | RelationalExpr '<' AdditiveExpr
9119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | RelationalExpr '>' AdditiveExpr
9129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | RelationalExpr '<=' AdditiveExpr
9139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | RelationalExpr '>=' AdditiveExpr
9149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param addPos Position where expression is to be added, or -1 for append.
9179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return the position at the end of the relational expression.
9199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
9219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
9229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected int RelationalExpr(int addPos) throws javax.xml.transform.TransformerException
9239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
9249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
9269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (-1 == addPos)
9289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      addPos = opPos;
9299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    AdditiveExpr(-1);
9319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != m_token)
9339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
9349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('<'))
9359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
9369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
9379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (tokenIs('='))
9399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
9409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          nextToken();
9419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          insertOp(addPos, 2, OpCodes.OP_LTE);
9429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
9439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        else
9449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
9459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          insertOp(addPos, 2, OpCodes.OP_LT);
9469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
9479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
9499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = RelationalExpr(addPos);
9519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
9529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
9539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
9549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
9559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (tokenIs('>'))
9569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
9579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
9589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (tokenIs('='))
9609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
9619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          nextToken();
9629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          insertOp(addPos, 2, OpCodes.OP_GTE);
9639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
9649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        else
9659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
9669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          insertOp(addPos, 2, OpCodes.OP_GT);
9679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
9689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
9709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = RelationalExpr(addPos);
9729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
9739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
9749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
9759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
9769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
9779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return addPos;
9799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
9809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
9819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
9829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * This has to handle construction of the operations so that they are evaluated
9839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * in pre-fix order.  So, for 9+7-6, instead of |+|9|-|7|6|, this needs to be
9849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * evaluated as |-|+|9|7|6|.
9859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * AdditiveExpr  ::=  MultiplicativeExpr
9879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | AdditiveExpr '+' MultiplicativeExpr
9889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | AdditiveExpr '-' MultiplicativeExpr
9899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param addPos Position where expression is to be added, or -1 for append.
9929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return the position at the end of the equality expression.
9949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
9959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
9969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
9979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected int AdditiveExpr(int addPos) throws javax.xml.transform.TransformerException
9989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
9999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
10019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (-1 == addPos)
10039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      addPos = opPos;
10049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    MultiplicativeExpr(-1);
10069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != m_token)
10089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
10099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('+'))
10109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
10119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
10129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(addPos, 2, OpCodes.OP_PLUS);
10139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
10159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = AdditiveExpr(addPos);
10179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
10189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
10199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
10209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
10219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (tokenIs('-'))
10229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
10239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
10249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(addPos, 2, OpCodes.OP_MINUS);
10259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
10279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = AdditiveExpr(addPos);
10299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
10309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
10319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
10329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
10339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
10349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return addPos;
10369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
10379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
10399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * This has to handle construction of the operations so that they are evaluated
10409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * in pre-fix order.  So, for 9+7-6, instead of |+|9|-|7|6|, this needs to be
10419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * evaluated as |-|+|9|7|6|.
10429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
10439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * MultiplicativeExpr  ::=  UnaryExpr
10449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | MultiplicativeExpr MultiplyOperator UnaryExpr
10459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | MultiplicativeExpr 'div' UnaryExpr
10469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | MultiplicativeExpr 'mod' UnaryExpr
10479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | MultiplicativeExpr 'quo' UnaryExpr
10489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
10499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param addPos Position where expression is to be added, or -1 for append.
10509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
10519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return the position at the end of the equality expression.
10529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
10539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
10549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
10559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected int MultiplicativeExpr(int addPos) throws javax.xml.transform.TransformerException
10569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
10579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
10599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (-1 == addPos)
10619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      addPos = opPos;
10629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    UnaryExpr();
10649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != m_token)
10669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
10679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('*'))
10689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
10699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
10709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(addPos, 2, OpCodes.OP_MULT);
10719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
10739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = MultiplicativeExpr(addPos);
10759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
10769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
10779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
10789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
10799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (tokenIs("div"))
10809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
10819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
10829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(addPos, 2, OpCodes.OP_DIV);
10839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
10859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = MultiplicativeExpr(addPos);
10879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
10889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
10899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
10909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
10919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (tokenIs("mod"))
10929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
10939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
10949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(addPos, 2, OpCodes.OP_MOD);
10959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
10979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
10989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = MultiplicativeExpr(addPos);
10999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
11009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
11019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
11029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
11039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (tokenIs("quo"))
11049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
11059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
11069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(addPos, 2, OpCodes.OP_QUO);
11079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
11099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos = MultiplicativeExpr(addPos);
11119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
11129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
11139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        addPos += 2;
11149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
11159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
11169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return addPos;
11189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
11199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
11219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * UnaryExpr  ::=  UnionExpr
11239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | '-' UnaryExpr
11249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
11279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
11289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void UnaryExpr() throws javax.xml.transform.TransformerException
11299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
11309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
11329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean isNeg = false;
11339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_tokenChar == '-')
11359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
11369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
11379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, OpCodes.OP_NEG);
11389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      isNeg = true;
11409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
11419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    UnionExpr();
11439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (isNeg)
11459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
11469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
11479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
11489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
11509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * StringExpr  ::=  Expr
11529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
11559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
11569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void StringExpr() throws javax.xml.transform.TransformerException
11579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
11589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
11609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    appendOp(2, OpCodes.OP_STRING);
11629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Expr();
11639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
11659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
11669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
11679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
11699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * StringExpr  ::=  Expr
11729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
11759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
11769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void BooleanExpr() throws javax.xml.transform.TransformerException
11779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
11789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
11809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    appendOp(2, OpCodes.OP_BOOL);
11829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Expr();
11839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos;
11859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (opLen == 2)
11879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
11889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      error(XPATHErrorResources.ER_BOOLEAN_ARG_NO_LONGER_OPTIONAL, null);  //"boolean(...) argument is no longer optional with 19990709 XPath draft.");
11899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
11909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, opLen);
11929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
11939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
11949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
11959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * NumberExpr  ::=  Expr
11989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
11999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
12019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
12029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void NumberExpr() throws javax.xml.transform.TransformerException
12039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
12049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
12069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    appendOp(2, OpCodes.OP_NUMBER);
12089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Expr();
12099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
12119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
12129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
12139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
12159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The context of the right hand side expressions is the context of the
12169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * left hand side expression. The results of the right hand side expressions
12179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * are node sets. The result of the left hand side UnionExpr is the union
12189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * of the results of the right hand side expressions.
12199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * UnionExpr    ::=    PathExpr
12229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | UnionExpr '|' PathExpr
12239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
12269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
12279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void UnionExpr() throws javax.xml.transform.TransformerException
12289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
12299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
12319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean continueOrLoop = true;
12329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean foundUnion = false;
12339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    do
12359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
12369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      PathExpr();
12379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('|'))
12399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
12409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (false == foundUnion)
12419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
12429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          foundUnion = true;
12439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          insertOp(opPos, 2, OpCodes.OP_UNION);
12459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
12469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
12489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
12499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
12509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
12519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        break;
12529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
12539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // this.m_testForDocOrder = true;
12559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
12569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    while (continueOrLoop);
12579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
12599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
12609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
12619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
12639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * PathExpr  ::=  LocationPath
12649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | FilterExpr
12659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | FilterExpr '/' RelativeLocationPath
12669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | FilterExpr '//' RelativeLocationPath
12679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
12699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the error condition is severe enough to halt processing.
12709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
12719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
12729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
12739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void PathExpr() throws javax.xml.transform.TransformerException
12749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
12759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
12779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int filterExprMatch = FilterExpr();
12799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (filterExprMatch != FILTER_MATCH_FAILED)
12819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
12829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // If FilterExpr had Predicates, a OP_LOCATIONPATH opcode would already
12839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // have been inserted.
12849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      boolean locationPathStarted = (filterExprMatch==FILTER_MATCH_PREDICATES);
12859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('/'))
12879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
12889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
12899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (!locationPathStarted)
12919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
12929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // int locationPathOpPos = opPos;
12939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          insertOp(opPos, 2, OpCodes.OP_LOCATIONPATH);
12949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          locationPathStarted = true;
12969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
12979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
12989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (!RelativeLocationPath())
12999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
13009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // "Relative location path expected following '/' or '//'"
13019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          error(XPATHErrorResources.ER_EXPECTED_REL_LOC_PATH, null);
13029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
13039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
13059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Terminate for safety.
13079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (locationPathStarted)
13089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
13099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
13109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
13119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
13129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
13139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
13149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
13159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
13169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
13179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      LocationPath();
13189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
13199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
13209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
13229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * FilterExpr  ::=  PrimaryExpr
13259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | FilterExpr Predicate
13269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
13289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the error condition is severe enough to halt processing.
13299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return  FILTER_MATCH_PREDICATES, if this method successfully matched a
13319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *          FilterExpr with one or more Predicates;
13329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *          FILTER_MATCH_PRIMARY, if this method successfully matched a
13339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *          FilterExpr that was just a PrimaryExpr; or
13349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *          FILTER_MATCH_FAILED, if this method did not match a FilterExpr
13359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
13379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
13389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected int FilterExpr() throws javax.xml.transform.TransformerException
13399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
13409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
13429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int filterMatch;
13449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (PrimaryExpr())
13469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
13479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('['))
13489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
13499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // int locationPathOpPos = opPos;
13519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        insertOp(opPos, 2, OpCodes.OP_LOCATIONPATH);
13529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        while (tokenIs('['))
13549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
13559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          Predicate();
13569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
13579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        filterMatch = FILTER_MATCH_PREDICATES;
13599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
13609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
13619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
13629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        filterMatch = FILTER_MATCH_PRIMARY;
13639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
13649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
13659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
13669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
13679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      filterMatch = FILTER_MATCH_FAILED;
13689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
13699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return filterMatch;
13719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /*
13739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * if(tokenIs('['))
13749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * {
13759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *   Predicate();
13769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *   m_ops.m_opMap[opPos + OpMap.MAPINDEX_LENGTH] = m_ops.m_opMap[OpMap.MAPINDEX_LENGTH] - opPos;
13779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * }
13789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
13799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
13809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
13829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * PrimaryExpr  ::=  VariableReference
13849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | '(' Expr ')'
13859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | Literal
13869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | Number
13879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | FunctionCall
13889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return true if this method successfully matched a PrimaryExpr
13909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
13929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
13939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
13949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected boolean PrimaryExpr() throws javax.xml.transform.TransformerException
13959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
13969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
13979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean matchFound;
13989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
13999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if ((m_tokenChar == '\'') || (m_tokenChar == '"'))
14019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, OpCodes.OP_LITERAL);
14039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Literal();
14049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
14069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
14079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      matchFound = true;
14099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
14109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (m_tokenChar == '$')
14119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();  // consume '$'
14139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, OpCodes.OP_VARIABLE);
14149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      QName();
14159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
14179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
14189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      matchFound = true;
14209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
14219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (m_tokenChar == '(')
14229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
14249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, OpCodes.OP_GROUP);
14259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Expr();
14269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      consumeExpected(')');
14279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
14299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
14309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      matchFound = true;
14329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
14339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if ((null != m_token) && ((('.' == m_tokenChar) && (m_token.length() > 1) && Character.isDigit(
14349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            m_token.charAt(1))) || Character.isDigit(m_tokenChar)))
14359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, OpCodes.OP_NUMBERLIT);
14379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Number();
14389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
14409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
14419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      matchFound = true;
14439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
14449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (lookahead('(', 1) || (lookahead(':', 1) && lookahead('(', 3)))
14459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      matchFound = FunctionCall();
14479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
14489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
14499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      matchFound = false;
14519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
14529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return matchFound;
14549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
14559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
14579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Argument    ::=    Expr
14599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
14629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
14639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void Argument() throws javax.xml.transform.TransformerException
14649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
14659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
14679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    appendOp(2, OpCodes.OP_ARGUMENT);
14699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Expr();
14709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
14729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
14739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
14749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
14769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * FunctionCall    ::=    FunctionName '(' ( Argument ( ',' Argument)*)? ')'
14789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return true if, and only if, a FunctionCall was matched
14809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
14819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
14829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
14839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected boolean FunctionCall() throws javax.xml.transform.TransformerException
14849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
14859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
14879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (lookahead(':', 1))
14899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
14909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(4, OpCodes.OP_EXTFUNCTION);
14919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, m_queueMark - 1);
14939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
14959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      consumeExpected(':');
14969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 2, m_queueMark - 1);
14989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
14999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
15009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
15019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
15029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
15039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int funcTok = getFunctionToken(m_token);
15049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (-1 == funcTok)
15069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
15079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_COULDNOT_FIND_FUNCTION,
15089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              new Object[]{ m_token });  //"Could not find function: "+m_token+"()");
15099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
15109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      switch (funcTok)
15129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
15139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case OpCodes.NODETYPE_PI :
15149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case OpCodes.NODETYPE_COMMENT :
15159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case OpCodes.NODETYPE_TEXT :
15169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      case OpCodes.NODETYPE_NODE :
15179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Node type tests look like function calls, but they're not
15189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return false;
15199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      default :
15209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        appendOp(3, OpCodes.OP_FUNCTION);
15219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, funcTok);
15239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
15249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
15269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
15279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    consumeExpected('(');
15299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    while (!tokenIs(')') && m_token != null)
15319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
15329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs(','))
15339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
15349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG, null);  //"Found ',' but no preceding argument!");
15359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
15369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Argument();
15389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (!tokenIs(')'))
15409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
15419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        consumeExpected(',');
15429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (tokenIs(')'))
15449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
15459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG,
15469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                null);  //"Found ',' but no following argument!");
15479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
15489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
15499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
15509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    consumeExpected(')');
15529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Terminate for safety.
15549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
15559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
15569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
15579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
15589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return true;
15609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
15619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // ============= GRAMMAR FUNCTIONS =================
15639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
15659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * LocationPath ::= RelativeLocationPath
15679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | AbsoluteLocationPath
15689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
15709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
15719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
15729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void LocationPath() throws javax.xml.transform.TransformerException
15739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
15749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
15769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // int locationPathOpPos = opPos;
15789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    appendOp(2, OpCodes.OP_LOCATIONPATH);
15799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean seenSlash = tokenIs('/');
15819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (seenSlash)
15839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
15849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(4, OpCodes.FROM_ROOT);
15859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Tell how long the step is without the predicate
15879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2, 4);
15889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_ROOT);
15899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
15919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } else if (m_token == null) {
15929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      error(XPATHErrorResources.ER_EXPECTED_LOC_PATH_AT_END_EXPR, null);
15939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
15949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
15959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (m_token != null)
15969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
15979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (!RelativeLocationPath() && !seenSlash)
15989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
15999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Neither a '/' nor a RelativeLocationPath - i.e., matched nothing
16009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // "Location path expected, but found "+m_token+" was encountered."
16019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_EXPECTED_LOC_PATH,
16029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              new Object [] {m_token});
16039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
16049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
16059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Terminate for safety.
16079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
16089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
16099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
16109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
16119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
16129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
16149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * RelativeLocationPath ::= Step
16169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | RelativeLocationPath '/' Step
16179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | AbbreviatedRelativeLocationPath
16189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @returns true if, and only if, a RelativeLocationPath was matched
16209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
16229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
16239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected boolean RelativeLocationPath()
16249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson               throws javax.xml.transform.TransformerException
16259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
16269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (!Step())
16279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
16289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return false;
16299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
16309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    while (tokenIs('/'))
16329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
16339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
16349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (!Step())
16369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
16379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // RelativeLocationPath can't end with a trailing '/'
16389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // "Location step expected following '/' or '//'"
16399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_EXPECTED_LOC_STEP, null);
16409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
16419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
16429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return true;
16449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
16459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
16479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Step    ::=    Basis Predicate
16499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | AbbreviatedStep
16509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @returns false if step was empty (or only a '/'); true, otherwise
16529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
16539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
16549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
16559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected boolean Step() throws javax.xml.transform.TransformerException
16569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
16579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
16589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean doubleSlash = tokenIs('/');
16609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // At most a single '/' before each Step is consumed by caller; if the
16629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // first thing is a '/', that means we had '//' and the Step must not
16639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // be empty.
16649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (doubleSlash)
16659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
16669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
16679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, OpCodes.FROM_DESCENDANTS_OR_SELF);
16699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Have to fix up for patterns such as '//@foo' or '//attribute::foo',
16719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // which translate to 'descendant-or-self::node()/attribute::foo'.
16729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // notice I leave the '/' on the queue, so the next will be processed
16739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // by a regular step pattern.
16749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Make room for telling how long the step is without the predicate
16769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
16779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.NODETYPE_NODE);
16789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
16799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Tell how long the step is without the predicate
16819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1,
16829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
16839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Tell how long the step is with the predicate
16859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
16869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
16879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
16899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
16909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (tokenIs("."))
16929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
16939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
16949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
16959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('['))
16969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
16979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_PREDICATE_ILLEGAL_SYNTAX, null);  //"'..[predicate]' or '.[predicate]' is illegal syntax.  Use 'self::node()[predicate]' instead.");
16989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
16999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(4, OpCodes.FROM_SELF);
17019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Tell how long the step is without the predicate
17039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2,4);
17049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_NODE);
17059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (tokenIs(".."))
17079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
17099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(4, OpCodes.FROM_PARENT);
17109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Tell how long the step is without the predicate
17129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2,4);
17139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_NODE);
17149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // There is probably a better way to test for this
17179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // transition... but it gets real hairy if you try
17189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // to do it in basis().
17199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (tokenIs('*') || tokenIs('@') || tokenIs('_')
17209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson             || (m_token!= null && Character.isLetter(m_token.charAt(0))))
17219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Basis();
17239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while (tokenIs('['))
17259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
17269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        Predicate();
17279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
17289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Tell how long the entire step is.
17309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
17319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
17329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
17349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // No Step matched - that's an error if previous thing was a '//'
17369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (doubleSlash)
17379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
17389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // "Location step expected following '/' or '//'"
17399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_EXPECTED_LOC_STEP, null);
17409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
17419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return false;
17439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return true;
17469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
17479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
17499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
17509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Basis    ::=    AxisName '::' NodeTest
17519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | AbbreviatedBasis
17529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
17539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
17549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
17559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void Basis() throws javax.xml.transform.TransformerException
17569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
17579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
17599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int axesType;
17609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // The next blocks guarantee that a FROM_XXX will be added.
17629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (lookahead("::", 1))
17639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      axesType = AxisName();
17659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
17679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
17689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (tokenIs('@'))
17709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      axesType = OpCodes.FROM_ATTRIBUTES;
17729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, axesType);
17749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
17759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
17779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
17789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      axesType = OpCodes.FROM_CHILDREN;
17799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, axesType);
17819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
17829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Make room for telling how long the step is without the predicate
17849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
17859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    NodeTest(axesType);
17879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Tell how long the step is without the predicate
17899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1,
17909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
17919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   }
17929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
17939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
17949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
17959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Basis    ::=    AxisName '::' NodeTest
17969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | AbbreviatedBasis
17979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
17989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return FROM_XXX axes type, found in {@link org.apache.xpath.compiler.Keywords}.
17999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
18009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
18019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
18029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected int AxisName() throws javax.xml.transform.TransformerException
18039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
18049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Object val = Keywords.getAxisName(m_token);
18069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null == val)
18089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
18099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      error(XPATHErrorResources.ER_ILLEGAL_AXIS_NAME,
18109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            new Object[]{ m_token });  //"illegal axis name: "+m_token);
18119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
18129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int axesType = ((Integer) val).intValue();
18149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    appendOp(2, axesType);
18169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return axesType;
18189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
18199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
18219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
18229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * NodeTest    ::=    WildcardName
18239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | NodeType '(' ')'
18249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | 'processing-instruction' '(' Literal ')'
18259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
18269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param axesType FROM_XXX axes type, found in {@link org.apache.xpath.compiler.Keywords}.
18279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
18289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
18299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
18309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void NodeTest(int axesType) throws javax.xml.transform.TransformerException
18319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
18329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (lookahead('(', 1))
18349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
18359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Object nodeTestOp = Keywords.getNodeType(m_token);
18369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null == nodeTestOp)
18389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
18399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_UNKNOWN_NODETYPE,
18409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              new Object[]{ m_token });  //"Unknown nodetype: "+m_token);
18419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
18429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
18439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
18449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
18459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int nt = ((Integer) nodeTestOp).intValue();
18479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), nt);
18499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
18509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        consumeExpected('(');
18529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (OpCodes.NODETYPE_PI == nt)
18549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
18559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (!tokenIs(')'))
18569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
18579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            Literal();
18589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
18599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
18609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        consumeExpected(')');
18629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
18639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
18649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
18659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
18669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Assume name of attribute or element.
18689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.NODENAME);
18699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
18709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (lookahead(':', 1))
18729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
18739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (tokenIs('*'))
18749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
18759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD);
18769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
18779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        else
18789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
18799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
18809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // Minimalist check for an NCName - just check first character
18829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // to distinguish from other possible tokens
18839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (!Character.isLetter(m_tokenChar) && !tokenIs('_'))
18849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
18859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // "Node test that matches either NCName:* or QName was expected."
18869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null);
18879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
18889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
18899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
18919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        consumeExpected(':');
18929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
18939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
18949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
18959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.EMPTY);
18969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
18979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
18989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
18999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('*'))
19019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
19029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD);
19039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
19049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
19059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
19069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
19079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Minimalist check for an NCName - just check first character
19099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // to distinguish from other possible tokens
19109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (!Character.isLetter(m_tokenChar) && !tokenIs('_'))
19119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
19129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // "Node test that matches either NCName:* or QName was expected."
19139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null);
19149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
19159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
19169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
19189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
19209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
19219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
19229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
19249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
19259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Predicate ::= '[' PredicateExpr ']'
19269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
19279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
19289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
19299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
19309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void Predicate() throws javax.xml.transform.TransformerException
19319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
19329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (tokenIs('['))
19349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
19359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
19369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      PredicateExpr();
19379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      consumeExpected(']');
19389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
19399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
19409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
19429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
19439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * PredicateExpr ::= Expr
19449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
19459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
19469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
19479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
19489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void PredicateExpr() throws javax.xml.transform.TransformerException
19499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
19509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
19529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    appendOp(2, OpCodes.OP_PREDICATE);
19549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    Expr();
19559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Terminate for safety.
19579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
19589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
19599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
19609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
19619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
19629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
19649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * QName ::=  (Prefix ':')? LocalPart
19659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Prefix ::=  NCName
19669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * LocalPart ::=  NCName
19679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
19689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
19699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
19709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void QName() throws javax.xml.transform.TransformerException
19719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
19729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Namespace
19739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(lookahead(':', 1))
19749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
19759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
19769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
19779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
19799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      consumeExpected(':');
19809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
19819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
19829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
19839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.EMPTY);
19849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
19859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
19869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Local name
19889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
19899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
19909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    nextToken();
19929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
19939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
19949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
19959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * NCName ::=  (Letter | '_') (NCNameChar)
19969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * NCNameChar ::=  Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender
19979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
19989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void NCName()
19999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
20009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
20029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
20039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    nextToken();
20059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
20069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
20089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The value of the Literal is the sequence of characters inside
20099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the " or ' characters>.
20109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Literal  ::=  '"' [^"]* '"'
20129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | "'" [^']* "'"
20139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
20169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
20179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void Literal() throws javax.xml.transform.TransformerException
20189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
20199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int last = m_token.length() - 1;
20219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    char c0 = m_tokenChar;
20229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    char cX = m_token.charAt(last);
20239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (((c0 == '\"') && (cX == '\"')) || ((c0 == '\'') && (cX == '\'')))
20259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
20269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Mutate the token to remove the quotes and have the XString object
20289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // already made.
20299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int tokenQueuePos = m_queueMark - 1;
20309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.m_tokenQueue.setElementAt(null,tokenQueuePos);
20329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Object obj = new XString(m_token.substring(1, last));
20349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.m_tokenQueue.setElementAt(obj,tokenQueuePos);
20369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // lit = m_token.substring(1, last);
20389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), tokenQueuePos);
20399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
20409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
20429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
20439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
20449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
20459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      error(XPATHErrorResources.ER_PATTERN_LITERAL_NEEDS_BE_QUOTED,
20469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            new Object[]{ m_token });  //"Pattern literal ("+m_token+") needs to be quoted!");
20479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
20489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
20499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
20519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Number ::= [0-9]+('.'[0-9]+)? | '.'[0-9]+
20539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
20569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
20579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void Number() throws javax.xml.transform.TransformerException
20589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
20599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != m_token)
20619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
20629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Mutate the token to remove the quotes and have the XNumber object
20649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // already made.
20659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      double num;
20669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      try
20689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
20699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      	// XPath 1.0 does not support number in exp notation
20709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      	if ((m_token.indexOf('e') > -1)||(m_token.indexOf('E') > -1))
20719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      		throw new NumberFormatException();
20729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        num = Double.valueOf(m_token).doubleValue();
20739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
20749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      catch (NumberFormatException nfe)
20759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
20769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        num = 0.0;  // to shut up compiler.
20779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_COULDNOT_BE_FORMATTED_TO_NUMBER,
20799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              new Object[]{ m_token });  //m_token+" could not be formatted to a number!");
20809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
20819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.m_tokenQueue.setElementAt(new XNumber(num),m_queueMark - 1);
20839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
20849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
20859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
20879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
20889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
20899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // ============= PATTERN FUNCTIONS =================
20919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
20929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
20939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Pattern  ::=  LocationPathPattern
20959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | Pattern '|' LocationPathPattern
20969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
20989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
20999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
21009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void Pattern() throws javax.xml.transform.TransformerException
21019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
21029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    while (true)
21049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
21059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      LocationPathPattern();
21069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('|'))
21089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
21099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
21109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
21119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
21129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
21139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        break;
21149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
21159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
21169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
21179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
21199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
21209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
21219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * LocationPathPattern  ::=  '/' RelativePathPattern?
21229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | IdKeyPattern (('/' | '//') RelativePathPattern)?
21239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | '//'? RelativePathPattern
21249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
21259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
21269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
21279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
21289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void LocationPathPattern() throws javax.xml.transform.TransformerException
21299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
21309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
21329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    final int RELATIVE_PATH_NOT_PERMITTED = 0;
21349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    final int RELATIVE_PATH_PERMITTED     = 1;
21359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    final int RELATIVE_PATH_REQUIRED      = 2;
21369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int relativePathStatus = RELATIVE_PATH_NOT_PERMITTED;
21389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    appendOp(2, OpCodes.OP_LOCATIONPATHPATTERN);
21409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (lookahead('(', 1)
21429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            && (tokenIs(Keywords.FUNC_ID_STRING)
21439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                || tokenIs(Keywords.FUNC_KEY_STRING)))
21449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
21459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      IdKeyPattern();
21469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs('/'))
21489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
21499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
21509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (tokenIs('/'))
21529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
21539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          appendOp(4, OpCodes.MATCH_ANY_ANCESTOR);
21549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          nextToken();
21569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
21579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        else
21589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
21599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          appendOp(4, OpCodes.MATCH_IMMEDIATE_ANCESTOR);
21609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
21619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Tell how long the step is without the predicate
21639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2, 4);
21649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_FUNCTEST);
21659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        relativePathStatus = RELATIVE_PATH_REQUIRED;
21679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
21689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
21699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (tokenIs('/'))
21709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
21719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (lookahead('/', 1))
21729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
21739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        appendOp(4, OpCodes.MATCH_ANY_ANCESTOR);
21749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Added this to fix bug reported by Myriam for match="//x/a"
21769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // patterns.  If you don't do this, the 'x' step will think it's part
21779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // of a '//' pattern, and so will cause 'a' to be matched when it has
21789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // any ancestor that is 'x'.
21799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        nextToken();
21809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        relativePathStatus = RELATIVE_PATH_REQUIRED;
21829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
21839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
21849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
21859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        appendOp(4, OpCodes.FROM_ROOT);
21869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        relativePathStatus = RELATIVE_PATH_PERMITTED;
21889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
21899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Tell how long the step is without the predicate
21929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2, 4);
21939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_ROOT);
21949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
21959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
21969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
21979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
21989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
21999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      relativePathStatus = RELATIVE_PATH_REQUIRED;
22009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
22019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (relativePathStatus != RELATIVE_PATH_NOT_PERMITTED)
22039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
22049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (!tokenIs('|') && (null != m_token))
22059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
22069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        RelativePathPattern();
22079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
22089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (relativePathStatus == RELATIVE_PATH_REQUIRED)
22099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
22109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // "A relative path pattern was expected."
22119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_EXPECTED_REL_PATH_PATTERN, null);
22129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
22139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
22149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Terminate for safety.
22169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
22179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
22189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
22199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
22209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
22219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
22239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * IdKeyPattern  ::=  'id' '(' Literal ')'
22259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | 'key' '(' Literal ',' Literal ')'
22269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * (Also handle doc())
22279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
22309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
22319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void IdKeyPattern() throws javax.xml.transform.TransformerException
22329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
22339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    FunctionCall();
22349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
22359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
22379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * RelativePathPattern  ::=  StepPattern
22399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | RelativePathPattern '/' StepPattern
22409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * | RelativePathPattern '//' StepPattern
22419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
22439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
22449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void RelativePathPattern()
22459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              throws javax.xml.transform.TransformerException
22469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
22479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Caller will have consumed any '/' or '//' preceding the
22499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // RelativePathPattern, so let StepPattern know it can't begin with a '/'
22509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean trailingSlashConsumed = StepPattern(false);
22519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    while (tokenIs('/'))
22539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
22549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
22559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // StepPattern() may consume first slash of pair in "a//b" while
22579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // processing StepPattern "a".  On next iteration, let StepPattern know
22589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // that happened, so it doesn't match ill-formed patterns like "a///b".
22599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      trailingSlashConsumed = StepPattern(!trailingSlashConsumed);
22609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
22619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
22629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
22649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * StepPattern  ::=  AbbreviatedNodeTestStep
22669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param isLeadingSlashPermitted a boolean indicating whether a slash can
22689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *        appear at the start of this step
22699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return boolean indicating whether a slash following the step was consumed
22719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
22739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
22749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected boolean StepPattern(boolean isLeadingSlashPermitted)
22759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws javax.xml.transform.TransformerException
22769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
22779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return AbbreviatedNodeTestStep(isLeadingSlashPermitted);
22789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
22799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
22819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * AbbreviatedNodeTestStep    ::=    '@'? NodeTest Predicate
22839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param isLeadingSlashPermitted a boolean indicating whether a slash can
22859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *        appear at the start of this step
22869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return boolean indicating whether a slash following the step was consumed
22889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
22899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
22909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
22919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected boolean AbbreviatedNodeTestStep(boolean isLeadingSlashPermitted)
22929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws javax.xml.transform.TransformerException
22939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
22949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
22969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int axesType;
22979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
22989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // The next blocks guarantee that a MATCH_XXX will be added.
22999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int matchTypePos = -1;
23009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (tokenIs('@'))
23029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
23039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      axesType = OpCodes.MATCH_ATTRIBUTE;
23049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, axesType);
23069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
23079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
23089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (this.lookahead("::", 1))
23099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
23109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (tokenIs("attribute"))
23119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
23129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        axesType = OpCodes.MATCH_ATTRIBUTE;
23139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        appendOp(2, axesType);
23159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
23169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else if (tokenIs("child"))
23179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
23189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        matchTypePos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
23199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        axesType = OpCodes.MATCH_IMMEDIATE_ANCESTOR;
23209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        appendOp(2, axesType);
23229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
23239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      else
23249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
23259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        axesType = -1;
23269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        this.error(XPATHErrorResources.ER_AXES_NOT_ALLOWED,
23289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                   new Object[]{ this.m_token });
23299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
23309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
23329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
23339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
23349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (tokenIs('/'))
23359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
23369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (!isLeadingSlashPermitted)
23379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
23389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // "A step was expected in the pattern, but '/' was encountered."
23399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        error(XPATHErrorResources.ER_EXPECTED_STEP_PATTERN, null);
23409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
23419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      axesType = OpCodes.MATCH_ANY_ANCESTOR;
23429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, axesType);
23449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
23459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
23469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
23479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
23489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      matchTypePos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
23499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      axesType = OpCodes.MATCH_IMMEDIATE_ANCESTOR;
23509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      appendOp(2, axesType);
23529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
23539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Make room for telling how long the step is without the predicate
23559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
23569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    NodeTest(axesType);
23589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Tell how long the step is without the predicate
23609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1,
23619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
23629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    while (tokenIs('['))
23649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
23659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      Predicate();
23669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
23679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    boolean trailingSlashConsumed;
23699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // For "a//b", where "a" is current step, we need to mark operation of
23719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // current step as "MATCH_ANY_ANCESTOR".  Then we'll consume the first
23729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // slash and subsequent step will be treated as a MATCH_IMMEDIATE_ANCESTOR
23739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // (unless it too is followed by '//'.)
23749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
23759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %REVIEW%  Following is what happens today, but I'm not sure that's
23769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %REVIEW%  correct behaviour.  Perhaps no valid case could be constructed
23779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // %REVIEW%  where it would matter?
23789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
23799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // If current step is on the attribute axis (e.g., "@x//b"), we won't
23809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // change the current step, and let following step be marked as
23819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // MATCH_ANY_ANCESTOR on next call instead.
23829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if ((matchTypePos > -1) && tokenIs('/') && lookahead('/', 1))
23839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
23849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.setOp(matchTypePos, OpCodes.MATCH_ANY_ANCESTOR);
23859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      nextToken();
23879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      trailingSlashConsumed = true;
23899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
23909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
23919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
23929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      trailingSlashConsumed = false;
23939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
23949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Tell how long the entire step is.
23969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
23979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
23989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
23999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return trailingSlashConsumed;
24009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
24019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
2402