1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Copyright 2001-2004 The Apache Software Foundation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *     http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21/*
22 * $Id: xpath.cup,v 1.51 2004/12/15 17:35:39 jycli Exp $
23 */
24
25/*
26 * @author Jacek Ambroziak
27 * @author Santiago Pericas-Geertsen
28 * @author Morten Jorgensen
29 * @author G. Todd Miller
30 */
31
32package com.sun.org.apache.xalan.internal.xsltc.compiler;
33
34import java.util.Stack;
35import java.util.Vector;
36import java.io.StringReader;
37import com.sun.java_cup.internal.runtime.*;
38
39import com.sun.org.apache.xml.internal.dtm.DTM;
40import com.sun.org.apache.xalan.internal.xsltc.DOM;
41import com.sun.org.apache.xml.internal.dtm.Axis;
42import com.sun.org.apache.xalan.internal.xsltc.runtime.Operators;
43import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
44
45parser code {:
46    /**
47     * Used by function calls with no args.
48     */
49    static public final Vector EmptyArgs = new Vector(0);
50
51    /**
52     * Reference to non-existing variable.
53     */
54    static public final VariableRef DummyVarRef = null;
55
56    /**
57     * Reference to the Parser class.
58     */
59    private Parser _parser;
60    private XSLTC  _xsltc;
61
62    /**
63     * String representation of the expression being parsed.
64     */
65    private String _expression;
66
67    /**
68     * Line number where this expression/pattern was declared.
69     */
70    private int _lineNumber = 0;
71
72    /**
73     * Reference to the symbol table.
74     */
75    public SymbolTable _symbolTable;
76
77    public XPathParser(Parser parser) {
78        _parser = parser;
79	_xsltc = parser.getXSLTC();
80        _symbolTable = parser.getSymbolTable();
81    }
82
83    public int getLineNumber() {
84        return _lineNumber;
85    }
86
87    public QName getQNameIgnoreDefaultNs(String name) {
88          return _parser.getQNameIgnoreDefaultNs(name);
89    }
90
91    public QName getQName(String namespace, String prefix, String localname) {
92        return _parser.getQName(namespace, prefix, localname);
93    }
94
95    public void setMultiDocument(boolean flag) {
96          _xsltc.setMultiDocument(flag);
97    }
98
99    public void setCallsNodeset(boolean flag) {
100          _xsltc.setCallsNodeset(flag);
101    }
102
103    public void setHasIdCall(boolean flag) {
104          _xsltc.setHasIdCall(flag);
105    }
106
107
108    /**
109     * This method is similar to findNodeType(int, Object) except that it
110     * creates a StepPattern instead of just returning a node type. It also
111     * differs in the way it handles "{uri}:*" and "{uri}:@*". The last two
112     * patterns are expanded as "*[namespace-uri() = 'uri']" and
113     * "@*[namespace-uri() = 'uri']", respectively. This expansion considerably
114     * simplifies the grouping of patterns in the Mode class. For this
115     * expansion to be correct, the priority of the pattern/template must be
116     * set to -0.25 (when no other predicates are present).
117     */
118    public StepPattern createStepPattern(int axis, Object test, Vector predicates) {
119	int nodeType;
120
121	if (test == null) {  // "*"
122	    nodeType = (axis == Axis.ATTRIBUTE) ? NodeTest.ATTRIBUTE :
123		(axis == Axis.NAMESPACE) ? -1 : NodeTest.ELEMENT;
124
125	    return new StepPattern(axis, nodeType, predicates);
126        }
127        else if (test instanceof Integer) {
128	    nodeType = ((Integer) test).intValue();
129
130	    return new StepPattern(axis, nodeType, predicates);
131        }
132        else {
133	    QName name = (QName)test;
134	    boolean setPriority = false;
135
136	    if (axis == Axis.NAMESPACE) {
137		nodeType = (name.toString().equals("*")) ? -1
138				: _xsltc.registerNamespacePrefix(name);;
139            }
140	    else {
141		final String uri = name.getNamespace();
142		final String local = name.getLocalPart();
143		final QName namespace_uri =
144		    _parser.getQNameIgnoreDefaultNs("namespace-uri");
145
146		// Expand {uri}:* to *[namespace-uri() = 'uri'] - same for @*
147		if (uri != null && (local.equals("*") || local.equals("@*"))) {
148		    if (predicates == null) {
149			predicates = new Vector(2);
150		    }
151
152		    // Priority is set by hand if no other predicates exist
153		    setPriority = (predicates.size() == 0);
154
155		    predicates.add(
156			new Predicate(
157			    new EqualityExpr(Operators.EQ,
158				new NamespaceUriCall(namespace_uri),
159				new LiteralExpr(uri))));
160		}
161
162		if (local.equals("*")) {
163		    nodeType = (axis == Axis.ATTRIBUTE) ? NodeTest.ATTRIBUTE
164			: NodeTest.ELEMENT;
165		}
166		else if (local.equals("@*")) {
167		    nodeType = NodeTest.ATTRIBUTE;
168		}
169		else {
170		    nodeType = (axis == Axis.ATTRIBUTE) ? _xsltc.registerAttribute(name)
171			: _xsltc.registerElement(name);
172		}
173	    }
174
175	    final StepPattern result = new StepPattern(axis, nodeType, predicates);
176
177	    // Set priority for case prefix:* and prefix:@* (no predicates)
178	    if (setPriority) {
179		result.setPriority(-0.25);
180	    }
181
182	    return result;
183	}
184    }
185
186    public int findNodeType(int axis, Object test) {
187	if (test == null) {  // *
188	    return (axis == Axis.ATTRIBUTE) ?
189		NodeTest.ATTRIBUTE :
190		(axis == Axis.NAMESPACE) ? -1 : NodeTest.ELEMENT;
191        }
192        else if (test instanceof Integer) {
193            return ((Integer)test).intValue();
194        }
195        else {
196	    QName name = (QName)test;
197
198	    if (axis == Axis.NAMESPACE) {
199		return (name.toString().equals("*")) ? -1
200		    : _xsltc.registerNamespacePrefix(name);
201            }
202
203	    if (name.getNamespace() == null) {
204		final String local = name.getLocalPart();
205
206		if (local.equals("*")) {
207		    return (axis == Axis.ATTRIBUTE) ? NodeTest.ATTRIBUTE
208			: NodeTest.ELEMENT;
209		}
210		else if (local.equals("@*")) {
211		    return NodeTest.ATTRIBUTE;
212		}
213	    }
214
215	    return (axis == Axis.ATTRIBUTE) ? _xsltc.registerAttribute(name)
216		: _xsltc.registerElement(name);
217        }
218    }
219
220    /**
221     * Parse the expression passed to the current scanner. If this
222     * expression contains references to local variables and it will be
223     * compiled in an external module (not in the main class) request
224     * the current template to create a new variable stack frame.
225     *
226     * @param lineNumber Line where the current expression is defined.
227     * @param external   Set to <tt>true</tt> if this expression is
228     *                   compiled in a separate module.
229     *
230     */
231    public Symbol parse(String expression, int lineNumber) throws Exception {
232        try {
233	    _expression = expression;
234	    _lineNumber = lineNumber;
235	    return super.parse();
236        }
237        catch (IllegalCharException e) {
238            ErrorMsg err = new ErrorMsg(ErrorMsg.ILLEGAL_CHAR_ERR,
239                                        lineNumber, e.getMessage());
240            _parser.reportError(Constants.FATAL, err);
241        }
242        return null;
243    }
244
245    /**
246     * Lookup a variable or parameter in the symbol table given its name.
247     *
248     * @param name Name of the symbol being looked up.
249     */
250    final SyntaxTreeNode lookupName(QName name) {
251        // Is it a local var or param ?
252        final SyntaxTreeNode result = _parser.lookupVariable(name);
253	if (result != null)
254            return(result);
255        else
256	    return(_symbolTable.lookupName(name));
257    }
258
259    public final void addError(ErrorMsg error) {
260	_parser.reportError(Constants.ERROR, error);
261    }
262
263    public void report_error(String message, Object info) {
264	final ErrorMsg err = new ErrorMsg(ErrorMsg.SYNTAX_ERR, _lineNumber,
265	    _expression);
266	_parser.reportError(Constants.FATAL, err);
267    }
268
269    public void report_fatal_error(String message, Object info) {
270        // empty
271    }
272
273    public RelativeLocationPath insertStep(Step step, RelativeLocationPath rlp) {
274	if (rlp instanceof Step) {
275	    return new ParentLocationPath(step, (Step) rlp);
276	}
277	else if (rlp instanceof ParentLocationPath) {
278	    final ParentLocationPath plp = (ParentLocationPath) rlp;
279	    final RelativeLocationPath newrlp = insertStep(step, plp.getPath());
280	    return new ParentLocationPath(newrlp, plp.getStep());
281	}
282	else {
283	    addError(new ErrorMsg(ErrorMsg.INTERNAL_ERR, "XPathParser.insertStep"));
284	    return rlp;
285	}
286    }
287
288    /**
289     * Returns true if the axis applies to elements only. The axes
290     * child, attribute, namespace, descendant result in non-empty
291     * nodesets only if the context node is of type element.
292     */
293    public boolean isElementAxis(int axis) {
294	return (axis == Axis.CHILD || axis == Axis.ATTRIBUTE ||
295		axis == Axis.NAMESPACE || axis == Axis.DESCENDANT);
296    }
297:}
298
299terminal SLASH, DOT, LBRACK, RBRACK, VBAR, LPAREN, RPAREN, STAR, COMMA;
300terminal DOLLAR, ATSIGN;
301terminal DDOT, DCOLON, DSLASH;
302terminal EQ, NE;
303terminal LT, GT, LE, GE;
304terminal PLUS, MINUS, DIV, MOD, MULT;
305terminal String Literal;
306terminal String QNAME;
307terminal ID, KEY, TEXT, NODE, OR, AND, COMMENT, PI, PIPARAM, PRECEDINGSIBLING;
308terminal SELF, PARENT, CHILD, ATTRIBUTE, ANCESTOR, ANCESTORORSELF, DESCENDANT;
309terminal DESCENDANTORSELF, FOLLOWING, FOLLOWINGSIBLING, NAMESPACE, PRECEDING;
310terminal Double REAL;
311terminal Long INT;
312terminal PATTERN, EXPRESSION;
313
314non terminal SyntaxTreeNode TopLevel;
315
316non terminal Expression Expr, Argument, LocationPath;
317non terminal Expression Predicate, FilterExpr, Step;
318non terminal Expression OrExpr, AndExpr, EqualityExpr;
319non terminal Expression RelationalExpr, AdditiveExpr;
320non terminal Expression MultiplicativeExpr, UnaryExpr;
321non terminal Expression VariableReference, FunctionCall;
322non terminal Expression PrimaryExpr, UnionExpr, PathExpr, AbbreviatedStep;
323non terminal Expression RelativeLocationPath, AbbreviatedRelativeLocationPath;
324non terminal Expression AbsoluteLocationPath, AbbreviatedAbsoluteLocationPath;
325
326non terminal Object NodeTest, NameTest;
327
328non terminal IdKeyPattern IdKeyPattern;
329non terminal Pattern Pattern;
330non terminal Pattern LocationPathPattern;
331non terminal StepPattern ProcessingInstructionPattern;
332non terminal RelativePathPattern RelativePathPattern;
333non terminal StepPattern StepPattern;
334non terminal Object NodeTestPattern, NameTestPattern;
335
336non terminal Vector Predicates, NonemptyArgumentList;
337non terminal QName QName, FunctionName, VariableName;
338non terminal Integer AxisName, AxisSpecifier;
339non terminal Integer ChildOrAttributeAxisSpecifier;
340
341precedence left VBAR;
342precedence left OR;
343precedence left AND;
344precedence nonassoc EQ, NE;
345precedence left LT, GT, LE, GE;
346
347precedence left PLUS, MINUS;
348precedence left DIV, MOD, MULT;
349precedence left DOLLAR;
350precedence left ATSIGN;
351precedence right DCOLON;
352
353start with TopLevel;
354
355TopLevel ::= PATTERN Pattern:pattern
356            {: RESULT = pattern; :}
357
358            | EXPRESSION Expr:expr
359            {: RESULT = expr; :};
360
361/* --------------------------- Patterns ----------------------------------- */
362
363Pattern ::= LocationPathPattern:lpp
364            {: RESULT = lpp; :}
365
366            | LocationPathPattern:lpp VBAR Pattern:p
367            {: RESULT = new AlternativePattern(lpp, p);  :};
368
369LocationPathPattern ::= SLASH
370            {: RESULT = new AbsolutePathPattern(null); :}
371
372            | SLASH RelativePathPattern:rpp
373            {: RESULT = new AbsolutePathPattern(rpp); :}
374
375            | IdKeyPattern:ikp
376            {: RESULT = ikp; :}
377
378            | IdKeyPattern:ikp SLASH RelativePathPattern:rpp
379            {: RESULT = new ParentPattern(ikp, rpp); :}
380
381            | IdKeyPattern:ikp DSLASH RelativePathPattern:rpp
382            {: RESULT = new AncestorPattern(ikp, rpp); :}
383
384            | DSLASH RelativePathPattern:rpp
385            {: RESULT = new AncestorPattern(rpp); :}
386
387            | RelativePathPattern:rpp
388            {: RESULT = rpp; :};
389
390IdKeyPattern ::= ID LPAREN Literal:l RPAREN
391            {: RESULT = new IdPattern(l);
392               parser.setHasIdCall(true);
393            :}
394
395            | KEY LPAREN Literal:l1 COMMA Literal:l2 RPAREN
396            {: RESULT = new KeyPattern(l1, l2); :};
397
398ProcessingInstructionPattern ::= PIPARAM LPAREN Literal:l RPAREN
399            {: RESULT = new ProcessingInstructionPattern(l); :};
400
401RelativePathPattern ::= StepPattern:sp
402            {: RESULT = sp; :}
403
404            | StepPattern:sp SLASH RelativePathPattern:rpp
405            {: RESULT = new ParentPattern(sp, rpp); :}
406
407            | StepPattern:sp DSLASH RelativePathPattern:rpp
408            {: RESULT = new AncestorPattern(sp, rpp); :};
409
410StepPattern ::= NodeTestPattern:nt
411            {:
412		RESULT = parser.createStepPattern(Axis.CHILD, nt, null);
413            :}
414
415            | NodeTestPattern:nt Predicates:pp
416            {:
417		RESULT = parser.createStepPattern(Axis.CHILD, nt, pp);
418            :}
419
420            | ProcessingInstructionPattern:pip
421            {: RESULT = pip; :}
422
423	    | ProcessingInstructionPattern:pip Predicates:pp
424            {: RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp); :}
425
426            | ChildOrAttributeAxisSpecifier:axis NodeTestPattern:nt
427            {:
428	       RESULT = parser.createStepPattern(axis.intValue(), nt, null);
429            :}
430
431	    | ChildOrAttributeAxisSpecifier:axis
432		  NodeTestPattern:nt Predicates:pp
433            {:
434	       RESULT = parser.createStepPattern(axis.intValue(), nt, pp);
435            :}
436
437            | ChildOrAttributeAxisSpecifier:axis ProcessingInstructionPattern:pip
438            {:
439	       RESULT = pip; 	// TODO: report error if axis is attribute
440	    :}
441
442	    | ChildOrAttributeAxisSpecifier:axis ProcessingInstructionPattern:pip
443		Predicates:pp
444            {:
445	       // TODO: report error if axis is attribute
446	       RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp);
447	    :};
448
449NodeTestPattern ::= NameTestPattern:nt
450            {: RESULT = nt; :}
451
452            | NODE
453            {: RESULT = new Integer(NodeTest.ANODE); :}
454
455            | TEXT
456            {: RESULT = new Integer(NodeTest.TEXT); :}
457
458            | COMMENT
459            {: RESULT = new Integer(NodeTest.COMMENT); :}
460
461            | PI
462            {: RESULT = new Integer(NodeTest.PI); :};
463
464NameTestPattern ::= STAR
465            {: RESULT = null; :}
466
467            | QName:qn
468            {: RESULT = qn; :};
469
470ChildOrAttributeAxisSpecifier ::= ATSIGN
471            {: RESULT = new Integer(Axis.ATTRIBUTE); :}
472
473            | CHILD DCOLON
474            {: RESULT = new Integer(Axis.CHILD); :}
475
476            | ATTRIBUTE DCOLON
477            {: RESULT = new Integer(Axis.ATTRIBUTE); :};
478
479Predicates ::= Predicate:p
480            {:
481		Vector temp = new Vector();
482		temp.addElement(p);
483		RESULT = temp;
484            :}
485
486            | Predicate:p Predicates:pp
487            {: pp.insertElementAt(p, 0); RESULT = pp; :};
488
489Predicate ::=  LBRACK Expr:e RBRACK
490	    {:
491		RESULT = new Predicate(e);
492	    :};
493
494/* --------------------------- Expressions --------------------------------- */
495
496Expr ::= OrExpr:ex
497        {: RESULT = ex; :};
498
499OrExpr ::= AndExpr:ae
500        {: RESULT = ae; :}
501
502        | OrExpr:oe OR AndExpr:ae
503        {: RESULT = new LogicalExpr(LogicalExpr.OR, oe, ae); :};
504
505AndExpr ::= EqualityExpr:e
506        {: RESULT = e; :}
507
508        | AndExpr:ae AND EqualityExpr:ee
509        {: RESULT = new LogicalExpr(LogicalExpr.AND, ae, ee); :};
510
511EqualityExpr ::= RelationalExpr:re
512        {: RESULT = re; :}
513
514        | EqualityExpr:ee EQ RelationalExpr:re
515        {: RESULT = new EqualityExpr(Operators.EQ, ee, re); :}
516
517        | EqualityExpr:ee NE RelationalExpr:re
518        {: RESULT = new EqualityExpr(Operators.NE, ee, re); :};
519
520RelationalExpr ::= AdditiveExpr:ae
521        {: RESULT = ae; :}
522
523        | RelationalExpr:re LT AdditiveExpr:ae
524        {: RESULT = new RelationalExpr(Operators.LT, re, ae); :}
525
526        | RelationalExpr:re GT AdditiveExpr:ae
527        {: RESULT = new RelationalExpr(Operators.GT, re, ae); :}
528
529        | RelationalExpr:re LE AdditiveExpr:ae
530        {: RESULT = new RelationalExpr(Operators.LE, re, ae); :}
531
532        | RelationalExpr:re GE AdditiveExpr:ae
533        {: RESULT = new RelationalExpr(Operators.GE, re, ae); :};
534
535AdditiveExpr ::= MultiplicativeExpr:me
536        {: RESULT = me; :}
537
538        | AdditiveExpr:ae PLUS  MultiplicativeExpr:me
539        {: RESULT = new BinOpExpr(BinOpExpr.PLUS, ae, me); :}
540
541        | AdditiveExpr:ae MINUS MultiplicativeExpr:me
542        {: RESULT = new BinOpExpr(BinOpExpr.MINUS, ae, me); :};
543
544MultiplicativeExpr ::= UnaryExpr:ue
545        {: RESULT = ue; :}
546
547        | MultiplicativeExpr:me MULT UnaryExpr:ue
548        {: RESULT = new BinOpExpr(BinOpExpr.TIMES, me, ue); :}
549
550        | MultiplicativeExpr:me DIV UnaryExpr:ue
551        {: RESULT = new BinOpExpr(BinOpExpr.DIV, me, ue); :}
552
553        | MultiplicativeExpr:me MOD UnaryExpr:ue
554        {: RESULT = new BinOpExpr(BinOpExpr.MOD, me, ue); :};
555
556UnaryExpr ::= UnionExpr:ue
557        {: RESULT = ue; :}
558
559        | MINUS UnaryExpr:ue
560        {: RESULT = new UnaryOpExpr(ue); :};
561
562UnionExpr ::= PathExpr:pe
563        {: RESULT = pe; :}
564
565        | PathExpr:pe VBAR UnionExpr:rest
566        {: RESULT = new UnionPathExpr(pe, rest); :};
567
568PathExpr ::= LocationPath:lp
569        {: RESULT = lp; :}
570
571        | FilterExpr:fexp
572        {: RESULT = fexp; :}
573
574        | FilterExpr:fexp SLASH RelativeLocationPath:rlp
575        {: RESULT = new FilterParentPath(fexp, rlp); :}
576
577        | FilterExpr:fexp DSLASH RelativeLocationPath:rlp
578        {:
579           //
580	   // Expand '//' into '/descendant-or-self::node()/' or
581	   // into /descendant-or-self::*/
582	   //
583	   int nodeType = DOM.NO_TYPE;
584	   if (rlp instanceof Step &&
585	       parser.isElementAxis(((Step) rlp).getAxis()))
586	   {
587	       nodeType = DTM.ELEMENT_NODE;
588	   }
589           final Step step = new Step(Axis.DESCENDANTORSELF, nodeType, null);
590           FilterParentPath fpp = new FilterParentPath(fexp, step);
591           fpp = new FilterParentPath(fpp, rlp);
592           if (fexp instanceof KeyCall == false) {
593               fpp.setDescendantAxis();
594	   }
595           RESULT = fpp;
596        :};
597
598LocationPath ::= RelativeLocationPath:rlp
599        {: RESULT = rlp; :}
600
601        | AbsoluteLocationPath:alp
602        {: RESULT = alp; :};
603
604RelativeLocationPath ::= Step:step
605        {: RESULT = step; :}
606
607        | RelativeLocationPath:rlp SLASH Step:step
608        {:
609        if (rlp instanceof Step && ((Step) rlp).isAbbreviatedDot()) {
610              RESULT = step;       // Remove './' from the middle
611        }
612        else if (((Step) step).isAbbreviatedDot()) {
613              RESULT = rlp;        // Remove '/.' from the end
614        }
615        else {
616             RESULT =
617                new ParentLocationPath((RelativeLocationPath) rlp, step);
618           }
619        :}
620
621        | AbbreviatedRelativeLocationPath:arlp
622        {: RESULT = arlp; :};
623
624AbsoluteLocationPath ::= SLASH
625        {: RESULT = new AbsoluteLocationPath(); :}
626
627        | SLASH RelativeLocationPath:rlp
628        {: RESULT = new AbsoluteLocationPath(rlp); :}
629
630        | AbbreviatedAbsoluteLocationPath:aalp
631        {: RESULT = aalp; :};
632
633AbbreviatedRelativeLocationPath ::= RelativeLocationPath:rlp DSLASH Step:step
634        {:
635	   final Step right  = (Step)step;
636           final int  axis   = right.getAxis();
637           final int  type   = right.getNodeType();
638           final Vector predicates = right.getPredicates();
639
640           if ((axis == Axis.CHILD) && (type != NodeTest.ATTRIBUTE)) {
641               // Compress './/child:E' into 'descendant::E' - if possible
642               if (predicates == null) {
643                   right.setAxis(Axis.DESCENDANT);
644                   if (rlp instanceof Step && ((Step)rlp).isAbbreviatedDot()) {
645	               RESULT = right;
646                   }
647                   else {
648                       // Expand 'rlp//child::E' into 'rlp/descendant::E'
649                       RelativeLocationPath left = (RelativeLocationPath)rlp;
650	               RESULT = new ParentLocationPath(left, right);
651                   }
652               }
653               else {
654                   // Expand './/step' -> 'descendant-or-self::*/step'
655                   if (rlp instanceof Step && ((Step)rlp).isAbbreviatedDot()) {
656                       Step left = new Step(Axis.DESCENDANTORSELF,
657			    DTM.ELEMENT_NODE, null);
658                       RESULT = new ParentLocationPath(left, right);
659                   }
660                   else {
661                       // Expand 'rlp//step' -> 'rlp/descendant-or-self::*/step'
662                       RelativeLocationPath left = (RelativeLocationPath)rlp;
663                       Step mid = new Step(Axis.DESCENDANTORSELF,
664			    DTM.ELEMENT_NODE, null);
665                       ParentLocationPath ppl = new ParentLocationPath(mid, right);
666                       RESULT = new ParentLocationPath(left, ppl);
667                   }
668               }
669           }
670           else if ((axis == Axis.ATTRIBUTE) || (type == NodeTest.ATTRIBUTE)) {
671               // Expand 'rlp//step' -> 'rlp/descendant-or-self::*/step'
672               RelativeLocationPath left = (RelativeLocationPath)rlp;
673               Step middle = new Step(Axis.DESCENDANTORSELF,
674		    DTM.ELEMENT_NODE, null);
675               ParentLocationPath ppl = new ParentLocationPath(middle, right);
676               RESULT = new ParentLocationPath(left, ppl);
677	   }
678	   else {
679	       // Expand 'rlp//step' -> 'rlp/descendant-or-self::node()/step'
680               RelativeLocationPath left = (RelativeLocationPath)rlp;
681	       Step middle = new Step(Axis.DESCENDANTORSELF,
682		    DOM.NO_TYPE, null);
683               ParentLocationPath ppl = new ParentLocationPath(middle, right);
684	       RESULT = new ParentLocationPath(left, ppl);
685	   }
686        :};
687
688
689AbbreviatedAbsoluteLocationPath ::= DSLASH RelativeLocationPath:rlp
690        {:
691           //
692	   // Expand '//' into '/descendant-or-self::node()/' or
693	   // into /descendant-or-self::*/
694	   //
695	   int nodeType = DOM.NO_TYPE;
696	   if (rlp instanceof Step &&
697	       parser.isElementAxis(((Step) rlp).getAxis()))
698	   {
699	       nodeType = DTM.ELEMENT_NODE;
700	   }
701	   final Step step = new Step(Axis.DESCENDANTORSELF, nodeType, null);
702	   RESULT = new AbsoluteLocationPath(parser.insertStep(step,
703				(RelativeLocationPath) rlp));
704	:};
705
706Step ::= NodeTest:ntest
707        {:
708            if (ntest instanceof Step) {
709                RESULT = (Step)ntest;
710            }
711            else {
712		RESULT = new Step(Axis.CHILD,
713                             parser.findNodeType(Axis.CHILD, ntest),
714                             null);
715            }
716        :}
717
718        | NodeTest:ntest Predicates:pp
719        {:
720            if (ntest instanceof Step) {
721                Step step = (Step)ntest;
722                step.addPredicates(pp);
723                RESULT = (Step)ntest;
724            }
725            else {
726                RESULT = new Step(Axis.CHILD,
727                             parser.findNodeType(Axis.CHILD, ntest), pp);
728            }
729        :}
730
731        | AxisSpecifier:axis NodeTest:ntest Predicates:pp
732        {: RESULT = new Step(axis.intValue(),
733                             parser.findNodeType(axis.intValue(), ntest),
734                             pp);
735        :}
736
737        | AxisSpecifier:axis NodeTest:ntest
738        {: RESULT = new Step(axis.intValue(),
739                             parser.findNodeType(axis.intValue(), ntest),
740                             null);
741        :}
742
743        | AbbreviatedStep:abbrev
744        {: RESULT = abbrev; :};
745
746AxisSpecifier ::= AxisName:an DCOLON
747        {: RESULT = an; :}
748
749        | ATSIGN
750        {: RESULT = new Integer(Axis.ATTRIBUTE); :};
751
752AxisName ::=    ANCESTOR
753        {: RESULT = new Integer(Axis.ANCESTOR); :}
754
755        | ANCESTORORSELF
756        {: RESULT = new Integer(Axis.ANCESTORORSELF); :}
757
758        | ATTRIBUTE
759        {: RESULT = new Integer(Axis.ATTRIBUTE); :}
760
761        | CHILD
762        {: RESULT = new Integer(Axis.CHILD); :}
763
764        | DESCENDANT
765        {: RESULT = new Integer(Axis.DESCENDANT); :}
766
767        | DESCENDANTORSELF
768        {: RESULT = new Integer(Axis.DESCENDANTORSELF); :}
769
770        | FOLLOWING
771        {: RESULT = new Integer(Axis.FOLLOWING); :}
772
773        | FOLLOWINGSIBLING
774        {: RESULT = new Integer(Axis.FOLLOWINGSIBLING); :}
775
776        | NAMESPACE
777        {: RESULT = new Integer(Axis.NAMESPACE); :}
778
779        | PARENT
780        {: RESULT = new Integer(Axis.PARENT); :}
781
782        | PRECEDING
783        {: RESULT = new Integer(Axis.PRECEDING); :}
784
785        | PRECEDINGSIBLING
786        {: RESULT = new Integer(Axis.PRECEDINGSIBLING); :}
787
788        | SELF
789        {: RESULT = new Integer(Axis.SELF); :};
790
791AbbreviatedStep ::= DOT
792        {: RESULT = new Step(Axis.SELF, NodeTest.ANODE, null); :}
793
794        | DDOT
795        {: RESULT = new Step(Axis.PARENT, NodeTest.ANODE, null); :};
796
797FilterExpr ::=  PrimaryExpr:primary
798        {: RESULT = primary; :}
799
800        | PrimaryExpr:primary Predicates:pp
801        {: RESULT = new FilterExpr(primary, pp); :};
802
803PrimaryExpr ::= VariableReference:vr
804        {: RESULT = vr; :}
805
806        | LPAREN Expr:ex RPAREN
807        {: RESULT = ex; :}
808
809	| Literal:string
810	{:
811	/*
812	* If the string appears to have the syntax of a QName, store
813	* namespace info in the literal expression. This is used for
814	* element-available and function-available functions, among
815	* others. Also, the default namespace must be ignored.
816	*/
817	String namespace = null;
818	final int index = string.lastIndexOf(':');
819
820	if (index > 0) {
821	    final String prefix = string.substring(0, index);
822	    namespace = parser._symbolTable.lookupNamespace(prefix);
823	}
824	RESULT = (namespace == null) ? new LiteralExpr(string)
825		     : new LiteralExpr(string, namespace);
826	:}
827
828        | INT:num
829        {:
830	   long value = num.longValue();
831	   if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
832		RESULT = new RealExpr(value);
833	   }
834	   else {
835               if (num.doubleValue() == -0)
836                   RESULT = new RealExpr(num.doubleValue());
837               else if (num.intValue() == 0)
838                   RESULT = new IntExpr(num.intValue());
839               else if (num.doubleValue() == 0.0)
840                   RESULT = new RealExpr(num.doubleValue());
841               else
842                   RESULT = new IntExpr(num.intValue());
843	   }
844        :}
845
846        | REAL:num
847        {: RESULT = new RealExpr(num.doubleValue()); :}
848
849        | FunctionCall:fc
850        {: RESULT = fc; :};
851
852VariableReference ::= DOLLAR VariableName:varName
853        {:
854            // An empty qname prefix for a variable or parameter reference
855            // should map to the null namespace and not the default URI.
856            SyntaxTreeNode node = parser.lookupName(varName);
857
858            if (node != null) {
859                if (node instanceof Variable) {
860                    RESULT = new VariableRef((Variable)node);
861                }
862                else if (node instanceof Param) {
863                    RESULT = new ParameterRef((Param)node);
864                }
865                else {
866                    RESULT = new UnresolvedRef(varName);
867                }
868            }
869
870            if (node == null) {
871                RESULT = new UnresolvedRef(varName);
872            }
873        :};
874
875FunctionCall ::= FunctionName:fname LPAREN RPAREN
876        {:
877
878          if (parser.getQNameIgnoreDefaultNs("current").equals(fname)) {
879            RESULT = new CurrentCall(fname);
880	  }
881          else if (parser.getQNameIgnoreDefaultNs("number").equals(fname)) {
882            RESULT = new NumberCall(fname, parser.EmptyArgs);
883	  }
884          else if (parser.getQNameIgnoreDefaultNs("string").equals(fname)) {
885            RESULT = new StringCall(fname, parser.EmptyArgs);
886	  }
887          else if (parser.getQNameIgnoreDefaultNs("concat").equals(fname)) {
888            RESULT = new ConcatCall(fname, parser.EmptyArgs);
889	  }
890          else if (parser.getQNameIgnoreDefaultNs("true").equals(fname)) {
891            RESULT = new BooleanExpr(true);
892	  }
893          else if (parser.getQNameIgnoreDefaultNs("false").equals(fname)) {
894            RESULT = new BooleanExpr(false);
895	  }
896          else if (parser.getQNameIgnoreDefaultNs("name").equals(fname)) {
897            RESULT = new NameCall(fname);
898	  }
899          else if (parser.getQNameIgnoreDefaultNs("generate-id").equals(fname)) {
900            RESULT = new GenerateIdCall(fname, parser.EmptyArgs);
901	  }
902          else if (parser.getQNameIgnoreDefaultNs("string-length").equals(fname)) {
903            RESULT = new StringLengthCall(fname, parser.EmptyArgs);
904	  }
905          else if (parser.getQNameIgnoreDefaultNs("position").equals(fname)) {
906            RESULT = new PositionCall(fname);
907	  }
908          else if (parser.getQNameIgnoreDefaultNs("last").equals(fname)) {
909            RESULT = new LastCall(fname);
910	  }
911          else if (parser.getQNameIgnoreDefaultNs("local-name").equals(fname)) {
912            RESULT = new LocalNameCall(fname);
913	  }
914          else if (parser.getQNameIgnoreDefaultNs("namespace-uri").equals(fname)) {
915            RESULT = new NamespaceUriCall(fname);
916	  }
917          else {
918            RESULT = new FunctionCall(fname, parser.EmptyArgs);
919	  }
920        :}
921
922        | FunctionName:fname LPAREN NonemptyArgumentList:argl RPAREN
923        {:
924          if (parser.getQNameIgnoreDefaultNs("concat").equals(fname)) {
925            RESULT = new ConcatCall(fname, argl);
926	  }
927          else if (parser.getQNameIgnoreDefaultNs("number").equals(fname)) {
928            RESULT = new NumberCall(fname, argl);
929	  }
930          else if (parser.getQNameIgnoreDefaultNs("document").equals(fname)) {
931	    parser.setMultiDocument(true);
932            RESULT = new DocumentCall(fname, argl);
933	  }
934          else if (parser.getQNameIgnoreDefaultNs("string").equals(fname)) {
935            RESULT = new StringCall(fname, argl);
936	  }
937          else if (parser.getQNameIgnoreDefaultNs("boolean").equals(fname)) {
938            RESULT = new BooleanCall(fname, argl);
939	  }
940          else if (parser.getQNameIgnoreDefaultNs("name").equals(fname)) {
941            RESULT = new NameCall(fname, argl);
942	  }
943          else if (parser.getQNameIgnoreDefaultNs("generate-id").equals(fname)) {
944            RESULT = new GenerateIdCall(fname, argl);
945	  }
946          else if (parser.getQNameIgnoreDefaultNs("not").equals(fname)) {
947            RESULT = new NotCall(fname, argl);
948	  }
949          else if (parser.getQNameIgnoreDefaultNs("format-number").equals(fname)) {
950            RESULT = new FormatNumberCall(fname, argl);
951	  }
952          else if (parser.getQNameIgnoreDefaultNs("unparsed-entity-uri").equals(fname)) {
953            RESULT = new UnparsedEntityUriCall(fname, argl);
954	  }
955          else if (parser.getQNameIgnoreDefaultNs("key").equals(fname)) {
956            RESULT = new KeyCall(fname, argl);
957	  }
958          else if (parser.getQNameIgnoreDefaultNs("id").equals(fname)) {
959            RESULT = new KeyCall(fname, argl);
960            parser.setHasIdCall(true);
961	  }
962          else if (parser.getQNameIgnoreDefaultNs("ceiling").equals(fname)) {
963            RESULT = new CeilingCall(fname, argl);
964	  }
965          else if (parser.getQNameIgnoreDefaultNs("round").equals(fname)) {
966            RESULT = new RoundCall(fname, argl);
967	  }
968          else if (parser.getQNameIgnoreDefaultNs("floor").equals(fname)) {
969            RESULT = new FloorCall(fname, argl);
970	  }
971          else if (parser.getQNameIgnoreDefaultNs("contains").equals(fname)) {
972            RESULT = new ContainsCall(fname, argl);
973	  }
974          else if (parser.getQNameIgnoreDefaultNs("string-length").equals(fname)) {
975            RESULT = new StringLengthCall(fname, argl);
976	  }
977          else if (parser.getQNameIgnoreDefaultNs("starts-with").equals(fname)) {
978            RESULT = new StartsWithCall(fname, argl);
979	  }
980          else if (parser.getQNameIgnoreDefaultNs("function-available").equals(fname)) {
981            RESULT = new FunctionAvailableCall(fname, argl);
982	  }
983          else if (parser.getQNameIgnoreDefaultNs("element-available").equals(fname)) {
984            RESULT = new ElementAvailableCall(fname, argl);
985	  }
986          else if (parser.getQNameIgnoreDefaultNs("local-name").equals(fname)) {
987            RESULT = new LocalNameCall(fname, argl);
988	  }
989          else if (parser.getQNameIgnoreDefaultNs("lang").equals(fname)) {
990            RESULT = new LangCall(fname, argl);
991	  }
992          else if (parser.getQNameIgnoreDefaultNs("namespace-uri").equals(fname)) {
993            RESULT = new NamespaceUriCall(fname, argl);
994	  }
995          else if (parser.getQName(Constants.TRANSLET_URI, "xsltc", "cast").equals(fname)) {
996            RESULT = new CastCall(fname, argl);
997	  }
998	  // Special case for extension function nodeset()
999          else if (fname.getLocalPart().equals("nodeset") || fname.getLocalPart().equals("node-set")) {
1000	    parser.setCallsNodeset(true);  // implies MultiDOM
1001            RESULT = new FunctionCall(fname, argl);
1002	  }
1003          else {
1004            RESULT = new FunctionCall(fname, argl);
1005	  }
1006    :};
1007
1008NonemptyArgumentList ::= Argument:arg
1009        {:
1010            Vector temp = new Vector();
1011            temp.addElement(arg);
1012            RESULT = temp;
1013        :}
1014
1015        | Argument:arg COMMA NonemptyArgumentList:argl
1016        {: argl.insertElementAt(arg, 0); RESULT = argl; :};
1017
1018FunctionName ::= QName:fname
1019        {:
1020	    RESULT = fname;
1021	:};
1022
1023VariableName ::= QName:vname
1024        {:
1025	    RESULT = vname;
1026	:};
1027
1028Argument ::= Expr:ex
1029        {: RESULT = ex; :};
1030
1031NodeTest ::= NameTest:nt
1032        {: RESULT = nt; :}
1033
1034        | NODE
1035        {: RESULT = new Integer(NodeTest.ANODE); :}
1036
1037        | TEXT
1038        {: RESULT = new Integer(NodeTest.TEXT); :}
1039
1040        | COMMENT
1041        {: RESULT = new Integer(NodeTest.COMMENT); :}
1042
1043        | PIPARAM LPAREN Literal:l RPAREN
1044        {:
1045           QName name = parser.getQNameIgnoreDefaultNs("name");
1046           Expression exp = new EqualityExpr(Operators.EQ,
1047                                             new NameCall(name),
1048                                             new LiteralExpr(l));
1049           Vector predicates = new Vector();
1050           predicates.addElement(new Predicate(exp));
1051           RESULT = new Step(Axis.CHILD, NodeTest.PI, predicates);
1052        :}
1053
1054        | PI
1055        {: RESULT = new Integer(NodeTest.PI); :};
1056
1057NameTest ::= STAR
1058             {: RESULT = null; :}
1059
1060             | QName:qn
1061             {: RESULT = qn; :};
1062
1063QName ::= QNAME:qname
1064        {: RESULT = parser.getQNameIgnoreDefaultNs(qname); :}
1065
1066	| DIV
1067        {: RESULT = parser.getQNameIgnoreDefaultNs("div"); :}
1068
1069        | MOD
1070        {: RESULT = parser.getQNameIgnoreDefaultNs("mod"); :}
1071
1072        | KEY
1073        {: RESULT = parser.getQNameIgnoreDefaultNs("key"); :}
1074
1075        | ANCESTOR
1076        {: RESULT = parser.getQNameIgnoreDefaultNs("child"); :}
1077
1078        | ANCESTORORSELF
1079        {: RESULT = parser.getQNameIgnoreDefaultNs("ancestor-or-self"); :}
1080
1081        | ATTRIBUTE
1082        {: RESULT = parser.getQNameIgnoreDefaultNs("attribute"); :}
1083
1084        | CHILD
1085        {: RESULT = parser.getQNameIgnoreDefaultNs("child"); :}
1086
1087        | DESCENDANT
1088        {: RESULT = parser.getQNameIgnoreDefaultNs("decendant"); :}
1089
1090        | DESCENDANTORSELF
1091        {: RESULT = parser.getQNameIgnoreDefaultNs("decendant-or-self"); :}
1092
1093        | FOLLOWING
1094        {: RESULT = parser.getQNameIgnoreDefaultNs("following"); :}
1095
1096        | FOLLOWINGSIBLING
1097        {: RESULT = parser.getQNameIgnoreDefaultNs("following-sibling"); :}
1098
1099        | NAMESPACE
1100        {: RESULT = parser.getQNameIgnoreDefaultNs("namespace"); :}
1101
1102        | PARENT
1103        {: RESULT = parser.getQNameIgnoreDefaultNs("parent"); :}
1104
1105        | PRECEDING
1106        {: RESULT = parser.getQNameIgnoreDefaultNs("preceding"); :}
1107
1108        | PRECEDINGSIBLING
1109        {: RESULT = parser.getQNameIgnoreDefaultNs("preceding-sibling"); :}
1110
1111        | SELF
1112        {: RESULT = parser.getQNameIgnoreDefaultNs("self"); :}
1113
1114        | ID
1115        {: RESULT = parser.getQNameIgnoreDefaultNs("id"); :};
1116
1117