--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/xpath.cup Thu Apr 12 08:38:26 2012 -0700
@@ -0,0 +1,1116 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * $Id: xpath.cup,v 1.51 2004/12/15 17:35:39 jycli Exp $
+ */
+
+/*
+ * @author Jacek Ambroziak
+ * @author Santiago Pericas-Geertsen
+ * @author Morten Jorgensen
+ * @author G. Todd Miller
+ */
+
+package com.sun.org.apache.xalan.internal.xsltc.compiler;
+
+import java.util.Stack;
+import java.util.Vector;
+import java.io.StringReader;
+import com.sun.java_cup.internal.runtime.*;
+
+import com.sun.org.apache.xml.internal.dtm.DTM;
+import com.sun.org.apache.xalan.internal.xsltc.DOM;
+import com.sun.org.apache.xml.internal.dtm.Axis;
+import com.sun.org.apache.xalan.internal.xsltc.runtime.Operators;
+import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
+
+parser code {:
+ /**
+ * Used by function calls with no args.
+ */
+ static public final Vector EmptyArgs = new Vector(0);
+
+ /**
+ * Reference to non-existing variable.
+ */
+ static public final VariableRef DummyVarRef = null;
+
+ /**
+ * Reference to the Parser class.
+ */
+ private Parser _parser;
+ private XSLTC _xsltc;
+
+ /**
+ * String representation of the expression being parsed.
+ */
+ private String _expression;
+
+ /**
+ * Line number where this expression/pattern was declared.
+ */
+ private int _lineNumber = 0;
+
+ /**
+ * Reference to the symbol table.
+ */
+ public SymbolTable _symbolTable;
+
+ public XPathParser(Parser parser) {
+ _parser = parser;
+ _xsltc = parser.getXSLTC();
+ _symbolTable = parser.getSymbolTable();
+ }
+
+ public int getLineNumber() {
+ return _lineNumber;
+ }
+
+ public QName getQNameIgnoreDefaultNs(String name) {
+ return _parser.getQNameIgnoreDefaultNs(name);
+ }
+
+ public QName getQName(String namespace, String prefix, String localname) {
+ return _parser.getQName(namespace, prefix, localname);
+ }
+
+ public void setMultiDocument(boolean flag) {
+ _xsltc.setMultiDocument(flag);
+ }
+
+ public void setCallsNodeset(boolean flag) {
+ _xsltc.setCallsNodeset(flag);
+ }
+
+ public void setHasIdCall(boolean flag) {
+ _xsltc.setHasIdCall(flag);
+ }
+
+
+ /**
+ * This method is similar to findNodeType(int, Object) except that it
+ * creates a StepPattern instead of just returning a node type. It also
+ * differs in the way it handles "{uri}:*" and "{uri}:@*". The last two
+ * patterns are expanded as "*[namespace-uri() = 'uri']" and
+ * "@*[namespace-uri() = 'uri']", respectively. This expansion considerably
+ * simplifies the grouping of patterns in the Mode class. For this
+ * expansion to be correct, the priority of the pattern/template must be
+ * set to -0.25 (when no other predicates are present).
+ */
+ public StepPattern createStepPattern(int axis, Object test, Vector predicates) {
+ int nodeType;
+
+ if (test == null) { // "*"
+ nodeType = (axis == Axis.ATTRIBUTE) ? NodeTest.ATTRIBUTE :
+ (axis == Axis.NAMESPACE) ? -1 : NodeTest.ELEMENT;
+
+ return new StepPattern(axis, nodeType, predicates);
+ }
+ else if (test instanceof Integer) {
+ nodeType = ((Integer) test).intValue();
+
+ return new StepPattern(axis, nodeType, predicates);
+ }
+ else {
+ QName name = (QName)test;
+ boolean setPriority = false;
+
+ if (axis == Axis.NAMESPACE) {
+ nodeType = (name.toString().equals("*")) ? -1
+ : _xsltc.registerNamespacePrefix(name);;
+ }
+ else {
+ final String uri = name.getNamespace();
+ final String local = name.getLocalPart();
+ final QName namespace_uri =
+ _parser.getQNameIgnoreDefaultNs("namespace-uri");
+
+ // Expand {uri}:* to *[namespace-uri() = 'uri'] - same for @*
+ if (uri != null && (local.equals("*") || local.equals("@*"))) {
+ if (predicates == null) {
+ predicates = new Vector(2);
+ }
+
+ // Priority is set by hand if no other predicates exist
+ setPriority = (predicates.size() == 0);
+
+ predicates.add(
+ new Predicate(
+ new EqualityExpr(Operators.EQ,
+ new NamespaceUriCall(namespace_uri),
+ new LiteralExpr(uri))));
+ }
+
+ if (local.equals("*")) {
+ nodeType = (axis == Axis.ATTRIBUTE) ? NodeTest.ATTRIBUTE
+ : NodeTest.ELEMENT;
+ }
+ else if (local.equals("@*")) {
+ nodeType = NodeTest.ATTRIBUTE;
+ }
+ else {
+ nodeType = (axis == Axis.ATTRIBUTE) ? _xsltc.registerAttribute(name)
+ : _xsltc.registerElement(name);
+ }
+ }
+
+ final StepPattern result = new StepPattern(axis, nodeType, predicates);
+
+ // Set priority for case prefix:* and prefix:@* (no predicates)
+ if (setPriority) {
+ result.setPriority(-0.25);
+ }
+
+ return result;
+ }
+ }
+
+ public int findNodeType(int axis, Object test) {
+ if (test == null) { // *
+ return (axis == Axis.ATTRIBUTE) ?
+ NodeTest.ATTRIBUTE :
+ (axis == Axis.NAMESPACE) ? -1 : NodeTest.ELEMENT;
+ }
+ else if (test instanceof Integer) {
+ return ((Integer)test).intValue();
+ }
+ else {
+ QName name = (QName)test;
+
+ if (axis == Axis.NAMESPACE) {
+ return (name.toString().equals("*")) ? -1
+ : _xsltc.registerNamespacePrefix(name);
+ }
+
+ if (name.getNamespace() == null) {
+ final String local = name.getLocalPart();
+
+ if (local.equals("*")) {
+ return (axis == Axis.ATTRIBUTE) ? NodeTest.ATTRIBUTE
+ : NodeTest.ELEMENT;
+ }
+ else if (local.equals("@*")) {
+ return NodeTest.ATTRIBUTE;
+ }
+ }
+
+ return (axis == Axis.ATTRIBUTE) ? _xsltc.registerAttribute(name)
+ : _xsltc.registerElement(name);
+ }
+ }
+
+ /**
+ * Parse the expression passed to the current scanner. If this
+ * expression contains references to local variables and it will be
+ * compiled in an external module (not in the main class) request
+ * the current template to create a new variable stack frame.
+ *
+ * @param lineNumber Line where the current expression is defined.
+ * @param external Set to <tt>true</tt> if this expression is
+ * compiled in a separate module.
+ *
+ */
+ public Symbol parse(String expression, int lineNumber) throws Exception {
+ try {
+ _expression = expression;
+ _lineNumber = lineNumber;
+ return super.parse();
+ }
+ catch (IllegalCharException e) {
+ ErrorMsg err = new ErrorMsg(ErrorMsg.ILLEGAL_CHAR_ERR,
+ lineNumber, e.getMessage());
+ _parser.reportError(Constants.FATAL, err);
+ }
+ return null;
+ }
+
+ /**
+ * Lookup a variable or parameter in the symbol table given its name.
+ *
+ * @param name Name of the symbol being looked up.
+ */
+ final SyntaxTreeNode lookupName(QName name) {
+ // Is it a local var or param ?
+ final SyntaxTreeNode result = _parser.lookupVariable(name);
+ if (result != null)
+ return(result);
+ else
+ return(_symbolTable.lookupName(name));
+ }
+
+ public final void addError(ErrorMsg error) {
+ _parser.reportError(Constants.ERROR, error);
+ }
+
+ public void report_error(String message, Object info) {
+ final ErrorMsg err = new ErrorMsg(ErrorMsg.SYNTAX_ERR, _lineNumber,
+ _expression);
+ _parser.reportError(Constants.FATAL, err);
+ }
+
+ public void report_fatal_error(String message, Object info) {
+ // empty
+ }
+
+ public RelativeLocationPath insertStep(Step step, RelativeLocationPath rlp) {
+ if (rlp instanceof Step) {
+ return new ParentLocationPath(step, (Step) rlp);
+ }
+ else if (rlp instanceof ParentLocationPath) {
+ final ParentLocationPath plp = (ParentLocationPath) rlp;
+ final RelativeLocationPath newrlp = insertStep(step, plp.getPath());
+ return new ParentLocationPath(newrlp, plp.getStep());
+ }
+ else {
+ addError(new ErrorMsg(ErrorMsg.INTERNAL_ERR, "XPathParser.insertStep"));
+ return rlp;
+ }
+ }
+
+ /**
+ * Returns true if the axis applies to elements only. The axes
+ * child, attribute, namespace, descendant result in non-empty
+ * nodesets only if the context node is of type element.
+ */
+ public boolean isElementAxis(int axis) {
+ return (axis == Axis.CHILD || axis == Axis.ATTRIBUTE ||
+ axis == Axis.NAMESPACE || axis == Axis.DESCENDANT);
+ }
+:}
+
+terminal SLASH, DOT, LBRACK, RBRACK, VBAR, LPAREN, RPAREN, STAR, COMMA;
+terminal DOLLAR, ATSIGN;
+terminal DDOT, DCOLON, DSLASH;
+terminal EQ, NE;
+terminal LT, GT, LE, GE;
+terminal PLUS, MINUS, DIV, MOD, MULT;
+terminal String Literal;
+terminal String QNAME;
+terminal ID, KEY, TEXT, NODE, OR, AND, COMMENT, PI, PIPARAM, PRECEDINGSIBLING;
+terminal SELF, PARENT, CHILD, ATTRIBUTE, ANCESTOR, ANCESTORORSELF, DESCENDANT;
+terminal DESCENDANTORSELF, FOLLOWING, FOLLOWINGSIBLING, NAMESPACE, PRECEDING;
+terminal Double REAL;
+terminal Long INT;
+terminal PATTERN, EXPRESSION;
+
+non terminal SyntaxTreeNode TopLevel;
+
+non terminal Expression Expr, Argument, LocationPath;
+non terminal Expression Predicate, FilterExpr, Step;
+non terminal Expression OrExpr, AndExpr, EqualityExpr;
+non terminal Expression RelationalExpr, AdditiveExpr;
+non terminal Expression MultiplicativeExpr, UnaryExpr;
+non terminal Expression VariableReference, FunctionCall;
+non terminal Expression PrimaryExpr, UnionExpr, PathExpr, AbbreviatedStep;
+non terminal Expression RelativeLocationPath, AbbreviatedRelativeLocationPath;
+non terminal Expression AbsoluteLocationPath, AbbreviatedAbsoluteLocationPath;
+
+non terminal Object NodeTest, NameTest;
+
+non terminal IdKeyPattern IdKeyPattern;
+non terminal Pattern Pattern;
+non terminal Pattern LocationPathPattern;
+non terminal StepPattern ProcessingInstructionPattern;
+non terminal RelativePathPattern RelativePathPattern;
+non terminal StepPattern StepPattern;
+non terminal Object NodeTestPattern, NameTestPattern;
+
+non terminal Vector Predicates, NonemptyArgumentList;
+non terminal QName QName, FunctionName, VariableName;
+non terminal Integer AxisName, AxisSpecifier;
+non terminal Integer ChildOrAttributeAxisSpecifier;
+
+precedence left VBAR;
+precedence left OR;
+precedence left AND;
+precedence nonassoc EQ, NE;
+precedence left LT, GT, LE, GE;
+
+precedence left PLUS, MINUS;
+precedence left DIV, MOD, MULT;
+precedence left DOLLAR;
+precedence left ATSIGN;
+precedence right DCOLON;
+
+start with TopLevel;
+
+TopLevel ::= PATTERN Pattern:pattern
+ {: RESULT = pattern; :}
+
+ | EXPRESSION Expr:expr
+ {: RESULT = expr; :};
+
+/* --------------------------- Patterns ----------------------------------- */
+
+Pattern ::= LocationPathPattern:lpp
+ {: RESULT = lpp; :}
+
+ | LocationPathPattern:lpp VBAR Pattern:p
+ {: RESULT = new AlternativePattern(lpp, p); :};
+
+LocationPathPattern ::= SLASH
+ {: RESULT = new AbsolutePathPattern(null); :}
+
+ | SLASH RelativePathPattern:rpp
+ {: RESULT = new AbsolutePathPattern(rpp); :}
+
+ | IdKeyPattern:ikp
+ {: RESULT = ikp; :}
+
+ | IdKeyPattern:ikp SLASH RelativePathPattern:rpp
+ {: RESULT = new ParentPattern(ikp, rpp); :}
+
+ | IdKeyPattern:ikp DSLASH RelativePathPattern:rpp
+ {: RESULT = new AncestorPattern(ikp, rpp); :}
+
+ | DSLASH RelativePathPattern:rpp
+ {: RESULT = new AncestorPattern(rpp); :}
+
+ | RelativePathPattern:rpp
+ {: RESULT = rpp; :};
+
+IdKeyPattern ::= ID LPAREN Literal:l RPAREN
+ {: RESULT = new IdPattern(l);
+ parser.setHasIdCall(true);
+ :}
+
+ | KEY LPAREN Literal:l1 COMMA Literal:l2 RPAREN
+ {: RESULT = new KeyPattern(l1, l2); :};
+
+ProcessingInstructionPattern ::= PIPARAM LPAREN Literal:l RPAREN
+ {: RESULT = new ProcessingInstructionPattern(l); :};
+
+RelativePathPattern ::= StepPattern:sp
+ {: RESULT = sp; :}
+
+ | StepPattern:sp SLASH RelativePathPattern:rpp
+ {: RESULT = new ParentPattern(sp, rpp); :}
+
+ | StepPattern:sp DSLASH RelativePathPattern:rpp
+ {: RESULT = new AncestorPattern(sp, rpp); :};
+
+StepPattern ::= NodeTestPattern:nt
+ {:
+ RESULT = parser.createStepPattern(Axis.CHILD, nt, null);
+ :}
+
+ | NodeTestPattern:nt Predicates:pp
+ {:
+ RESULT = parser.createStepPattern(Axis.CHILD, nt, pp);
+ :}
+
+ | ProcessingInstructionPattern:pip
+ {: RESULT = pip; :}
+
+ | ProcessingInstructionPattern:pip Predicates:pp
+ {: RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp); :}
+
+ | ChildOrAttributeAxisSpecifier:axis NodeTestPattern:nt
+ {:
+ RESULT = parser.createStepPattern(axis.intValue(), nt, null);
+ :}
+
+ | ChildOrAttributeAxisSpecifier:axis
+ NodeTestPattern:nt Predicates:pp
+ {:
+ RESULT = parser.createStepPattern(axis.intValue(), nt, pp);
+ :}
+
+ | ChildOrAttributeAxisSpecifier:axis ProcessingInstructionPattern:pip
+ {:
+ RESULT = pip; // TODO: report error if axis is attribute
+ :}
+
+ | ChildOrAttributeAxisSpecifier:axis ProcessingInstructionPattern:pip
+ Predicates:pp
+ {:
+ // TODO: report error if axis is attribute
+ RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp);
+ :};
+
+NodeTestPattern ::= NameTestPattern:nt
+ {: RESULT = nt; :}
+
+ | NODE
+ {: RESULT = new Integer(NodeTest.ANODE); :}
+
+ | TEXT
+ {: RESULT = new Integer(NodeTest.TEXT); :}
+
+ | COMMENT
+ {: RESULT = new Integer(NodeTest.COMMENT); :}
+
+ | PI
+ {: RESULT = new Integer(NodeTest.PI); :};
+
+NameTestPattern ::= STAR
+ {: RESULT = null; :}
+
+ | QName:qn
+ {: RESULT = qn; :};
+
+ChildOrAttributeAxisSpecifier ::= ATSIGN
+ {: RESULT = new Integer(Axis.ATTRIBUTE); :}
+
+ | CHILD DCOLON
+ {: RESULT = new Integer(Axis.CHILD); :}
+
+ | ATTRIBUTE DCOLON
+ {: RESULT = new Integer(Axis.ATTRIBUTE); :};
+
+Predicates ::= Predicate:p
+ {:
+ Vector temp = new Vector();
+ temp.addElement(p);
+ RESULT = temp;
+ :}
+
+ | Predicate:p Predicates:pp
+ {: pp.insertElementAt(p, 0); RESULT = pp; :};
+
+Predicate ::= LBRACK Expr:e RBRACK
+ {:
+ RESULT = new Predicate(e);
+ :};
+
+/* --------------------------- Expressions --------------------------------- */
+
+Expr ::= OrExpr:ex
+ {: RESULT = ex; :};
+
+OrExpr ::= AndExpr:ae
+ {: RESULT = ae; :}
+
+ | OrExpr:oe OR AndExpr:ae
+ {: RESULT = new LogicalExpr(LogicalExpr.OR, oe, ae); :};
+
+AndExpr ::= EqualityExpr:e
+ {: RESULT = e; :}
+
+ | AndExpr:ae AND EqualityExpr:ee
+ {: RESULT = new LogicalExpr(LogicalExpr.AND, ae, ee); :};
+
+EqualityExpr ::= RelationalExpr:re
+ {: RESULT = re; :}
+
+ | EqualityExpr:ee EQ RelationalExpr:re
+ {: RESULT = new EqualityExpr(Operators.EQ, ee, re); :}
+
+ | EqualityExpr:ee NE RelationalExpr:re
+ {: RESULT = new EqualityExpr(Operators.NE, ee, re); :};
+
+RelationalExpr ::= AdditiveExpr:ae
+ {: RESULT = ae; :}
+
+ | RelationalExpr:re LT AdditiveExpr:ae
+ {: RESULT = new RelationalExpr(Operators.LT, re, ae); :}
+
+ | RelationalExpr:re GT AdditiveExpr:ae
+ {: RESULT = new RelationalExpr(Operators.GT, re, ae); :}
+
+ | RelationalExpr:re LE AdditiveExpr:ae
+ {: RESULT = new RelationalExpr(Operators.LE, re, ae); :}
+
+ | RelationalExpr:re GE AdditiveExpr:ae
+ {: RESULT = new RelationalExpr(Operators.GE, re, ae); :};
+
+AdditiveExpr ::= MultiplicativeExpr:me
+ {: RESULT = me; :}
+
+ | AdditiveExpr:ae PLUS MultiplicativeExpr:me
+ {: RESULT = new BinOpExpr(BinOpExpr.PLUS, ae, me); :}
+
+ | AdditiveExpr:ae MINUS MultiplicativeExpr:me
+ {: RESULT = new BinOpExpr(BinOpExpr.MINUS, ae, me); :};
+
+MultiplicativeExpr ::= UnaryExpr:ue
+ {: RESULT = ue; :}
+
+ | MultiplicativeExpr:me MULT UnaryExpr:ue
+ {: RESULT = new BinOpExpr(BinOpExpr.TIMES, me, ue); :}
+
+ | MultiplicativeExpr:me DIV UnaryExpr:ue
+ {: RESULT = new BinOpExpr(BinOpExpr.DIV, me, ue); :}
+
+ | MultiplicativeExpr:me MOD UnaryExpr:ue
+ {: RESULT = new BinOpExpr(BinOpExpr.MOD, me, ue); :};
+
+UnaryExpr ::= UnionExpr:ue
+ {: RESULT = ue; :}
+
+ | MINUS UnaryExpr:ue
+ {: RESULT = new UnaryOpExpr(ue); :};
+
+UnionExpr ::= PathExpr:pe
+ {: RESULT = pe; :}
+
+ | PathExpr:pe VBAR UnionExpr:rest
+ {: RESULT = new UnionPathExpr(pe, rest); :};
+
+PathExpr ::= LocationPath:lp
+ {: RESULT = lp; :}
+
+ | FilterExpr:fexp
+ {: RESULT = fexp; :}
+
+ | FilterExpr:fexp SLASH RelativeLocationPath:rlp
+ {: RESULT = new FilterParentPath(fexp, rlp); :}
+
+ | FilterExpr:fexp DSLASH RelativeLocationPath:rlp
+ {:
+ //
+ // Expand '//' into '/descendant-or-self::node()/' or
+ // into /descendant-or-self::*/
+ //
+ int nodeType = DOM.NO_TYPE;
+ if (rlp instanceof Step &&
+ parser.isElementAxis(((Step) rlp).getAxis()))
+ {
+ nodeType = DTM.ELEMENT_NODE;
+ }
+ final Step step = new Step(Axis.DESCENDANTORSELF, nodeType, null);
+ FilterParentPath fpp = new FilterParentPath(fexp, step);
+ fpp = new FilterParentPath(fpp, rlp);
+ if (fexp instanceof KeyCall == false) {
+ fpp.setDescendantAxis();
+ }
+ RESULT = fpp;
+ :};
+
+LocationPath ::= RelativeLocationPath:rlp
+ {: RESULT = rlp; :}
+
+ | AbsoluteLocationPath:alp
+ {: RESULT = alp; :};
+
+RelativeLocationPath ::= Step:step
+ {: RESULT = step; :}
+
+ | RelativeLocationPath:rlp SLASH Step:step
+ {:
+ if (rlp instanceof Step && ((Step) rlp).isAbbreviatedDot()) {
+ RESULT = step; // Remove './' from the middle
+ }
+ else if (((Step) step).isAbbreviatedDot()) {
+ RESULT = rlp; // Remove '/.' from the end
+ }
+ else {
+ RESULT =
+ new ParentLocationPath((RelativeLocationPath) rlp, step);
+ }
+ :}
+
+ | AbbreviatedRelativeLocationPath:arlp
+ {: RESULT = arlp; :};
+
+AbsoluteLocationPath ::= SLASH
+ {: RESULT = new AbsoluteLocationPath(); :}
+
+ | SLASH RelativeLocationPath:rlp
+ {: RESULT = new AbsoluteLocationPath(rlp); :}
+
+ | AbbreviatedAbsoluteLocationPath:aalp
+ {: RESULT = aalp; :};
+
+AbbreviatedRelativeLocationPath ::= RelativeLocationPath:rlp DSLASH Step:step
+ {:
+ final Step right = (Step)step;
+ final int axis = right.getAxis();
+ final int type = right.getNodeType();
+ final Vector predicates = right.getPredicates();
+
+ if ((axis == Axis.CHILD) && (type != NodeTest.ATTRIBUTE)) {
+ // Compress './/child:E' into 'descendant::E' - if possible
+ if (predicates == null) {
+ right.setAxis(Axis.DESCENDANT);
+ if (rlp instanceof Step && ((Step)rlp).isAbbreviatedDot()) {
+ RESULT = right;
+ }
+ else {
+ // Expand 'rlp//child::E' into 'rlp/descendant::E'
+ RelativeLocationPath left = (RelativeLocationPath)rlp;
+ RESULT = new ParentLocationPath(left, right);
+ }
+ }
+ else {
+ // Expand './/step' -> 'descendant-or-self::*/step'
+ if (rlp instanceof Step && ((Step)rlp).isAbbreviatedDot()) {
+ Step left = new Step(Axis.DESCENDANTORSELF,
+ DTM.ELEMENT_NODE, null);
+ RESULT = new ParentLocationPath(left, right);
+ }
+ else {
+ // Expand 'rlp//step' -> 'rlp/descendant-or-self::*/step'
+ RelativeLocationPath left = (RelativeLocationPath)rlp;
+ Step mid = new Step(Axis.DESCENDANTORSELF,
+ DTM.ELEMENT_NODE, null);
+ ParentLocationPath ppl = new ParentLocationPath(mid, right);
+ RESULT = new ParentLocationPath(left, ppl);
+ }
+ }
+ }
+ else if ((axis == Axis.ATTRIBUTE) || (type == NodeTest.ATTRIBUTE)) {
+ // Expand 'rlp//step' -> 'rlp/descendant-or-self::*/step'
+ RelativeLocationPath left = (RelativeLocationPath)rlp;
+ Step middle = new Step(Axis.DESCENDANTORSELF,
+ DTM.ELEMENT_NODE, null);
+ ParentLocationPath ppl = new ParentLocationPath(middle, right);
+ RESULT = new ParentLocationPath(left, ppl);
+ }
+ else {
+ // Expand 'rlp//step' -> 'rlp/descendant-or-self::node()/step'
+ RelativeLocationPath left = (RelativeLocationPath)rlp;
+ Step middle = new Step(Axis.DESCENDANTORSELF,
+ DOM.NO_TYPE, null);
+ ParentLocationPath ppl = new ParentLocationPath(middle, right);
+ RESULT = new ParentLocationPath(left, ppl);
+ }
+ :};
+
+
+AbbreviatedAbsoluteLocationPath ::= DSLASH RelativeLocationPath:rlp
+ {:
+ //
+ // Expand '//' into '/descendant-or-self::node()/' or
+ // into /descendant-or-self::*/
+ //
+ int nodeType = DOM.NO_TYPE;
+ if (rlp instanceof Step &&
+ parser.isElementAxis(((Step) rlp).getAxis()))
+ {
+ nodeType = DTM.ELEMENT_NODE;
+ }
+ final Step step = new Step(Axis.DESCENDANTORSELF, nodeType, null);
+ RESULT = new AbsoluteLocationPath(parser.insertStep(step,
+ (RelativeLocationPath) rlp));
+ :};
+
+Step ::= NodeTest:ntest
+ {:
+ if (ntest instanceof Step) {
+ RESULT = (Step)ntest;
+ }
+ else {
+ RESULT = new Step(Axis.CHILD,
+ parser.findNodeType(Axis.CHILD, ntest),
+ null);
+ }
+ :}
+
+ | NodeTest:ntest Predicates:pp
+ {:
+ if (ntest instanceof Step) {
+ Step step = (Step)ntest;
+ step.addPredicates(pp);
+ RESULT = (Step)ntest;
+ }
+ else {
+ RESULT = new Step(Axis.CHILD,
+ parser.findNodeType(Axis.CHILD, ntest), pp);
+ }
+ :}
+
+ | AxisSpecifier:axis NodeTest:ntest Predicates:pp
+ {: RESULT = new Step(axis.intValue(),
+ parser.findNodeType(axis.intValue(), ntest),
+ pp);
+ :}
+
+ | AxisSpecifier:axis NodeTest:ntest
+ {: RESULT = new Step(axis.intValue(),
+ parser.findNodeType(axis.intValue(), ntest),
+ null);
+ :}
+
+ | AbbreviatedStep:abbrev
+ {: RESULT = abbrev; :};
+
+AxisSpecifier ::= AxisName:an DCOLON
+ {: RESULT = an; :}
+
+ | ATSIGN
+ {: RESULT = new Integer(Axis.ATTRIBUTE); :};
+
+AxisName ::= ANCESTOR
+ {: RESULT = new Integer(Axis.ANCESTOR); :}
+
+ | ANCESTORORSELF
+ {: RESULT = new Integer(Axis.ANCESTORORSELF); :}
+
+ | ATTRIBUTE
+ {: RESULT = new Integer(Axis.ATTRIBUTE); :}
+
+ | CHILD
+ {: RESULT = new Integer(Axis.CHILD); :}
+
+ | DESCENDANT
+ {: RESULT = new Integer(Axis.DESCENDANT); :}
+
+ | DESCENDANTORSELF
+ {: RESULT = new Integer(Axis.DESCENDANTORSELF); :}
+
+ | FOLLOWING
+ {: RESULT = new Integer(Axis.FOLLOWING); :}
+
+ | FOLLOWINGSIBLING
+ {: RESULT = new Integer(Axis.FOLLOWINGSIBLING); :}
+
+ | NAMESPACE
+ {: RESULT = new Integer(Axis.NAMESPACE); :}
+
+ | PARENT
+ {: RESULT = new Integer(Axis.PARENT); :}
+
+ | PRECEDING
+ {: RESULT = new Integer(Axis.PRECEDING); :}
+
+ | PRECEDINGSIBLING
+ {: RESULT = new Integer(Axis.PRECEDINGSIBLING); :}
+
+ | SELF
+ {: RESULT = new Integer(Axis.SELF); :};
+
+AbbreviatedStep ::= DOT
+ {: RESULT = new Step(Axis.SELF, NodeTest.ANODE, null); :}
+
+ | DDOT
+ {: RESULT = new Step(Axis.PARENT, NodeTest.ANODE, null); :};
+
+FilterExpr ::= PrimaryExpr:primary
+ {: RESULT = primary; :}
+
+ | PrimaryExpr:primary Predicates:pp
+ {: RESULT = new FilterExpr(primary, pp); :};
+
+PrimaryExpr ::= VariableReference:vr
+ {: RESULT = vr; :}
+
+ | LPAREN Expr:ex RPAREN
+ {: RESULT = ex; :}
+
+ | Literal:string
+ {:
+ /*
+ * If the string appears to have the syntax of a QName, store
+ * namespace info in the literal expression. This is used for
+ * element-available and function-available functions, among
+ * others. Also, the default namespace must be ignored.
+ */
+ String namespace = null;
+ final int index = string.lastIndexOf(':');
+
+ if (index > 0) {
+ final String prefix = string.substring(0, index);
+ namespace = parser._symbolTable.lookupNamespace(prefix);
+ }
+ RESULT = (namespace == null) ? new LiteralExpr(string)
+ : new LiteralExpr(string, namespace);
+ :}
+
+ | INT:num
+ {:
+ long value = num.longValue();
+ if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
+ RESULT = new RealExpr(value);
+ }
+ else {
+ if (num.doubleValue() == -0)
+ RESULT = new RealExpr(num.doubleValue());
+ else if (num.intValue() == 0)
+ RESULT = new IntExpr(num.intValue());
+ else if (num.doubleValue() == 0.0)
+ RESULT = new RealExpr(num.doubleValue());
+ else
+ RESULT = new IntExpr(num.intValue());
+ }
+ :}
+
+ | REAL:num
+ {: RESULT = new RealExpr(num.doubleValue()); :}
+
+ | FunctionCall:fc
+ {: RESULT = fc; :};
+
+VariableReference ::= DOLLAR VariableName:varName
+ {:
+ // An empty qname prefix for a variable or parameter reference
+ // should map to the null namespace and not the default URI.
+ SyntaxTreeNode node = parser.lookupName(varName);
+
+ if (node != null) {
+ if (node instanceof Variable) {
+ RESULT = new VariableRef((Variable)node);
+ }
+ else if (node instanceof Param) {
+ RESULT = new ParameterRef((Param)node);
+ }
+ else {
+ RESULT = new UnresolvedRef(varName);
+ }
+ }
+
+ if (node == null) {
+ RESULT = new UnresolvedRef(varName);
+ }
+ :};
+
+FunctionCall ::= FunctionName:fname LPAREN RPAREN
+ {:
+
+ if (parser.getQNameIgnoreDefaultNs("current").equals(fname)) {
+ RESULT = new CurrentCall(fname);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("number").equals(fname)) {
+ RESULT = new NumberCall(fname, parser.EmptyArgs);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("string").equals(fname)) {
+ RESULT = new StringCall(fname, parser.EmptyArgs);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("concat").equals(fname)) {
+ RESULT = new ConcatCall(fname, parser.EmptyArgs);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("true").equals(fname)) {
+ RESULT = new BooleanExpr(true);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("false").equals(fname)) {
+ RESULT = new BooleanExpr(false);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("name").equals(fname)) {
+ RESULT = new NameCall(fname);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("generate-id").equals(fname)) {
+ RESULT = new GenerateIdCall(fname, parser.EmptyArgs);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("string-length").equals(fname)) {
+ RESULT = new StringLengthCall(fname, parser.EmptyArgs);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("position").equals(fname)) {
+ RESULT = new PositionCall(fname);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("last").equals(fname)) {
+ RESULT = new LastCall(fname);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("local-name").equals(fname)) {
+ RESULT = new LocalNameCall(fname);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("namespace-uri").equals(fname)) {
+ RESULT = new NamespaceUriCall(fname);
+ }
+ else {
+ RESULT = new FunctionCall(fname, parser.EmptyArgs);
+ }
+ :}
+
+ | FunctionName:fname LPAREN NonemptyArgumentList:argl RPAREN
+ {:
+ if (parser.getQNameIgnoreDefaultNs("concat").equals(fname)) {
+ RESULT = new ConcatCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("number").equals(fname)) {
+ RESULT = new NumberCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("document").equals(fname)) {
+ parser.setMultiDocument(true);
+ RESULT = new DocumentCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("string").equals(fname)) {
+ RESULT = new StringCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("boolean").equals(fname)) {
+ RESULT = new BooleanCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("name").equals(fname)) {
+ RESULT = new NameCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("generate-id").equals(fname)) {
+ RESULT = new GenerateIdCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("not").equals(fname)) {
+ RESULT = new NotCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("format-number").equals(fname)) {
+ RESULT = new FormatNumberCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("unparsed-entity-uri").equals(fname)) {
+ RESULT = new UnparsedEntityUriCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("key").equals(fname)) {
+ RESULT = new KeyCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("id").equals(fname)) {
+ RESULT = new KeyCall(fname, argl);
+ parser.setHasIdCall(true);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("ceiling").equals(fname)) {
+ RESULT = new CeilingCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("round").equals(fname)) {
+ RESULT = new RoundCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("floor").equals(fname)) {
+ RESULT = new FloorCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("contains").equals(fname)) {
+ RESULT = new ContainsCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("string-length").equals(fname)) {
+ RESULT = new StringLengthCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("starts-with").equals(fname)) {
+ RESULT = new StartsWithCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("function-available").equals(fname)) {
+ RESULT = new FunctionAvailableCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("element-available").equals(fname)) {
+ RESULT = new ElementAvailableCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("local-name").equals(fname)) {
+ RESULT = new LocalNameCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("lang").equals(fname)) {
+ RESULT = new LangCall(fname, argl);
+ }
+ else if (parser.getQNameIgnoreDefaultNs("namespace-uri").equals(fname)) {
+ RESULT = new NamespaceUriCall(fname, argl);
+ }
+ else if (parser.getQName(Constants.TRANSLET_URI, "xsltc", "cast").equals(fname)) {
+ RESULT = new CastCall(fname, argl);
+ }
+ // Special case for extension function nodeset()
+ else if (fname.getLocalPart().equals("nodeset") || fname.getLocalPart().equals("node-set")) {
+ parser.setCallsNodeset(true); // implies MultiDOM
+ RESULT = new FunctionCall(fname, argl);
+ }
+ else {
+ RESULT = new FunctionCall(fname, argl);
+ }
+ :};
+
+NonemptyArgumentList ::= Argument:arg
+ {:
+ Vector temp = new Vector();
+ temp.addElement(arg);
+ RESULT = temp;
+ :}
+
+ | Argument:arg COMMA NonemptyArgumentList:argl
+ {: argl.insertElementAt(arg, 0); RESULT = argl; :};
+
+FunctionName ::= QName:fname
+ {:
+ RESULT = fname;
+ :};
+
+VariableName ::= QName:vname
+ {:
+ RESULT = vname;
+ :};
+
+Argument ::= Expr:ex
+ {: RESULT = ex; :};
+
+NodeTest ::= NameTest:nt
+ {: RESULT = nt; :}
+
+ | NODE
+ {: RESULT = new Integer(NodeTest.ANODE); :}
+
+ | TEXT
+ {: RESULT = new Integer(NodeTest.TEXT); :}
+
+ | COMMENT
+ {: RESULT = new Integer(NodeTest.COMMENT); :}
+
+ | PIPARAM LPAREN Literal:l RPAREN
+ {:
+ QName name = parser.getQNameIgnoreDefaultNs("name");
+ Expression exp = new EqualityExpr(Operators.EQ,
+ new NameCall(name),
+ new LiteralExpr(l));
+ Vector predicates = new Vector();
+ predicates.addElement(new Predicate(exp));
+ RESULT = new Step(Axis.CHILD, NodeTest.PI, predicates);
+ :}
+
+ | PI
+ {: RESULT = new Integer(NodeTest.PI); :};
+
+NameTest ::= STAR
+ {: RESULT = null; :}
+
+ | QName:qn
+ {: RESULT = qn; :};
+
+QName ::= QNAME:qname
+ {: RESULT = parser.getQNameIgnoreDefaultNs(qname); :}
+
+ | DIV
+ {: RESULT = parser.getQNameIgnoreDefaultNs("div"); :}
+
+ | MOD
+ {: RESULT = parser.getQNameIgnoreDefaultNs("mod"); :}
+
+ | KEY
+ {: RESULT = parser.getQNameIgnoreDefaultNs("key"); :}
+
+ | ANCESTOR
+ {: RESULT = parser.getQNameIgnoreDefaultNs("child"); :}
+
+ | ANCESTORORSELF
+ {: RESULT = parser.getQNameIgnoreDefaultNs("ancestor-or-self"); :}
+
+ | ATTRIBUTE
+ {: RESULT = parser.getQNameIgnoreDefaultNs("attribute"); :}
+
+ | CHILD
+ {: RESULT = parser.getQNameIgnoreDefaultNs("child"); :}
+
+ | DESCENDANT
+ {: RESULT = parser.getQNameIgnoreDefaultNs("decendant"); :}
+
+ | DESCENDANTORSELF
+ {: RESULT = parser.getQNameIgnoreDefaultNs("decendant-or-self"); :}
+
+ | FOLLOWING
+ {: RESULT = parser.getQNameIgnoreDefaultNs("following"); :}
+
+ | FOLLOWINGSIBLING
+ {: RESULT = parser.getQNameIgnoreDefaultNs("following-sibling"); :}
+
+ | NAMESPACE
+ {: RESULT = parser.getQNameIgnoreDefaultNs("namespace"); :}
+
+ | PARENT
+ {: RESULT = parser.getQNameIgnoreDefaultNs("parent"); :}
+
+ | PRECEDING
+ {: RESULT = parser.getQNameIgnoreDefaultNs("preceding"); :}
+
+ | PRECEDINGSIBLING
+ {: RESULT = parser.getQNameIgnoreDefaultNs("preceding-sibling"); :}
+
+ | SELF
+ {: RESULT = parser.getQNameIgnoreDefaultNs("self"); :}
+
+ | ID
+ {: RESULT = parser.getQNameIgnoreDefaultNs("id"); :};
+