| /* |
| * @(#)$Id$ |
| * |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 2001 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xalan" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2001, Sun |
| * Microsystems., http://www.sun.com. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| * @author Jacek Ambroziak |
| * @author Santiago Pericas-Geertsen |
| * @author Morten Jorgensen |
| * @author G. Todd Miller |
| * |
| */ |
| |
| package org.apache.xalan.xsltc.compiler; |
| |
| import java.util.Stack; |
| import java.util.Vector; |
| import java.io.StringReader; |
| import java_cup.runtime.*; |
| |
| import org.apache.xalan.xsltc.dom.Axis; |
| import org.apache.xalan.xsltc.runtime.Operators; |
| import org.apache.xalan.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 getQName(String name) { |
| return _parser.getQName(name); |
| } |
| |
| public void setMultiDocument(boolean flag) { |
| _xsltc.setMultiDocument(flag); |
| } |
| |
| public void setCallsNodeset(boolean flag) { |
| _xsltc.setCallsNodeset(flag); |
| } |
| |
| public int findNodeType(int axis, Object test) { |
| |
| if (test == null) { // * |
| if (axis == Axis.ATTRIBUTE) |
| return NodeTest.ATTRIBUTE; |
| else if (axis == Axis.NAMESPACE) |
| return -1; |
| else |
| return NodeTest.ELEMENT; |
| } |
| else if (test instanceof Integer) { |
| return ((Integer)test).intValue(); |
| } |
| else { |
| QName name = (QName)test; |
| |
| if (axis == Axis.NAMESPACE) { |
| if (name.toString().equals("*")) |
| return -1; |
| else |
| return _xsltc.registerNamespace(name); |
| } |
| |
| if (name.getPrefix() == null || name.getNamespace() == null) { |
| final String local = name.getLocalPart(); |
| if (local.equals("*")) { |
| if (axis == Axis.ATTRIBUTE) |
| return(NodeTest.ATTRIBUTE); |
| else |
| return(NodeTest.ELEMENT); |
| } |
| else if (local.equals("@*")) |
| return(NodeTest.ATTRIBUTE); |
| name = new QName(null,null,local); |
| } |
| if (axis == Axis.ATTRIBUTE) { |
| return _xsltc.registerAttribute(name); |
| } |
| else { |
| return _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 |
| } |
| :} |
| |
| 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; |
| 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, STAR; |
| 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); :} |
| |
| | ProcessingInstructionPattern:pip |
| {: RESULT = pip; :} |
| |
| | ProcessingInstructionPattern:pip Predicates:pp |
| {: RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp); :} |
| |
| | 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); :} |
| |
| | 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 = new StepPattern(Axis.CHILD, |
| parser.findNodeType(Axis.CHILD, nt), |
| null); |
| :} |
| |
| | NodeTestPattern:nt Predicates:pp |
| {: RESULT = new StepPattern(Axis.CHILD, |
| parser.findNodeType(Axis.CHILD, nt), |
| pp); |
| :} |
| |
| | ChildOrAttributeAxisSpecifier:axis NodeTestPattern:nt |
| {: RESULT=new StepPattern(axis.intValue(), |
| parser.findNodeType(axis.intValue(), nt), |
| null); |
| :} |
| |
| | ChildOrAttributeAxisSpecifier:axis |
| NodeTestPattern:nt Predicates:pp |
| {: RESULT = new StepPattern(axis.intValue(), |
| parser.findNodeType(axis.intValue(),nt), |
| 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 STAR 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()/' |
| Step step = new Step(Axis.DESCENDANTORSELF, NodeTest.ANODE, null); |
| FilterParentPath fpp = new FilterParentPath(fexp, step); |
| fpp = new FilterParentPath(fpp, rlp); |
| if (!(fexp instanceof KeyCall)) |
| 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, -1, 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, -1, 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, -1, 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, -1, null); |
| ParentLocationPath ppl = new ParentLocationPath(middle, right); |
| RESULT = new ParentLocationPath(left, ppl); |
| } |
| :}; |
| |
| |
| AbbreviatedAbsoluteLocationPath ::= DSLASH RelativeLocationPath:rlp |
| {: |
| |
| AbsoluteLocationPath alp = null; |
| |
| Step left = new Step(Axis.DESCENDANTORSELF, -1, null); |
| |
| if (rlp instanceof ParentLocationPath) { |
| ParentLocationPath plp = new ParentLocationPath(left, rlp); |
| alp = new AbsoluteLocationPath(plp); |
| } |
| else if (rlp instanceof Step) { |
| Step right = (Step)rlp; |
| alp = new AbsoluteLocationPath(new ParentLocationPath(left, right)); |
| } |
| else { |
| // Don't think we'll ever get here... |
| Step right = new Step(Axis.CHILD, NodeTest.ELEMENT, null); |
| alp = new AbsoluteLocationPath(new ParentLocationPath(left, right)); |
| } |
| |
| RESULT = new FilteredAbsoluteLocationPath(alp); |
| :}; |
| |
| |
| |
| 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. |
| */ |
| final int index = string.lastIndexOf(':'); |
| final String prefix = index >= 0 |
| ? string.substring(0, index) |
| : Constants.EMPTYSTRING; |
| String namespace = parser._symbolTable.lookupNamespace(prefix); |
| RESULT = namespace == null |
| ? new LiteralExpr(string) |
| : new LiteralExpr(string, namespace); |
| :} |
| |
| | INT:num |
| {: |
| // bug fix 3592, num comes in as a Long rather than an Integer |
| // see xpath.lex, {Digit}+ rule. |
| long value = num.longValue(); |
| if ((value < Integer.MIN_VALUE) || (value > Integer.MAX_VALUE)) { |
| RESULT = new LongExpr(num.longValue()); |
| } |
| 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 (fname == parser.getQName("current")) { |
| RESULT = new CurrentCall(fname); |
| } |
| else if (fname == parser.getQName("number")) { |
| RESULT = new NumberCall(fname, parser.EmptyArgs); |
| } |
| else if (fname == parser.getQName("string")) { |
| RESULT = new StringCall(fname, parser.EmptyArgs); |
| } |
| else if (fname == parser.getQName("concat")) { |
| RESULT = new ConcatCall(fname, parser.EmptyArgs); |
| } |
| else if (fname == parser.getQName("true")) { |
| RESULT = new BooleanExpr(true); |
| } |
| else if (fname == parser.getQName("false")) { |
| RESULT = new BooleanExpr(false); |
| } |
| else if (fname == parser.getQName("name")) { |
| RESULT = new NameCall(fname); |
| } |
| else if (fname == parser.getQName("generate-id")) { |
| RESULT = new GenerateIdCall(fname, parser.EmptyArgs); |
| } |
| else if (fname == parser.getQName("string-length")) { |
| RESULT = new StringLengthCall(fname, parser.EmptyArgs); |
| } |
| else if (fname == parser.getQName("position")) { |
| RESULT = new PositionCall(fname); |
| } |
| else if (fname == parser.getQName("last")) { |
| RESULT = new LastCall(fname); |
| } |
| else if (fname == parser.getQName("local-name")) { |
| RESULT = new LocalNameCall(fname); |
| } |
| else if (fname == parser.getQName("namespace-uri")) { |
| RESULT = new NamespaceUriCall(fname); |
| } |
| else { |
| RESULT = new FunctionCall(fname, parser.EmptyArgs); |
| } |
| :} |
| |
| | FunctionName:fname LPAREN NonemptyArgumentList:argl RPAREN |
| {: |
| if (fname == parser.getQName("concat")) { |
| RESULT = new ConcatCall(fname, argl); |
| } |
| else if (fname == parser.getQName("number")) { |
| RESULT = new NumberCall(fname, argl); |
| } |
| else if (fname == parser.getQName("document")) { |
| parser.setMultiDocument(true); |
| RESULT = new DocumentCall(fname, argl); |
| } |
| else if (fname == parser.getQName("string")) { |
| RESULT = new StringCall(fname, argl); |
| } |
| else if (fname == parser.getQName("boolean")) { |
| RESULT = new BooleanCall(fname, argl); |
| } |
| else if (fname == parser.getQName("name")) { |
| RESULT = new NameCall(fname, argl); |
| } |
| else if (fname == parser.getQName("generate-id")) { |
| RESULT = new GenerateIdCall(fname, argl); |
| } |
| else if (fname == parser.getQName("not")) { |
| RESULT = new NotCall(fname, argl); |
| } |
| else if (fname == parser.getQName("format-number")) { |
| RESULT = new FormatNumberCall(fname, argl); |
| } |
| else if (fname == parser.getQName("unparsed-entity-uri")) { |
| RESULT = new UnparsedEntityUriCall(fname, argl); |
| } |
| else if (fname == parser.getQName("key")) { |
| RESULT = new KeyCall(fname, argl); |
| } |
| else if (fname == parser.getQName("id")) { |
| RESULT = new KeyCall(fname, argl); |
| } |
| else if (fname == parser.getQName("ceiling")) { |
| RESULT = new CeilingCall(fname, argl); |
| } |
| else if (fname == parser.getQName("round")) { |
| RESULT = new RoundCall(fname, argl); |
| } |
| else if (fname == parser.getQName("floor")) { |
| RESULT = new FloorCall(fname, argl); |
| } |
| else if (fname == parser.getQName("contains")) { |
| RESULT = new ContainsCall(fname, argl); |
| } |
| else if (fname == parser.getQName("string-length")) { |
| RESULT = new StringLengthCall(fname, argl); |
| } |
| else if (fname == parser.getQName("starts-with")) { |
| RESULT = new StartsWithCall(fname, argl); |
| } |
| else if (fname == parser.getQName("function-available")) { |
| RESULT = new FunctionAvailableCall(fname, argl); |
| } |
| else if (fname == parser.getQName("element-available")) { |
| RESULT = new ElementAvailableCall(fname, argl); |
| } |
| else if (fname == parser.getQName("local-name")) { |
| RESULT = new LocalNameCall(fname, argl); |
| } |
| else if (fname == parser.getQName("lang")) { |
| RESULT = new LangCall(fname, argl); |
| } |
| else if (fname == parser.getQName("namespace-uri")) { |
| RESULT = new NamespaceUriCall(fname, argl); |
| } |
| // Special case for extension function nodeset() |
| else if (fname.getLocalPart().equals("nodeset")) { |
| 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 |
| {: |
| fname.clearDefaultNamespace(); |
| RESULT = fname; |
| :}; |
| |
| VariableName ::= QName:vname |
| {: |
| vname.clearDefaultNamespace(); |
| 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.getQName("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); |
| //RESULT = new Integer(NodeTest.PI); |
| :} |
| |
| | PI |
| {: RESULT = new Integer(NodeTest.PI); :}; |
| |
| NameTest ::= STAR |
| {: RESULT = null; :} |
| |
| | QName:qn |
| {: RESULT = qn; :}; |
| |
| QName ::= QNAME:qname |
| {: RESULT = parser.getQName(qname); :} |
| |
| | DIV |
| {: RESULT = parser.getQName("div"); :} |
| |
| | MOD |
| {: RESULT = parser.getQName("mod"); :} |
| |
| | KEY |
| {: RESULT = parser.getQName("key"); :} |
| |
| | ANCESTOR |
| {: RESULT = parser.getQName("child"); :} |
| |
| | ANCESTORORSELF |
| {: RESULT = parser.getQName("ancestor-or-self"); :} |
| |
| | ATTRIBUTE |
| {: RESULT = parser.getQName("attribute"); :} |
| |
| | CHILD |
| {: RESULT = parser.getQName("child"); :} |
| |
| | DESCENDANT |
| {: RESULT = parser.getQName("decendant"); :} |
| |
| | DESCENDANTORSELF |
| {: RESULT = parser.getQName("decendant-or-self"); :} |
| |
| | FOLLOWING |
| {: RESULT = parser.getQName("following"); :} |
| |
| | FOLLOWINGSIBLING |
| {: RESULT = parser.getQName("following-sibling"); :} |
| |
| | NAMESPACE |
| {: RESULT = parser.getQName("namespace"); :} |
| |
| | PARENT |
| {: RESULT = parser.getQName("parent"); :} |
| |
| | PRECEDING |
| {: RESULT = parser.getQName("preceding"); :} |
| |
| | PRECEDINGSIBLING |
| {: RESULT = parser.getQName("preceding-sibling"); :} |
| |
| | SELF |
| {: RESULT = parser.getQName("self"); :} |
| |
| | ID |
| {: RESULT = parser.getQName("id"); :}; |
| |