📄 xpathparser.java
字号:
} else if (lookahead('(', 1) || (lookahead(':', 1) && lookahead('(', 3))) { matchFound = FunctionCall(); } else { matchFound = false; } return matchFound; } /** * * Argument ::= Expr * * * @throws javax.xml.transform.TransformerException */ protected void Argument() throws javax.xml.transform.TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); appendOp(2, OpCodes.OP_ARGUMENT); Expr(); m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); } /** * * FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')' * * @return true if, and only if, a FunctionCall was matched * * @throws javax.xml.transform.TransformerException */ protected boolean FunctionCall() throws javax.xml.transform.TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); if (lookahead(':', 1)) { appendOp(4, OpCodes.OP_EXTFUNCTION); m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, m_queueMark - 1); nextToken(); consumeExpected(':'); m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 2, m_queueMark - 1); nextToken(); } else { int funcTok = getFunctionToken(m_token); if (-1 == funcTok) { error(XPATHErrorResources.ER_COULDNOT_FIND_FUNCTION, new Object[]{ m_token }); //"Could not find function: "+m_token+"()"); } switch (funcTok) { case OpCodes.NODETYPE_PI : case OpCodes.NODETYPE_COMMENT : case OpCodes.NODETYPE_TEXT : case OpCodes.NODETYPE_NODE : // Node type tests look like function calls, but they're not return false; default : appendOp(3, OpCodes.OP_FUNCTION); m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, funcTok); } nextToken(); } consumeExpected('('); while (!tokenIs(')') && m_token != null) { if (tokenIs(',')) { error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_PRECEDING_ARG, null); //"Found ',' but no preceding argument!"); } Argument(); if (!tokenIs(')')) { consumeExpected(','); if (tokenIs(')')) { error(XPATHErrorResources.ER_FOUND_COMMA_BUT_NO_FOLLOWING_ARG, null); //"Found ',' but no following argument!"); } } } consumeExpected(')'); // 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); return true; } // ============= GRAMMAR FUNCTIONS ================= /** * * LocationPath ::= RelativeLocationPath * | AbsoluteLocationPath * * * @throws javax.xml.transform.TransformerException */ protected void LocationPath() throws javax.xml.transform.TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); // int locationPathOpPos = opPos; appendOp(2, OpCodes.OP_LOCATIONPATH); boolean seenSlash = tokenIs('/'); if (seenSlash) { appendOp(4, OpCodes.FROM_ROOT); // 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 if (m_token == null) { error(XPATHErrorResources.ER_EXPECTED_LOC_PATH_AT_END_EXPR, null); } if (m_token != null) { if (!RelativeLocationPath() && !seenSlash) { // Neither a '/' nor a RelativeLocationPath - i.e., matched nothing // "Location path expected, but found "+m_token+" was encountered." error(XPATHErrorResources.ER_EXPECTED_LOC_PATH, new Object [] {m_token}); } } // 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); } /** * * RelativeLocationPath ::= Step * | RelativeLocationPath '/' Step * | AbbreviatedRelativeLocationPath * * @returns true if, and only if, a RelativeLocationPath was matched * * @throws javax.xml.transform.TransformerException */ protected boolean RelativeLocationPath() throws javax.xml.transform.TransformerException { if (!Step()) { return false; } while (tokenIs('/')) { nextToken(); if (!Step()) { // RelativeLocationPath can't end with a trailing '/' // "Location step expected following '/' or '//'" error(XPATHErrorResources.ER_EXPECTED_LOC_STEP, null); } } return true; } /** * * Step ::= Basis Predicate * | AbbreviatedStep * * @returns false if step was empty (or only a '/'); true, otherwise * * @throws javax.xml.transform.TransformerException */ protected boolean Step() throws javax.xml.transform.TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); boolean doubleSlash = tokenIs('/'); // At most a single '/' before each Step is consumed by caller; if the // first thing is a '/', that means we had '//' and the Step must not // be empty. if (doubleSlash) { nextToken(); appendOp(2, OpCodes.FROM_DESCENDANTS_OR_SELF); // Have to fix up for patterns such as '//@foo' or '//attribute::foo', // which translate to 'descendant-or-self::node()/attribute::foo'. // notice I leave the '/' on the queue, so the next will be processed // by a regular step pattern. // Make room for telling how long the step is without the predicate m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.NODETYPE_NODE); m_ops.setOp(OpMap.MAPINDEX_LENGTH,m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); // Tell how long the step is without the predicate m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); // Tell how long the step is with the predicate m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); } if (tokenIs(".")) { nextToken(); if (tokenIs('[')) { error(XPATHErrorResources.ER_PREDICATE_ILLEGAL_SYNTAX, null); //"'..[predicate]' or '.[predicate]' is illegal syntax. Use 'self::node()[predicate]' instead."); } appendOp(4, OpCodes.FROM_SELF); // 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_NODE); } else if (tokenIs("..")) { nextToken(); appendOp(4, OpCodes.FROM_PARENT); // 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_NODE); } // There is probably a better way to test for this // transition... but it gets real hairy if you try // to do it in basis(). else if (tokenIs('*') || tokenIs('@') || tokenIs('_') || (m_token!= null && Character.isLetter(m_token.charAt(0)))) { Basis(); while (tokenIs('[')) { Predicate(); } // Tell how long the entire step is. m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); } else { // No Step matched - that's an error if previous thing was a '//' if (doubleSlash) { // "Location step expected following '/' or '//'" error(XPATHErrorResources.ER_EXPECTED_LOC_STEP, null); } return false; } return true; } /** * * Basis ::= AxisName '::' NodeTest * | AbbreviatedBasis * * @throws javax.xml.transform.TransformerException */ protected void Basis() throws javax.xml.transform.TransformerException { int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH); int axesType; // The next blocks guarantee that a FROM_XXX will be added. if (lookahead("::", 1)) { axesType = AxisName(); nextToken(); nextToken(); } else if (tokenIs('@')) { axesType = OpCodes.FROM_ATTRIBUTES; appendOp(2, axesType); nextToken(); } else { axesType = OpCodes.FROM_CHILDREN; appendOp(2, axesType); } // Make room for telling how long the step is without the predicate m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); NodeTest(axesType); // Tell how long the step is without the predicate m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH + 1, m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos); } /** * * Basis ::= AxisName '::' NodeTest * | AbbreviatedBasis * * @return FROM_XXX axes type, found in {@link com.sun.org.apache.xpath.internal.compiler.Keywords}. * * @throws javax.xml.transform.TransformerException */ protected int AxisName() throws javax.xml.transform.TransformerException { Object val = Keywords.getAxisName(m_token); if (null == val) { error(XPATHErrorResources.ER_ILLEGAL_AXIS_NAME, new Object[]{ m_token }); //"illegal axis name: "+m_token); } int axesType = ((Integer) val).intValue(); appendOp(2, axesType); return axesType; } /** * * NodeTest ::= WildcardName * | NodeType '(' ')' * | 'processing-instruction' '(' Literal ')' * * @param axesType FROM_XXX axes type, found in {@link com.sun.org.apache.xpath.internal.compiler.Keywords}. * * @throws javax.xml.transform.TransformerException */ protected void NodeTest(int axesType) throws javax.xml.transform.TransformerException { if (lookahead('(', 1)) { Object nodeTestOp = Keywords.getNodeType(m_token); if (null == nodeTestOp) { error(XPATHErrorResources.ER_UNKNOWN_NODETYPE, new Object[]{ m_token }); //"Unknown nodetype: "+m_token); } else { nextToken(); int nt = ((Integer) nodeTestOp).intValue(); m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), nt); m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); consumeExpected('('); if (OpCodes.NODETYPE_PI == nt) { if (!tokenIs(')')) { Literal(); } } consumeExpected(')'); } } else { // Assume name of attribute or element. m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.NODENAME); m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); if (lookahead(':', 1)) { if (tokenIs('*')) { m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD); } else { m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); // Minimalist check for an NCName - just check first character // to distinguish from other possible tokens if (!Character.isLetter(m_tokenChar) && !tokenIs('_')) { // "Node test that matches either NCName:* or QName was expected." error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null); } } nextToken(); consumeExpected(':'); } else { m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.EMPTY); } m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); if (tokenIs('*')) { m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), OpCodes.ELEMWILDCARD); } else { m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1); // Minimalist check for an NCName - just check first character // to distinguish from other possible tokens if (!Character.isLetter(m_tokenChar) && !tokenIs('_')) { // "Node test that matches either NCName:* or QName was expected." error(XPATHErrorResources.ER_EXPECTED_NODE_TEST, null); } } m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1); nextToken(); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -