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