blob: adce4e3a90badcf50eff927accd9430cd8ee424f [file] [log] [blame]
/*
* @(#)$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 QName getQNameIgnoreDefaultNs(String name) {
return _parser.getQNameIgnoreDefaultNs(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
}
public RelativeLocationPath insertStep(Step step, RelativeLocationPath rlp) {
if (rlp instanceof Step) {
return new ParentLocationPath(step, (Step) rlp);
}
else if (rlp instanceof ParentLocationPath) {
final ParentLocationPath plp = (ParentLocationPath) rlp;
final RelativeLocationPath newrlp = insertStep(step, plp.getPath());
return new ParentLocationPath(newrlp, plp.getStep());
}
else {
addError(new ErrorMsg(ErrorMsg.INTERNAL_ERR, "XPathParser.insertStep"));
return rlp;
}
}
:}
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); :}
| 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);
:}
| ProcessingInstructionPattern:pip
{: RESULT = pip; :}
| ProcessingInstructionPattern:pip Predicates:pp
{: RESULT = (ProcessingInstructionPattern)pip.setPredicates(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);
:}
| ChildOrAttributeAxisSpecifier:axis ProcessingInstructionPattern:pip
{:
RESULT = pip; // TODO: report error if axis is attribute
:}
| ChildOrAttributeAxisSpecifier:axis ProcessingInstructionPattern:pip
Predicates:pp
{:
// TODO: report error if axis is attribute
RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp);
:};
NodeTestPattern ::= NameTestPattern:nt
{: RESULT = nt; :}
| NODE
{: RESULT = new Integer(NodeTest.ANODE); :}
| TEXT
{: RESULT = new Integer(NodeTest.TEXT); :}
| COMMENT
{: RESULT = new Integer(NodeTest.COMMENT); :}
| PI
{: RESULT = new Integer(NodeTest.PI); :};
NameTestPattern ::= STAR
{: RESULT = null; :}
| QName:qn
{: RESULT = qn; :};
ChildOrAttributeAxisSpecifier ::= ATSIGN
{: RESULT = new Integer(Axis.ATTRIBUTE); :}
| CHILD DCOLON
{: RESULT = new Integer(Axis.CHILD); :}
| ATTRIBUTE DCOLON
{: RESULT = new Integer(Axis.ATTRIBUTE); :};
Predicates ::= Predicate:p
{:
Vector temp = new Vector();
temp.addElement(p);
RESULT = temp;
:}
| Predicate:p Predicates:pp
{: pp.insertElementAt(p, 0); RESULT = pp; :};
Predicate ::= LBRACK Expr:e RBRACK
{:
RESULT = new Predicate(e);
:};
/* --------------------------- Expressions --------------------------------- */
Expr ::= OrExpr:ex
{: RESULT = ex; :};
OrExpr ::= AndExpr:ae
{: RESULT = ae; :}
| OrExpr:oe OR AndExpr:ae
{: RESULT = new LogicalExpr(LogicalExpr.OR, oe, ae); :};
AndExpr ::= EqualityExpr:e
{: RESULT = e; :}
| AndExpr:ae AND EqualityExpr:ee
{: RESULT = new LogicalExpr(LogicalExpr.AND, ae, ee); :};
EqualityExpr ::= RelationalExpr:re
{: RESULT = re; :}
| EqualityExpr:ee EQ RelationalExpr:re
{: RESULT = new EqualityExpr(Operators.EQ, ee, re); :}
| EqualityExpr:ee NE RelationalExpr:re
{: RESULT = new EqualityExpr(Operators.NE, ee, re); :};
RelationalExpr ::= AdditiveExpr:ae
{: RESULT = ae; :}
| RelationalExpr:re LT AdditiveExpr:ae
{: RESULT = new RelationalExpr(Operators.LT, re, ae); :}
| RelationalExpr:re GT AdditiveExpr:ae
{: RESULT = new RelationalExpr(Operators.GT, re, ae); :}
| RelationalExpr:re LE AdditiveExpr:ae
{: RESULT = new RelationalExpr(Operators.LE, re, ae); :}
| RelationalExpr:re GE AdditiveExpr:ae
{: RESULT = new RelationalExpr(Operators.GE, re, ae); :};
AdditiveExpr ::= MultiplicativeExpr:me
{: RESULT = me; :}
| AdditiveExpr:ae PLUS MultiplicativeExpr:me
{: RESULT = new BinOpExpr(BinOpExpr.PLUS, ae, me); :}
| AdditiveExpr:ae MINUS MultiplicativeExpr:me
{: RESULT = new BinOpExpr(BinOpExpr.MINUS, ae, me); :};
MultiplicativeExpr ::= UnaryExpr:ue
{: RESULT = ue; :}
| MultiplicativeExpr:me 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
{:
final Step step = new Step(Axis.DESCENDANTORSELF, -1, null);
RESULT = new FilteredAbsoluteLocationPath(
new AbsoluteLocationPath(parser.insertStep(step,
(RelativeLocationPath) rlp)));
:};
Step ::= NodeTest:ntest
{:
if (ntest instanceof Step) {
RESULT = (Step)ntest;
}
else {
RESULT = new Step(Axis.CHILD,
parser.findNodeType(Axis.CHILD, ntest),
null);
}
:}
| NodeTest:ntest Predicates:pp
{:
if (ntest instanceof Step) {
Step step = (Step)ntest;
step.addPredicates(pp);
RESULT = (Step)ntest;
}
else {
RESULT = new Step(Axis.CHILD,
parser.findNodeType(Axis.CHILD, ntest), pp);
}
:}
| AxisSpecifier:axis NodeTest:ntest Predicates:pp
{: RESULT = new Step(axis.intValue(),
parser.findNodeType(axis.intValue(), ntest),
pp);
:}
| AxisSpecifier:axis NodeTest:ntest
{: RESULT = new Step(axis.intValue(),
parser.findNodeType(axis.intValue(), ntest),
null);
:}
| AbbreviatedStep:abbrev
{: RESULT = abbrev; :};
AxisSpecifier ::= AxisName:an DCOLON
{: RESULT = an; :}
| ATSIGN
{: RESULT = new Integer(Axis.ATTRIBUTE); :};
AxisName ::= ANCESTOR
{: RESULT = new Integer(Axis.ANCESTOR); :}
| ANCESTORORSELF
{: RESULT = new Integer(Axis.ANCESTORORSELF); :}
| ATTRIBUTE
{: RESULT = new Integer(Axis.ATTRIBUTE); :}
| CHILD
{: RESULT = new Integer(Axis.CHILD); :}
| DESCENDANT
{: RESULT = new Integer(Axis.DESCENDANT); :}
| DESCENDANTORSELF
{: RESULT = new Integer(Axis.DESCENDANTORSELF); :}
| FOLLOWING
{: RESULT = new Integer(Axis.FOLLOWING); :}
| FOLLOWINGSIBLING
{: RESULT = new Integer(Axis.FOLLOWINGSIBLING); :}
| NAMESPACE
{: RESULT = new Integer(Axis.NAMESPACE); :}
| PARENT
{: RESULT = new Integer(Axis.PARENT); :}
| PRECEDING
{: RESULT = new Integer(Axis.PRECEDING); :}
| PRECEDINGSIBLING
{: RESULT = new Integer(Axis.PRECEDINGSIBLING); :}
| SELF
{: RESULT = new Integer(Axis.SELF); :};
AbbreviatedStep ::= DOT
{: RESULT = new Step(Axis.SELF, NodeTest.ANODE, null); :}
| DDOT
{: RESULT = new Step(Axis.PARENT, NodeTest.ANODE, null); :};
FilterExpr ::= PrimaryExpr:primary
{: RESULT = primary; :}
| PrimaryExpr:primary Predicates:pp
{: RESULT = new FilterExpr(primary, pp); :};
PrimaryExpr ::= VariableReference:vr
{: RESULT = vr; :}
| LPAREN Expr:ex RPAREN
{: RESULT = ex; :}
| Literal:string
{:
/*
* If the string appears to have the syntax of a QName, store
* namespace info in the literal expression. This is used for
* element-available and function-available functions, among
* others. Also, the default namespace must be ignored.
*/
String namespace = null;
final int index = string.lastIndexOf(':');
if (index > 0) {
final String prefix = string.substring(0, index);
namespace = parser._symbolTable.lookupNamespace(prefix);
}
RESULT = (namespace == null) ? new LiteralExpr(string)
: new LiteralExpr(string, namespace);
:}
| INT:num
{:
long value = num.longValue();
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
RESULT = new RealExpr(value);
}
else {
if (num.doubleValue() == -0)
RESULT = new RealExpr(num.doubleValue());
else if (num.intValue() == 0)
RESULT = new IntExpr(num.intValue());
else if (num.doubleValue() == 0.0)
RESULT = new RealExpr(num.doubleValue());
else
RESULT = new IntExpr(num.intValue());
}
:}
| REAL:num
{: RESULT = new RealExpr(num.doubleValue()); :}
| FunctionCall:fc
{: RESULT = fc; :};
VariableReference ::= DOLLAR VariableName:varName
{:
// An empty qname prefix for a variable or parameter reference
// should map to the null namespace and not the default URI.
SyntaxTreeNode node = parser.lookupName(varName);
if (node != null) {
if (node instanceof Variable) {
RESULT = new VariableRef((Variable)node);
}
else if (node instanceof Param) {
RESULT = new ParameterRef((Param)node);
}
else {
RESULT = new UnresolvedRef(varName);
}
}
if (node == null) {
RESULT = new UnresolvedRef(varName);
}
:};
FunctionCall ::= FunctionName:fname LPAREN RPAREN
{:
if (fname == parser.getQNameIgnoreDefaultNs("current")) {
RESULT = new CurrentCall(fname);
}
else if (fname == parser.getQNameIgnoreDefaultNs("number")) {
RESULT = new NumberCall(fname, parser.EmptyArgs);
}
else if (fname == parser.getQNameIgnoreDefaultNs("string")) {
RESULT = new StringCall(fname, parser.EmptyArgs);
}
else if (fname == parser.getQNameIgnoreDefaultNs("concat")) {
RESULT = new ConcatCall(fname, parser.EmptyArgs);
}
else if (fname == parser.getQNameIgnoreDefaultNs("true")) {
RESULT = new BooleanExpr(true);
}
else if (fname == parser.getQNameIgnoreDefaultNs("false")) {
RESULT = new BooleanExpr(false);
}
else if (fname == parser.getQNameIgnoreDefaultNs("name")) {
RESULT = new NameCall(fname);
}
else if (fname == parser.getQNameIgnoreDefaultNs("generate-id")) {
RESULT = new GenerateIdCall(fname, parser.EmptyArgs);
}
else if (fname == parser.getQNameIgnoreDefaultNs("string-length")) {
RESULT = new StringLengthCall(fname, parser.EmptyArgs);
}
else if (fname == parser.getQNameIgnoreDefaultNs("position")) {
RESULT = new PositionCall(fname);
}
else if (fname == parser.getQNameIgnoreDefaultNs("last")) {
RESULT = new LastCall(fname);
}
else if (fname == parser.getQNameIgnoreDefaultNs("local-name")) {
RESULT = new LocalNameCall(fname);
}
else if (fname == parser.getQNameIgnoreDefaultNs("namespace-uri")) {
RESULT = new NamespaceUriCall(fname);
}
else {
RESULT = new FunctionCall(fname, parser.EmptyArgs);
}
:}
| FunctionName:fname LPAREN NonemptyArgumentList:argl RPAREN
{:
if (fname == parser.getQNameIgnoreDefaultNs("concat")) {
RESULT = new ConcatCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("number")) {
RESULT = new NumberCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("document")) {
parser.setMultiDocument(true);
RESULT = new DocumentCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("string")) {
RESULT = new StringCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("boolean")) {
RESULT = new BooleanCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("name")) {
RESULT = new NameCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("generate-id")) {
RESULT = new GenerateIdCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("not")) {
RESULT = new NotCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("format-number")) {
RESULT = new FormatNumberCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("unparsed-entity-uri")) {
RESULT = new UnparsedEntityUriCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("key")) {
RESULT = new KeyCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("id")) {
RESULT = new KeyCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("ceiling")) {
RESULT = new CeilingCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("round")) {
RESULT = new RoundCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("floor")) {
RESULT = new FloorCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("contains")) {
RESULT = new ContainsCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("string-length")) {
RESULT = new StringLengthCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("starts-with")) {
RESULT = new StartsWithCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("function-available")) {
RESULT = new FunctionAvailableCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("element-available")) {
RESULT = new ElementAvailableCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("local-name")) {
RESULT = new LocalNameCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("lang")) {
RESULT = new LangCall(fname, argl);
}
else if (fname == parser.getQNameIgnoreDefaultNs("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
{:
final String prefix = fname.getPrefix();
if (prefix == null || prefix.equals(Constants.EMPTYSTRING)) {
fname = parser.getQNameIgnoreDefaultNs(fname.getLocalPart());
}
RESULT = fname;
:};
VariableName ::= QName:vname
{:
final String prefix = vname.getPrefix();
if (prefix == null || prefix.equals(Constants.EMPTYSTRING)) {
vname = parser.getQNameIgnoreDefaultNs(vname.getLocalPart());
}
RESULT = vname;
:};
Argument ::= Expr:ex
{: RESULT = ex; :};
NodeTest ::= NameTest:nt
{: RESULT = nt; :}
| NODE
{: RESULT = new Integer(NodeTest.ANODE); :}
| TEXT
{: RESULT = new Integer(NodeTest.TEXT); :}
| COMMENT
{: RESULT = new Integer(NodeTest.COMMENT); :}
| PIPARAM LPAREN Literal:l RPAREN
{:
QName name = parser.getQNameIgnoreDefaultNs("name");
Expression exp = new EqualityExpr(Operators.EQ,
new NameCall(name),
new LiteralExpr(l));
Vector predicates = new Vector();
predicates.addElement(new Predicate(exp));
RESULT = new Step(Axis.CHILD, NodeTest.PI, predicates);
:}
| PI
{: RESULT = new Integer(NodeTest.PI); :};
NameTest ::= STAR
{: RESULT = null; :}
| QName:qn
{: RESULT = qn; :};
QName ::= QNAME:qname
{: RESULT = parser.getQName(qname); :}
| DIV
{: RESULT = parser.getQNameIgnoreDefaultNs("div"); :}
| MOD
{: RESULT = parser.getQNameIgnoreDefaultNs("mod"); :}
| KEY
{: RESULT = parser.getQNameIgnoreDefaultNs("key"); :}
| ANCESTOR
{: RESULT = parser.getQNameIgnoreDefaultNs("child"); :}
| ANCESTORORSELF
{: RESULT = parser.getQNameIgnoreDefaultNs("ancestor-or-self"); :}
| ATTRIBUTE
{: RESULT = parser.getQNameIgnoreDefaultNs("attribute"); :}
| CHILD
{: RESULT = parser.getQNameIgnoreDefaultNs("child"); :}
| DESCENDANT
{: RESULT = parser.getQNameIgnoreDefaultNs("decendant"); :}
| DESCENDANTORSELF
{: RESULT = parser.getQNameIgnoreDefaultNs("decendant-or-self"); :}
| FOLLOWING
{: RESULT = parser.getQNameIgnoreDefaultNs("following"); :}
| FOLLOWINGSIBLING
{: RESULT = parser.getQNameIgnoreDefaultNs("following-sibling"); :}
| NAMESPACE
{: RESULT = parser.getQNameIgnoreDefaultNs("namespace"); :}
| PARENT
{: RESULT = parser.getQNameIgnoreDefaultNs("parent"); :}
| PRECEDING
{: RESULT = parser.getQNameIgnoreDefaultNs("preceding"); :}
| PRECEDINGSIBLING
{: RESULT = parser.getQNameIgnoreDefaultNs("preceding-sibling"); :}
| SELF
{: RESULT = parser.getQNameIgnoreDefaultNs("self"); :}
| ID
{: RESULT = parser.getQNameIgnoreDefaultNs("id"); :};