void XercesXPath::parseExpression()

in src/xercesc/validators/schema/identity/XercesXPath.cpp [382:688]


void XercesXPath::parseExpression(XMLStringPool* const stringPool,
                                  XercesNamespaceResolver* const scopeContext) {

    XMLSize_t length = XMLString::stringLen(fExpression);

    if (!length) {
        return;
    }

    ValueVectorOf<int>                tokens(16, fMemoryManager);
    XPathScannerForSchema             scanner(stringPool);
    if(!scanner.scanExpression(fExpression, 0, length, &tokens))
        ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_TokenNotSupported, fMemoryManager);

    bool                              firstTokenOfLocationPath=true;
    XMLSize_t                         tokenCount = tokens.size();
    RefVectorOf<XercesStep>*          stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
    Janitor<RefVectorOf<XercesStep> > janSteps(stepsVector);

    if (tokenCount) {
        fLocationPaths = new (fMemoryManager) RefVectorOf<XercesLocationPath>(8, true, fMemoryManager);
    }

    for (XMLSize_t i = 0; i < tokenCount; i++) {

        int  aToken = tokens.elementAt(i);
        bool isNamespace=false;

        switch (aToken) {
        case  XercesXPath::EXPRTOKEN_OPERATOR_UNION:
            {
                if (i == 0) {
                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtStart, fMemoryManager);
                }

                XMLSize_t stepsSize = stepsVector->size();

                if (stepsSize == 0) {
                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoMultipleUnion, fMemoryManager);
                }

                if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF)
                {
                    // prepend ./
                    XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
                    XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
                    stepsVector->insertElementAt(step, 0);
                }
                XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector);
                janSteps.orphan();
                bool bFound=false;
                for(XMLSize_t i=0;i<fLocationPaths->size();i++)
                    if((*(fLocationPaths->elementAt(i)))==(*newPath))
                    {
                        bFound=true;
                        break;
                    }
                if(bFound)
                    delete newPath;
                else
                    fLocationPaths->addElement(newPath);
                stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
                janSteps.reset(stepsVector);
                firstTokenOfLocationPath = true;
            }
            break;
        case XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE:
            {
                // consume "::" token and drop through
                i++;
            }
        case XercesXPath::EXPRTOKEN_ATSIGN:
            {
                // consume QName token
                if (i == tokenCount - 1) {
                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_MissingAttr, fMemoryManager);
                }

                aToken = tokens.elementAt(++i);

                if (aToken != XercesXPath::EXPRTOKEN_NAMETEST_QNAME
                    && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_ANY
                    && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE) {
                        ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedToken1, fMemoryManager);
                }

                bool isNamespaceAtt=false;

                switch (aToken) {

                case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
                    {
                        XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, fMemoryManager);
                        XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
                        stepsVector->addElement(step);
                        break;
                    }
                case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
                    {
                        isNamespaceAtt = true;
                    }
                case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
                    {
                        aToken = tokens.elementAt(++i);

                        const XMLCh* prefix = XMLUni::fgZeroLenString;
                        unsigned int uri = fEmptyNamespaceId;

                        if (scopeContext && aToken != -1) {

                            prefix = stringPool->getValueForId(aToken);
                            uri = scopeContext->getNamespaceForPrefix(prefix);
                        }

                        if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
                            ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager);
                        }

                        if (isNamespaceAtt) {

                            // build step
                            XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager);
                            XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
                            stepsVector->addElement(step);
                            break;
                        }

                        aToken = tokens.elementAt(++i);

                        const XMLCh* localPart = stringPool->getValueForId(aToken);
                        QName aQName(prefix, localPart, uri, fMemoryManager);

                        // build step
                        XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
                        XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
                        stepsVector->addElement(step);
                        break;
                    }
				}

                firstTokenOfLocationPath=false;
                break;
            }
        case XercesXPath::EXPRTOKEN_DOUBLE_COLON:
            {
                // should never have a bare double colon
                ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleColon, fMemoryManager);
            }
        case XercesXPath::EXPRTOKEN_AXISNAME_CHILD:
            {
                // consume "::" token and drop through
                i++;

                if (i == tokenCount - 1) {
                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep1, fMemoryManager);
                }

                firstTokenOfLocationPath=false;
                break;
            }
        case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
            {
                XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, fMemoryManager);
                XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
                stepsVector->addElement(step);
                firstTokenOfLocationPath = false;
                break;
            }
        case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
            {
                isNamespace=true;
            }
        case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
            {
                // consume QName token
                aToken = tokens.elementAt(++i);

                const XMLCh* prefix = XMLUni::fgZeroLenString;
                unsigned int uri = fEmptyNamespaceId;

                if (scopeContext && aToken != -1) {

                    prefix = stringPool->getValueForId(aToken);
                    uri = scopeContext->getNamespaceForPrefix(prefix);
                }

                if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
                    ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager);
                }

                if (isNamespace) {

                    // build step
                    XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager);
                    XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
                    stepsVector->addElement(step);
                    break;
                }

                aToken = tokens.elementAt(++i);
                const XMLCh* localPart = stringPool->getValueForId(aToken);
                QName aQName(prefix, localPart, uri, fMemoryManager);

                // build step
                XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
                XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
                stepsVector->addElement(step);
                firstTokenOfLocationPath = false;
                break;
            }
        case XercesXPath::EXPRTOKEN_PERIOD:
            {
                // build step
                XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
                XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
                stepsVector->addElement(step);

                if (firstTokenOfLocationPath && i+1 < tokenCount) {

                    aToken = tokens.elementAt(i+1);

                    if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH){

                        if (++i == tokenCount - 1) {
                            ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep2, fMemoryManager);
                        }

                        if (i+1 < tokenCount)	{

                            aToken = tokens.elementAt(i+1);

                            if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH) {
                                ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlash, fMemoryManager);
                            }
                        }
                        // build step
                        nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
                        step = new (fMemoryManager) XercesStep(XercesStep::AxisType_DESCENDANT, nodeTest);
                        stepsVector->addElement(step);
                    }
                }
                firstTokenOfLocationPath=false;
                break;
            }
        case XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH:
            {
                ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleForwardSlash, fMemoryManager);
            }
        case XercesXPath::EXPRTOKEN_OPERATOR_SLASH:
            {
                if (i == 0) {
                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlashAtStart, fMemoryManager);
                }

                // keep on truckin'
                if (firstTokenOfLocationPath) {
                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoSelectionOfRoot, fMemoryManager);
                }

                if (i == tokenCount - 1) {
                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager);
                }

                aToken = tokens.elementAt(i+1);
                if(aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION)
                    ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager);

                firstTokenOfLocationPath=false;
                break;
            }
        default:
            firstTokenOfLocationPath=false;
        }
    }

    XMLSize_t stepsSize = stepsVector->size();

    if (stepsSize == 0) {
        if (!fLocationPaths || fLocationPaths->size() == 0) {
            ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_EmptyExpr, fMemoryManager);
        }
        else {
            ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtEnd, fMemoryManager);
        }
    }

    if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF)
    {
        // prepend ./
        XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
        XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
        stepsVector->insertElementAt(step, 0);
    }
    XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector);
    janSteps.orphan();
    bool bFound=false;
    for(XMLSize_t j=0;j<fLocationPaths->size();j++)
        if((*(fLocationPaths->elementAt(j)))==(*newPath))
        {
            bFound=true;
            break;
        }
    if(bFound)
        delete newPath;
    else
        fLocationPaths->addElement(newPath);
}