nsresult txPatternParser::createStepPattern(txExprLexer& aLexer,
                                            txIParseContext* aContext,
                                            txPattern*& aPattern)
{
    nsresult rv = NS_OK;
    bool isAttr = false;
    Token* tok = aLexer.peek();
    if (tok->mType == Token::AXIS_IDENTIFIER) {
        if (TX_StringEqualsAtom(tok->Value(), nsGkAtoms::attribute)) {
            isAttr = true;
        }
        else if (!TX_StringEqualsAtom(tok->Value(), nsGkAtoms::child)) {
            // all done already for CHILD_AXIS, for all others
            // XXX report unexpected axis error
            return NS_ERROR_XPATH_PARSE_FAILURE;
        }
        aLexer.nextToken();
    }
    else if (tok->mType == Token::AT_SIGN) {
        aLexer.nextToken();
        isAttr = true;
    }

    txNodeTest* nodeTest;
    if (aLexer.peek()->mType == Token::CNAME) {
        tok = aLexer.nextToken();

        // resolve QName
        RefPtr<nsAtom> prefix, lName;
        int32_t nspace;
        rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
                          getter_AddRefs(lName), nspace, true);
        if (NS_FAILED(rv)) {
            // XXX error report namespace resolve failed
            return rv;
        }

        uint16_t nodeType = isAttr ?
                            (uint16_t)txXPathNodeType::ATTRIBUTE_NODE :
                            (uint16_t)txXPathNodeType::ELEMENT_NODE;
        nodeTest = new txNameTest(prefix, lName, nspace, nodeType);
    }
    else {
        rv = createNodeTypeTest(aLexer, &nodeTest);
        NS_ENSURE_SUCCESS(rv, rv);
    }

    nsAutoPtr<txStepPattern> step(new txStepPattern(nodeTest, isAttr));
    rv = parsePredicates(step, aLexer, aContext);
    NS_ENSURE_SUCCESS(rv, rv);

    aPattern = step.forget();

    return NS_OK;
}
nsresult txPatternParser::createStepPattern(txExprLexer& aLexer,
                                            txIParseContext* aContext,
                                            txPattern*& aPattern)
{
    nsresult rv = NS_OK;
    MBool isAttr = MB_FALSE;
    Token* tok = aLexer.peek();
    if (tok->mType == Token::AXIS_IDENTIFIER) {
        if (TX_StringEqualsAtom(tok->Value(), txXPathAtoms::attribute)) {
            isAttr = MB_TRUE;
        }
        else if (!TX_StringEqualsAtom(tok->Value(), txXPathAtoms::child)) {
            // all done already for CHILD_AXIS, for all others
            // XXX report unexpected axis error
            return NS_ERROR_XPATH_PARSE_FAILURE;
        }
        aLexer.nextToken();
    }
    else if (tok->mType == Token::AT_SIGN) {
        aLexer.nextToken();
        isAttr = MB_TRUE;
    }
    tok = aLexer.nextToken();

    txNodeTest* nodeTest;
    if (tok->mType == Token::CNAME) {
        // resolve QName
        nsCOMPtr<nsIAtom> prefix, lName;
        PRInt32 nspace;
        rv = resolveQName(tok->Value(), getter_AddRefs(prefix), aContext,
                          getter_AddRefs(lName), nspace, PR_TRUE);
        if (NS_FAILED(rv)) {
            // XXX error report namespace resolve failed
            return rv;
        }

        PRUint16 nodeType = isAttr ?
                            (PRUint16)txXPathNodeType::ATTRIBUTE_NODE :
                            (PRUint16)txXPathNodeType::ELEMENT_NODE;
        nodeTest = new txNameTest(prefix, lName, nspace, nodeType);
        if (!nodeTest) {
            return NS_ERROR_OUT_OF_MEMORY;
        }
    }
    else {
        aLexer.pushBack();
        rv = createNodeTypeTest(aLexer, &nodeTest);
        NS_ENSURE_SUCCESS(rv, rv);
    }

    nsAutoPtr<txStepPattern> step(new txStepPattern(nodeTest, isAttr));
    if (!step) {
        delete nodeTest;
        return NS_ERROR_OUT_OF_MEMORY;
    }

    rv = parsePredicates(step, aLexer, aContext);
    NS_ENSURE_SUCCESS(rv, rv);

    aPattern = step.forget();

    return NS_OK;
}
Example #3
0
nsresult
txExprParser::createLocationStep(txExprLexer& lexer, txIParseContext* aContext,
                                 Expr** aExpr)
{
    *aExpr = nullptr;

    //-- child axis is default
    LocationStep::LocationStepType axisIdentifier = LocationStep::CHILD_AXIS;
    nsAutoPtr<txNodeTest> nodeTest;

    //-- get Axis Identifier or AbbreviatedStep, if present
    Token* tok = lexer.peek();
    switch (tok->mType) {
        case Token::AXIS_IDENTIFIER:
        {
            //-- eat token
            lexer.nextToken();
            nsCOMPtr<nsIAtom> axis = do_GetAtom(tok->Value());
            if (axis == nsGkAtoms::ancestor) {
                axisIdentifier = LocationStep::ANCESTOR_AXIS;
            }
            else if (axis == nsGkAtoms::ancestorOrSelf) {
                axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS;
            }
            else if (axis == nsGkAtoms::attribute) {
                axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
            }
            else if (axis == nsGkAtoms::child) {
                axisIdentifier = LocationStep::CHILD_AXIS;
            }
            else if (axis == nsGkAtoms::descendant) {
                axisIdentifier = LocationStep::DESCENDANT_AXIS;
            }
            else if (axis == nsGkAtoms::descendantOrSelf) {
                axisIdentifier = LocationStep::DESCENDANT_OR_SELF_AXIS;
            }
            else if (axis == nsGkAtoms::following) {
                axisIdentifier = LocationStep::FOLLOWING_AXIS;
            }
            else if (axis == nsGkAtoms::followingSibling) {
                axisIdentifier = LocationStep::FOLLOWING_SIBLING_AXIS;
            }
            else if (axis == nsGkAtoms::_namespace) {
                axisIdentifier = LocationStep::NAMESPACE_AXIS;
            }
            else if (axis == nsGkAtoms::parent) {
                axisIdentifier = LocationStep::PARENT_AXIS;
            }
            else if (axis == nsGkAtoms::preceding) {
                axisIdentifier = LocationStep::PRECEDING_AXIS;
            }
            else if (axis == nsGkAtoms::precedingSibling) {
                axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
            }
            else if (axis == nsGkAtoms::self) {
                axisIdentifier = LocationStep::SELF_AXIS;
            }
            else {
                return NS_ERROR_XPATH_INVALID_AXIS;
            }
            break;
        }
        case Token::AT_SIGN:
            //-- eat token
            lexer.nextToken();
            axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
            break;
        case Token::PARENT_NODE :
            //-- eat token
            lexer.nextToken();
            axisIdentifier = LocationStep::PARENT_AXIS;
            nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
            break;
        case Token::SELF_NODE :
            //-- eat token
            lexer.nextToken();
            axisIdentifier = LocationStep::SELF_AXIS;
            nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
            break;
        default:
            break;
    }

    //-- get NodeTest unless an AbbreviatedStep was found
    nsresult rv = NS_OK;
    if (!nodeTest) {
        tok = lexer.peek();

        if (tok->mType == Token::CNAME) {
            lexer.nextToken();
            // resolve QName
            nsCOMPtr<nsIAtom> prefix, lName;
            int32_t nspace;
            rv = resolveQName(tok->Value(), getter_AddRefs(prefix),
                              aContext, getter_AddRefs(lName),
                              nspace, true);
            NS_ENSURE_SUCCESS(rv, rv);

            nodeTest =
              new txNameTest(prefix, lName, nspace,
                             axisIdentifier == LocationStep::ATTRIBUTE_AXIS ?
                             static_cast<uint16_t>(txXPathNodeType::ATTRIBUTE_NODE) :
                             static_cast<uint16_t>(txXPathNodeType::ELEMENT_NODE));
        }
        else {
            rv = createNodeTypeTest(lexer, getter_Transfers(nodeTest));
            NS_ENSURE_SUCCESS(rv, rv);
        }
    }
    
    nsAutoPtr<LocationStep> lstep(new LocationStep(nodeTest, axisIdentifier));

    nodeTest.forget();

    //-- handle predicates
    rv = parsePredicates(lstep, lexer, aContext);
    NS_ENSURE_SUCCESS(rv, rv);

    *aExpr = lstep.forget();
    return NS_OK;
}