XPathParserpublic class XPathParser extends Object Tokenizes and parses XPath expressions. This should really be named
XPathParserImpl, and may be renamed in the future. |
Fields Summary |
---|
public static final String | CONTINUE_AFTER_FATAL_ERROR | private OpMap | m_opsThe XPath to be processed. | transient String | m_tokenThe next token in the pattern. | transient char | m_tokenCharThe first char in m_token, the theory being that this
is an optimization because we won't have to do charAt(0) as
often. | int | m_queueMarkThe position in the token queue is tracked by m_queueMark. | protected static final int | FILTER_MATCH_FAILEDResults from checking FilterExpr syntax | protected static final int | FILTER_MATCH_PRIMARY | protected static final int | FILTER_MATCH_PREDICATES | PrefixResolver | m_namespaceContextThe prefix resolver to map prefixes to namespaces in the OpMap. | private ErrorListener | m_errorListenerThe error listener where syntax errors are to be sent. | SourceLocator | m_sourceLocatorThe source location of the XPath. | private FunctionTable | m_functionTableThe table contains build-in functions and customized functions |
Constructors Summary |
---|
public XPathParser(ErrorListener errorListener, SourceLocator sourceLocator)The parser constructor.
m_errorListener = errorListener;
m_sourceLocator = sourceLocator;
|
Methods Summary |
---|
protected boolean | AbbreviatedNodeTestStep(boolean isLeadingSlashPermitted)AbbreviatedNodeTestStep ::= '@'? NodeTest Predicate
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
int axesType;
// The next blocks guarantee that a MATCH_XXX will be added.
int matchTypePos = -1;
if (tokenIs('@"))
{
axesType = OpCodes.MATCH_ATTRIBUTE;
appendOp(2, axesType);
nextToken();
}
else if (this.lookahead("::", 1))
{
if (tokenIs("attribute"))
{
axesType = OpCodes.MATCH_ATTRIBUTE;
appendOp(2, axesType);
}
else if (tokenIs("child"))
{
matchTypePos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
axesType = OpCodes.MATCH_IMMEDIATE_ANCESTOR;
appendOp(2, axesType);
}
else
{
axesType = -1;
this.error(XPATHErrorResources.ER_AXES_NOT_ALLOWED,
new Object[]{ this.m_token });
}
nextToken();
nextToken();
}
else if (tokenIs('/"))
{
if (!isLeadingSlashPermitted)
{
// "A step was expected in the pattern, but '/' was encountered."
error(XPATHErrorResources.ER_EXPECTED_STEP_PATTERN, null);
}
axesType = OpCodes.MATCH_ANY_ANCESTOR;
appendOp(2, axesType);
nextToken();
}
else
{
matchTypePos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
axesType = OpCodes.MATCH_IMMEDIATE_ANCESTOR;
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);
while (tokenIs('["))
{
Predicate();
}
boolean trailingSlashConsumed;
// For "a//b", where "a" is current step, we need to mark operation of
// current step as "MATCH_ANY_ANCESTOR". Then we'll consume the first
// slash and subsequent step will be treated as a MATCH_IMMEDIATE_ANCESTOR
// (unless it too is followed by '//'.)
//
// %REVIEW% Following is what happens today, but I'm not sure that's
// %REVIEW% correct behaviour. Perhaps no valid case could be constructed
// %REVIEW% where it would matter?
//
// If current step is on the attribute axis (e.g., "@x//b"), we won't
// change the current step, and let following step be marked as
// MATCH_ANY_ANCESTOR on next call instead.
if ((matchTypePos > -1) && tokenIs('/") && lookahead('/", 1))
{
m_ops.setOp(matchTypePos, OpCodes.MATCH_ANY_ANCESTOR);
nextToken();
trailingSlashConsumed = true;
}
else
{
trailingSlashConsumed = false;
}
// Tell how long the entire step is.
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
return trailingSlashConsumed;
| protected int | AdditiveExpr(int addPos)This has to handle construction of the operations so that they are evaluated
in pre-fix order. So, for 9+7-6, instead of |+|9|-|7|6|, this needs to be
evaluated as |-|+|9|7|6|.
AdditiveExpr ::= MultiplicativeExpr
| AdditiveExpr '+' MultiplicativeExpr
| AdditiveExpr '-' MultiplicativeExpr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
if (-1 == addPos)
addPos = opPos;
MultiplicativeExpr(-1);
if (null != m_token)
{
if (tokenIs('+"))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_PLUS);
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = AdditiveExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs('-"))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_MINUS);
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = AdditiveExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
}
return addPos;
| protected void | AndExpr()AndExpr ::= EqualityExpr
| AndExpr 'and' EqualityExpr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
EqualityExpr(-1);
if ((null != m_token) && tokenIs("and"))
{
nextToken();
insertOp(opPos, 2, OpCodes.OP_AND);
AndExpr();
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
}
| protected void | Argument()Argument ::= Expr
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);
| protected int | AxisName()Basis ::= AxisName '::' NodeTest
| AbbreviatedBasis
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;
| protected void | Basis()Basis ::= AxisName '::' NodeTest
| AbbreviatedBasis
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);
| protected void | BooleanExpr()StringExpr ::= Expr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
appendOp(2, OpCodes.OP_BOOL);
Expr();
int opLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos;
if (opLen == 2)
{
error(XPATHErrorResources.ER_BOOLEAN_ARG_NO_LONGER_OPTIONAL, null); //"boolean(...) argument is no longer optional with 19990709 XPath draft.");
}
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH, opLen);
| protected int | EqualityExpr(int addPos)
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
if (-1 == addPos)
addPos = opPos;
RelationalExpr(-1);
if (null != m_token)
{
if (tokenIs('!") && lookahead('=", 1))
{
nextToken();
nextToken();
insertOp(addPos, 2, OpCodes.OP_NOTEQUALS);
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = EqualityExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs('="))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_EQUALS);
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = EqualityExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
}
return addPos;
| protected void | Expr()Expr ::= OrExpr
OrExpr();
| protected int | FilterExpr()FilterExpr ::= PrimaryExpr
| FilterExpr Predicate
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
int filterMatch;
if (PrimaryExpr())
{
if (tokenIs('["))
{
// int locationPathOpPos = opPos;
insertOp(opPos, 2, OpCodes.OP_LOCATIONPATH);
while (tokenIs('["))
{
Predicate();
}
filterMatch = FILTER_MATCH_PREDICATES;
}
else
{
filterMatch = FILTER_MATCH_PRIMARY;
}
}
else
{
filterMatch = FILTER_MATCH_FAILED;
}
return filterMatch;
/*
* if(tokenIs('['))
* {
* Predicate();
* m_ops.m_opMap[opPos + OpMap.MAPINDEX_LENGTH] = m_ops.m_opMap[OpMap.MAPINDEX_LENGTH] - opPos;
* }
*/
| protected boolean | FunctionCall()FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')'
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;
| protected void | IdKeyPattern()IdKeyPattern ::= 'id' '(' Literal ')'
| 'key' '(' Literal ',' Literal ')'
(Also handle doc())
FunctionCall();
| protected void | Literal()The value of the Literal is the sequence of characters inside
the " or ' characters>.
Literal ::= '"' [^"]* '"'
| "'" [^']* "'"
int last = m_token.length() - 1;
char c0 = m_tokenChar;
char cX = m_token.charAt(last);
if (((c0 == '\"") && (cX == '\"")) || ((c0 == '\'") && (cX == '\'")))
{
// Mutate the token to remove the quotes and have the XString object
// already made.
int tokenQueuePos = m_queueMark - 1;
m_ops.m_tokenQueue.setElementAt(null,tokenQueuePos);
Object obj = new XString(m_token.substring(1, last));
m_ops.m_tokenQueue.setElementAt(obj,tokenQueuePos);
// lit = m_token.substring(1, last);
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), tokenQueuePos);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
nextToken();
}
else
{
error(XPATHErrorResources.ER_PATTERN_LITERAL_NEEDS_BE_QUOTED,
new Object[]{ m_token }); //"Pattern literal ("+m_token+") needs to be quoted!");
}
| protected void | LocationPath()LocationPath ::= RelativeLocationPath
| AbsoluteLocationPath
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);
| protected void | LocationPathPattern()LocationPathPattern ::= '/' RelativePathPattern?
| IdKeyPattern (('/' | '//') RelativePathPattern)?
| '//'? RelativePathPattern
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 int | MultiplicativeExpr(int addPos)This has to handle construction of the operations so that they are evaluated
in pre-fix order. So, for 9+7-6, instead of |+|9|-|7|6|, this needs to be
evaluated as |-|+|9|7|6|.
MultiplicativeExpr ::= UnaryExpr
| MultiplicativeExpr MultiplyOperator UnaryExpr
| MultiplicativeExpr 'div' UnaryExpr
| MultiplicativeExpr 'mod' UnaryExpr
| MultiplicativeExpr 'quo' UnaryExpr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
if (-1 == addPos)
addPos = opPos;
UnaryExpr();
if (null != m_token)
{
if (tokenIs('*"))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_MULT);
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = MultiplicativeExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs("div"))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_DIV);
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = MultiplicativeExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs("mod"))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_MOD);
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = MultiplicativeExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs("quo"))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_QUO);
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = MultiplicativeExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
}
return addPos;
| protected void | NCName()NCName ::= (Letter | '_') (NCNameChar)
NCNameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
nextToken();
| protected void | NodeTest(int axesType)NodeTest ::= WildcardName
| NodeType '(' ')'
| 'processing-instruction' '(' Literal ')'
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();
}
| protected void | Number()Number ::= [0-9]+('.'[0-9]+)? | '.'[0-9]+
if (null != m_token)
{
// Mutate the token to remove the quotes and have the XNumber object
// already made.
double num;
try
{
// XPath 1.0 does not support number in exp notation
if ((m_token.indexOf('e") > -1)||(m_token.indexOf('E") > -1))
throw new NumberFormatException();
num = Double.valueOf(m_token).doubleValue();
}
catch (NumberFormatException nfe)
{
num = 0.0; // to shut up compiler.
error(XPATHErrorResources.ER_COULDNOT_BE_FORMATTED_TO_NUMBER,
new Object[]{ m_token }); //m_token+" could not be formatted to a number!");
}
m_ops.m_tokenQueue.setElementAt(new XNumber(num),m_queueMark - 1);
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
nextToken();
}
| protected void | NumberExpr()NumberExpr ::= Expr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
appendOp(2, OpCodes.OP_NUMBER);
Expr();
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
| protected void | OrExpr()OrExpr ::= AndExpr
| OrExpr 'or' AndExpr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
AndExpr();
if ((null != m_token) && tokenIs("or"))
{
nextToken();
insertOp(opPos, 2, OpCodes.OP_OR);
OrExpr();
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
}
| protected void | PathExpr()PathExpr ::= LocationPath
| FilterExpr
| FilterExpr '/' RelativeLocationPath
| FilterExpr '//' RelativeLocationPath
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
int filterExprMatch = FilterExpr();
if (filterExprMatch != FILTER_MATCH_FAILED)
{
// If FilterExpr had Predicates, a OP_LOCATIONPATH opcode would already
// have been inserted.
boolean locationPathStarted = (filterExprMatch==FILTER_MATCH_PREDICATES);
if (tokenIs('/"))
{
nextToken();
if (!locationPathStarted)
{
// int locationPathOpPos = opPos;
insertOp(opPos, 2, OpCodes.OP_LOCATIONPATH);
locationPathStarted = true;
}
if (!RelativeLocationPath())
{
// "Relative location path expected following '/' or '//'"
error(XPATHErrorResources.ER_EXPECTED_REL_LOC_PATH, null);
}
}
// Terminate for safety.
if (locationPathStarted)
{
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);
}
}
else
{
LocationPath();
}
| protected void | Pattern()Pattern ::= LocationPathPattern
| Pattern '|' LocationPathPattern
while (true)
{
LocationPathPattern();
if (tokenIs('|"))
{
nextToken();
}
else
{
break;
}
}
| protected void | Predicate()Predicate ::= '[' PredicateExpr ']'
if (tokenIs('["))
{
nextToken();
PredicateExpr();
consumeExpected(']");
}
| protected void | PredicateExpr()PredicateExpr ::= Expr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
appendOp(2, OpCodes.OP_PREDICATE);
Expr();
// 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 boolean | PrimaryExpr()PrimaryExpr ::= VariableReference
| '(' Expr ')'
| Literal
| Number
| FunctionCall
boolean matchFound;
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
if ((m_tokenChar == '\'") || (m_tokenChar == '""))
{
appendOp(2, OpCodes.OP_LITERAL);
Literal();
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
matchFound = true;
}
else if (m_tokenChar == '$")
{
nextToken(); // consume '$'
appendOp(2, OpCodes.OP_VARIABLE);
QName();
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
matchFound = true;
}
else if (m_tokenChar == '(")
{
nextToken();
appendOp(2, OpCodes.OP_GROUP);
Expr();
consumeExpected(')");
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
matchFound = true;
}
else if ((null != m_token) && ((('." == m_tokenChar) && (m_token.length() > 1) && Character.isDigit(
m_token.charAt(1))) || Character.isDigit(m_tokenChar)))
{
appendOp(2, OpCodes.OP_NUMBERLIT);
Number();
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
matchFound = true;
}
else if (lookahead('(", 1) || (lookahead(':", 1) && lookahead('(", 3)))
{
matchFound = FunctionCall();
}
else
{
matchFound = false;
}
return matchFound;
| protected void | QName()QName ::= (Prefix ':')? LocalPart
Prefix ::= NCName
LocalPart ::= NCName
// Namespace
if(lookahead(':", 1))
{
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
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);
}
// Local name
m_ops.setOp(m_ops.getOp(OpMap.MAPINDEX_LENGTH), m_queueMark - 1);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, m_ops.getOp(OpMap.MAPINDEX_LENGTH) + 1);
nextToken();
| protected int | RelationalExpr(int addPos).
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
if (-1 == addPos)
addPos = opPos;
AdditiveExpr(-1);
if (null != m_token)
{
if (tokenIs('<"))
{
nextToken();
if (tokenIs('="))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_LTE);
}
else
{
insertOp(addPos, 2, OpCodes.OP_LT);
}
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = RelationalExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
else if (tokenIs('>"))
{
nextToken();
if (tokenIs('="))
{
nextToken();
insertOp(addPos, 2, OpCodes.OP_GTE);
}
else
{
insertOp(addPos, 2, OpCodes.OP_GT);
}
int opPlusLeftHandLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH) - addPos;
addPos = RelationalExpr(addPos);
m_ops.setOp(addPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(addPos + opPlusLeftHandLen + 1) + opPlusLeftHandLen);
addPos += 2;
}
}
return addPos;
| protected boolean | RelativeLocationPath()RelativeLocationPath ::= Step
| RelativeLocationPath '/' Step
| AbbreviatedRelativeLocationPath
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;
| protected void | RelativePathPattern()RelativePathPattern ::= StepPattern
| RelativePathPattern '/' StepPattern
| RelativePathPattern '//' StepPattern
// Caller will have consumed any '/' or '//' preceding the
// RelativePathPattern, so let StepPattern know it can't begin with a '/'
boolean trailingSlashConsumed = StepPattern(false);
while (tokenIs('/"))
{
nextToken();
// StepPattern() may consume first slash of pair in "a//b" while
// processing StepPattern "a". On next iteration, let StepPattern know
// that happened, so it doesn't match ill-formed patterns like "a///b".
trailingSlashConsumed = StepPattern(!trailingSlashConsumed);
}
| protected boolean | Step()Step ::= Basis Predicate
| AbbreviatedStep
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;
| protected boolean | StepPattern(boolean isLeadingSlashPermitted)StepPattern ::= AbbreviatedNodeTestStep
return AbbreviatedNodeTestStep(isLeadingSlashPermitted);
| protected void | StringExpr()StringExpr ::= Expr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
appendOp(2, OpCodes.OP_STRING);
Expr();
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
| protected void | UnaryExpr()UnaryExpr ::= UnionExpr
| '-' UnaryExpr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
boolean isNeg = false;
if (m_tokenChar == '-")
{
nextToken();
appendOp(2, OpCodes.OP_NEG);
isNeg = true;
}
UnionExpr();
if (isNeg)
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
| protected void | UnionExpr()The context of the right hand side expressions is the context of the
left hand side expression. The results of the right hand side expressions
are node sets. The result of the left hand side UnionExpr is the union
of the results of the right hand side expressions.
UnionExpr ::= PathExpr
| UnionExpr '|' PathExpr
int opPos = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
boolean continueOrLoop = true;
boolean foundUnion = false;
do
{
PathExpr();
if (tokenIs('|"))
{
if (false == foundUnion)
{
foundUnion = true;
insertOp(opPos, 2, OpCodes.OP_UNION);
}
nextToken();
}
else
{
break;
}
// this.m_testForDocOrder = true;
}
while (continueOrLoop);
m_ops.setOp(opPos + OpMap.MAPINDEX_LENGTH,
m_ops.getOp(OpMap.MAPINDEX_LENGTH) - opPos);
| void | appendOp(int length, int op)Insert room for operation. This WILL set
the length value of the operation, and will update
the length value for the total expression.
int totalLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
m_ops.setOp(totalLen, op);
m_ops.setOp(totalLen + OpMap.MAPINDEX_LENGTH, length);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, totalLen + length);
| private void | assertion(boolean b, java.lang.String msg)Notify the user of an assertion error, and probably throw an
exception.
if (!b)
{
String fMsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
new Object[]{ msg });
throw new RuntimeException(fMsg);
}
| private final void | consumeExpected(java.lang.String expected)Consume an expected token, throwing an exception if it
isn't there.
if (tokenIs(expected))
{
nextToken();
}
else
{
error(XPATHErrorResources.ER_EXPECTED_BUT_FOUND, new Object[]{ expected,
m_token }); //"Expected "+expected+", but found: "+m_token);
// Patch for Christina's gripe. She wants her errorHandler to return from
// this error and continue trying to parse, rather than throwing an exception.
// Without the patch, that put us into an endless loop.
throw new XPathProcessorException(CONTINUE_AFTER_FATAL_ERROR);
}
| private final void | consumeExpected(char expected)Consume an expected token, throwing an exception if it
isn't there.
if (tokenIs(expected))
{
nextToken();
}
else
{
error(XPATHErrorResources.ER_EXPECTED_BUT_FOUND,
new Object[]{ String.valueOf(expected),
m_token }); //"Expected "+expected+", but found: "+m_token);
// Patch for Christina's gripe. She wants her errorHandler to return from
// this error and continue trying to parse, rather than throwing an exception.
// Without the patch, that put us into an endless loop.
throw new XPathProcessorException(CONTINUE_AFTER_FATAL_ERROR);
}
| protected java.lang.String | dumpRemainingTokenQueue()Dump the remaining token queue.
Thanks to Craig for this.
int q = m_queueMark;
String returnMsg;
if (q < m_ops.getTokenQueueSize())
{
String msg = "\n Remaining tokens: (";
while (q < m_ops.getTokenQueueSize())
{
String t = (String) m_ops.m_tokenQueue.elementAt(q++);
msg += (" '" + t + "'");
}
returnMsg = msg + ")";
}
else
{
returnMsg = "";
}
return returnMsg;
| void | error(java.lang.String msg, java.lang.Object[] args)Notify the user of an error, and probably throw an
exception.
String fmsg = XSLMessages.createXPATHMessage(msg, args);
ErrorListener ehandler = this.getErrorListener();
TransformerException te = new TransformerException(fmsg, m_sourceLocator);
if (null != ehandler)
{
// TO DO: Need to get stylesheet Locator from here.
ehandler.fatalError(te);
}
else
{
// System.err.println(fmsg);
throw te;
}
| void | errorForDOM3(java.lang.String msg, java.lang.Object[] args)This method is added to support DOM 3 XPath API.
This method is exactly like error(String, Object[]); except that
the underlying TransformerException is
XpathStylesheetDOM3Exception (which extends TransformerException).
So older XPath code in Xalan is not affected by this. To older XPath code
the behavior of whether error() or errorForDOM3() is called because it is
always catching TransformerException objects and is oblivious to
the new subclass of XPathStylesheetDOM3Exception. Older XPath code
runs as before.
However, newer DOM3 XPath code upon catching a TransformerException can
can check if the exception is an instance of XPathStylesheetDOM3Exception
and take appropriate action.
String fmsg = XSLMessages.createXPATHMessage(msg, args);
ErrorListener ehandler = this.getErrorListener();
TransformerException te = new XPathStylesheetDOM3Exception(fmsg, m_sourceLocator);
if (null != ehandler)
{
// TO DO: Need to get stylesheet Locator from here.
ehandler.fatalError(te);
}
else
{
// System.err.println(fmsg);
throw te;
}
| public javax.xml.transform.ErrorListener | getErrorListener()Return the current error listener.
return m_errorListener;
| final int | getFunctionToken(java.lang.String key)Given a string, return the corresponding function token.
int tok;
Object id;
try
{
// These are nodetests, xpathparser treats them as functions when parsing
// a FilterExpr.
id = Keywords.lookupNodeTest(key);
if (null == id) id = m_functionTable.getFunctionID(key);
tok = ((Integer) id).intValue();
}
catch (NullPointerException npe)
{
tok = -1;
}
catch (ClassCastException cce)
{
tok = -1;
}
return tok;
| private final java.lang.String | getTokenRelative(int i)Retrieve a token relative to the current token.
String tok;
int relative = m_queueMark + i;
if ((relative > 0) && (relative < m_ops.getTokenQueueSize()))
{
tok = (String) m_ops.m_tokenQueue.elementAt(relative);
}
else
{
tok = null;
}
return tok;
| public void | initMatchPattern(com.sun.org.apache.xpath.internal.compiler.Compiler compiler, java.lang.String expression, com.sun.org.apache.xml.internal.utils.PrefixResolver namespaceContext)Given an string, init an XPath object for pattern matches,
in order that a parse doesn't
have to be done each time the expression is evaluated.
m_ops = compiler;
m_namespaceContext = namespaceContext;
m_functionTable = compiler.getFunctionTable();
Lexer lexer = new Lexer(compiler, namespaceContext, this);
lexer.tokenize(expression);
m_ops.setOp(0, OpCodes.OP_MATCHPATTERN);
m_ops.setOp(OpMap.MAPINDEX_LENGTH, 2);
nextToken();
Pattern();
if (null != m_token)
{
String extraTokens = "";
while (null != m_token)
{
extraTokens += "'" + m_token + "'";
nextToken();
if (null != m_token)
extraTokens += ", ";
}
error(XPATHErrorResources.ER_EXTRA_ILLEGAL_TOKENS,
new Object[]{ extraTokens }); //"Extra illegal tokens: "+extraTokens);
}
// 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.shrink();
| public void | initXPath(com.sun.org.apache.xpath.internal.compiler.Compiler compiler, java.lang.String expression, com.sun.org.apache.xml.internal.utils.PrefixResolver namespaceContext)Given an string, init an XPath object for selections,
in order that a parse doesn't
have to be done each time the expression is evaluated.
m_ops = compiler;
m_namespaceContext = namespaceContext;
m_functionTable = compiler.getFunctionTable();
Lexer lexer = new Lexer(compiler, namespaceContext, this);
lexer.tokenize(expression);
m_ops.setOp(0,OpCodes.OP_XPATH);
m_ops.setOp(OpMap.MAPINDEX_LENGTH,2);
// Patch for Christine's gripe. She wants her errorHandler to return from
// a fatal error and continue trying to parse, rather than throwing an exception.
// Without the patch, that put us into an endless loop.
//
// %REVIEW% Is there a better way of doing this?
// %REVIEW% Are there any other cases which need the safety net?
// (and if so do we care right now, or should we rewrite the XPath
// grammar engine and can fix it at that time?)
try {
nextToken();
Expr();
if (null != m_token)
{
String extraTokens = "";
while (null != m_token)
{
extraTokens += "'" + m_token + "'";
nextToken();
if (null != m_token)
extraTokens += ", ";
}
error(XPATHErrorResources.ER_EXTRA_ILLEGAL_TOKENS,
new Object[]{ extraTokens }); //"Extra illegal tokens: "+extraTokens);
}
}
catch (com.sun.org.apache.xpath.internal.XPathProcessorException e)
{
if(CONTINUE_AFTER_FATAL_ERROR.equals(e.getMessage()))
{
// What I _want_ to do is null out this XPath.
// I doubt this has the desired effect, but I'm not sure what else to do.
// %REVIEW%!!!
initXPath(compiler, "/..", namespaceContext);
}
else
throw e;
}
compiler.shrink();
| void | insertOp(int pos, int length, int op)Insert room for operation. This will NOT set
the length value of the operation, but will update
the length value for the total expression.
int totalLen = m_ops.getOp(OpMap.MAPINDEX_LENGTH);
for (int i = totalLen - 1; i >= pos; i--)
{
m_ops.setOp(i + length, m_ops.getOp(i));
}
m_ops.setOp(pos,op);
m_ops.setOp(OpMap.MAPINDEX_LENGTH,totalLen + length);
| private final boolean | lookahead(java.lang.String s, int n)Look ahead of the current token in order to
make a branching decision.
boolean isToken;
if ((m_queueMark + n) <= m_ops.getTokenQueueSize())
{
String lookahead = (String) m_ops.m_tokenQueue.elementAt(m_queueMark + (n - 1));
isToken = (lookahead != null) ? lookahead.equals(s) : (s == null);
}
else
{
isToken = (null == s);
}
return isToken;
| final boolean | lookahead(char c, int n)Look ahead of the current token in order to
make a branching decision.
int pos = (m_queueMark + n);
boolean b;
if ((pos <= m_ops.getTokenQueueSize()) && (pos > 0)
&& (m_ops.getTokenQueueSize() != 0))
{
String tok = ((String) m_ops.m_tokenQueue.elementAt(pos - 1));
b = (tok.length() == 1) ? (tok.charAt(0) == c) : false;
}
else
{
b = false;
}
return b;
| private final boolean | lookbehind(char c, int n)Look behind the first character of the current token in order to
make a branching decision.
boolean isToken;
int lookBehindPos = m_queueMark - (n + 1);
if (lookBehindPos >= 0)
{
String lookbehind = (String) m_ops.m_tokenQueue.elementAt(lookBehindPos);
if (lookbehind.length() == 1)
{
char c0 = (lookbehind == null) ? '|" : lookbehind.charAt(0);
isToken = (c0 == '|") ? false : (c0 == c);
}
else
{
isToken = false;
}
}
else
{
isToken = false;
}
return isToken;
| private final boolean | lookbehindHasToken(int n)look behind the current token in order to
see if there is a useable token.
boolean hasToken;
if ((m_queueMark - n) > 0)
{
String lookbehind = (String) m_ops.m_tokenQueue.elementAt(m_queueMark - (n - 1));
char c0 = (lookbehind == null) ? '|" : lookbehind.charAt(0);
hasToken = (c0 == '|") ? false : true;
}
else
{
hasToken = false;
}
return hasToken;
| private final void | nextToken()Retrieve the next token from the command and
store it in m_token string.
if (m_queueMark < m_ops.getTokenQueueSize())
{
m_token = (String) m_ops.m_tokenQueue.elementAt(m_queueMark++);
m_tokenChar = m_token.charAt(0);
}
else
{
m_token = null;
m_tokenChar = 0;
}
| private final void | prevToken()Retrieve the previous token from the command and
store it in m_token string.
if (m_queueMark > 0)
{
m_queueMark--;
m_token = (String) m_ops.m_tokenQueue.elementAt(m_queueMark);
m_tokenChar = m_token.charAt(0);
}
else
{
m_token = null;
m_tokenChar = 0;
}
| public void | setErrorHandler(javax.xml.transform.ErrorListener handler)Allow an application to register an error event handler, where syntax
errors will be sent. If the error listener is not set, syntax errors
will be sent to System.err.
m_errorListener = handler;
| final boolean | tokenIs(java.lang.String s)Check whether m_token matches the target string.
return (m_token != null) ? (m_token.equals(s)) : (s == null);
| final boolean | tokenIs(char c)Check whether m_tokenChar==c.
return (m_token != null) ? (m_tokenChar == c) : false;
| void | warn(java.lang.String msg, java.lang.Object[] args)Warn the user of a problem.
String fmsg = XSLMessages.createXPATHWarning(msg, args);
ErrorListener ehandler = this.getErrorListener();
if (null != ehandler)
{
// TO DO: Need to get stylesheet Locator from here.
ehandler.warning(new TransformerException(fmsg, m_sourceLocator));
}
else
{
// Should never happen.
System.err.println(fmsg);
}
|
|