protected void LocationPathPattern() throws javax.xml.transform.TransformerException
  {

    int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);

    final int RELATIVE_PATH_NOT_PERMITTED = 0;
    final int RELATIVE_PATH_PERMITTED     = 1;
    final int RELATIVE_PATH_REQUIRED      = 2;

    int relativePathStatus = RELATIVE_PATH_NOT_PERMITTED;

    appendOp(2, OpCodes.OP_LOCATIONPATHPATTERN);

    if (lookahead('(', 1)
            && (tokenIs(Keywords.FUNC_ID_STRING)
                || tokenIs(Keywords.FUNC_KEY_STRING)))
    {
      IdKeyPattern();

      if (tokenIs('/'))
      {
        nextToken();

        if (tokenIs('/'))
        {
          appendOp(4, OpCodes.MATCH_ANY_ANCESTOR);

          nextToken();
        }
        else
        {
          appendOp(4, OpCodes.MATCH_IMMEDIATE_ANCESTOR);
        }

        // Tell how long the step is without the predicate
        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2, 4);
        m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_FUNCTEST);

        relativePathStatus = RELATIVE_PATH_REQUIRED;
      }
    }
    else if (tokenIs('/'))
    {
      if (lookahead('/', 1))
      {
        appendOp(4, OpCodes.MATCH_ANY_ANCESTOR);
        
        // Added this to fix bug reported by Myriam for match="//x/a"
        // patterns.  If you don't do this, the 'x' step will think it's part
        // of a '//' pattern, and so will cause 'a' to be matched when it has
        // any ancestor that is 'x'.
        nextToken();

        relativePathStatus = RELATIVE_PATH_REQUIRED;
      }
      else
      {
        appendOp(4, OpCodes.FROM_ROOT);

        relativePathStatus = RELATIVE_PATH_PERMITTED;
      }


      // Tell how long the step is without the predicate
      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 2, 4);
      m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH) - 1, OpCodes.NODETYPE_ROOT);

      nextToken();
    }
    else
    {
      relativePathStatus = RELATIVE_PATH_REQUIRED;
    }

    if (relativePathStatus != RELATIVE_PATH_NOT_PERMITTED)
    {
      if (!tokenIs('|') && (null != m_token))
      {
        RelativePathPattern();
      }
      else if (relativePathStatus == RELATIVE_PATH_REQUIRED)
      {
        // "A relative path pattern was expected."
        error(XPATHErrorResources.ER_EXPECTED_REL_PATH_PATTERN, null);
      }
    }

    // Terminate for safety.
    m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ENDOP);
    m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
    m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
      m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
  }
protected void LocationPathPattern ( ) throws javax . xml . transform . TransformerException { int opPos = m_ops . getOp ( OpMap . MAPINDEX_LENGTH ) ; final int RELATIVE_PATH_NOT_PERMITTED = 0 ; final int RELATIVE_PATH_PERMITTED = 1 ; final int RELATIVE_PATH_REQUIRED = 2 ; int relativePathStatus = RELATIVE_PATH_NOT_PERMITTED ; appendOp ( 2 , OpCodes . OP_LOCATIONPATHPATTERN ) ; if ( lookahead ( '(' , 1 ) && ( tokenIs ( Keywords . FUNC_ID_STRING ) || tokenIs ( Keywords . FUNC_KEY_STRING ) ) ) { IdKeyPattern ( ) ; if ( tokenIs ( '/' ) ) { nextToken ( ) ; if ( tokenIs ( '/' ) ) { appendOp ( 4 , OpCodes . MATCH_ANY_ANCESTOR ) ; nextToken ( ) ; } else { appendOp ( 4 , OpCodes . MATCH_IMMEDIATE_ANCESTOR ) ; } m_ops . setOp ( m_ops . getOp ( OpMap . MAPINDEX_LENGTH ) - 2 , 4 ) ; m_ops . setOp ( m_ops . getOp ( OpMap . MAPINDEX_LENGTH ) - 1 , OpCodes . NODETYPE_FUNCTEST ) ; relativePathStatus = RELATIVE_PATH_REQUIRED ; } } else if ( tokenIs ( '/' ) ) { if ( lookahead ( '/' , 1 ) ) { appendOp ( 4 , OpCodes . MATCH_ANY_ANCESTOR ) ; nextToken ( ) ; relativePathStatus = RELATIVE_PATH_REQUIRED ; } else { appendOp ( 4 , OpCodes . FROM_ROOT ) ; relativePathStatus = RELATIVE_PATH_PERMITTED ; } m_ops . setOp ( m_ops . getOp ( OpMap . MAPINDEX_LENGTH ) - 2 , 4 ) ; m_ops . setOp ( m_ops . getOp ( OpMap . MAPINDEX_LENGTH ) - 1 , OpCodes . NODETYPE_ROOT ) ; nextToken ( ) ; } else { relativePathStatus = RELATIVE_PATH_REQUIRED ; } if ( relativePathStatus != RELATIVE_PATH_NOT_PERMITTED ) { if ( ! tokenIs ( '|' ) && ( null != m_token ) ) { RelativePathPattern ( ) ; } else if ( relativePathStatus == RELATIVE_PATH_REQUIRED ) { error ( XPATHErrorResources . ER_EXPECTED_REL_PATH_PATTERN , null ) ; } } m_ops . setOp ( m_ops . getOp ( OpMap . MAPINDEX_LENGTH ) , OpCodes . ENDOP ) ; m_ops . setOp ( OpMap . MAPINDEX_LENGTH , m_ops . getOp ( OpMap . MAPINDEX_LENGTH ) + 1 ) ; m_ops . setOp ( opPos + OpMap . MAPINDEX_LENGTH , m_ops . getOp ( OpMap . MAPINDEX_LENGTH ) - opPos ) ; }
LocationPathPattern  ::=  '/' RelativePathPattern?
| IdKeyPattern (('/' | '//') RelativePathPattern)?
| '//'? RelativePathPattern


@throws javax.xml.transform.TransformerException