class XPathParser {

    protected PathExpression parsePathExpr( TokenStream tokens ) {
        boolean relative = true;
        boolean prependDependentOrSelf = false;
        if (tokens.canConsume('/')) {
            if (tokens.canConsume('/')) {
                if (!tokens.hasNext()) {
                    // See http://www.w3.org/XML/2007/qt-errata/xpath20-errata.html#E3
                    throw new ParsingException(tokens.previousPosition(), "'//' is not a valid XPath expression");
                }
                prependDependentOrSelf = true;
            }
            relative = false;
        }
        PathExpression relativeExpr = parseRelativePathExpr(tokens);
        PathExpression result = new PathExpression(relative, relativeExpr.getSteps(), relativeExpr.getOrderBy());
        if (prependDependentOrSelf) {
            result.getSteps().add(0, new DescendantOrSelf());
        }
        return result;
    }

    public  XPathParser( TypeSystem context );

}