blob: dca1695b3825e74f0626a54c2ec377a443f55980 [file] [log] [blame]
/*
* @(#)$Id$
*
* Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the proprietary information of Sun Microsystems, Inc.
* Use is subject to license terms.
*
* @author Jacek Ambroziak
* @author Santiago Pericas-Geertsen
* @author Morten Jorgensen
*
*/
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;
/**
* 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 int findNodeType(int axis, Object test) {
if (test == null) { // *
return axis == Axis.ATTRIBUTE
? NodeTest.ATTRIBUTE
: NodeTest.ELEMENT;
}
else if (test instanceof Integer) {
return ((Integer)test).intValue();
}
else {
QName name = (QName)test;
if (name.getPrefix() == null || name.getNamespace() == null) {
final String local = name.getLocalPart();
if (local.equals("*"))
return(NodeTest.ELEMENT);
else if (local.equals("@*"))
return(NodeTest.ATTRIBUTE);
if (local.startsWith("@"))
name = new QName(null,null,local);
}
return axis == Axis.ATTRIBUTE
? _xsltc.registerAttribute(name)
: _xsltc.registerElement(name);
}
}
/**
* Parse the expression passed to the current scanner. If this
* expression contains references to local variables and it will be
* compiled in an external module (not in the main class) request
* the current template to create a new variable stack frame.
*
* @param lineNumber Line where the current expression is defined.
* @param external Set to <tt>true</tt> if this expression is
* compiled in a separate module.
*
*/
public Symbol parse(int lineNumber) throws Exception {
try {
_lineNumber = lineNumber;
return super.parse();
}
catch (IllegalCharException e) {
addError(new ErrorMsg("Illegal character '" + e.getMessage() +
"' in XPath expression.", lineNumber));
}
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.addError(error);
_parser.reportError(Constants.ERROR, error);
}
public void report_error(String message, Object info) {
// empty
}
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, PRECEDINGSIBLING;
terminal SELF, PARENT, CHILD, ATTRIBUTE, ANCESTOR, ANCESTORORSELF, DESCENDANT;
terminal DESCENDANTORSELF, FOLLOWING, FOLLOWINGSIBLING, NAMESPACE, PRECEDING;
terminal Double REAL;
terminal Integer 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 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); :};
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 nodeStep = new Step(Axis.DESCENDANTORSELF,
NodeTest.ANODE, null);
RESULT = new FilterParentPath(
new FilterParentPath(fexp, nodeStep), rlp);
:};
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
{:
Step nodeStep;
final Step temp = (Step) step;
if (temp.getAxis() == Axis.CHILD) {
// Expand 'rlp//child::E' into 'rlp/descendant::E'
nodeStep = new Step(Axis.DESCENDANT,
temp.getNodeType(),
temp.getPredicates());
if (rlp instanceof Step && ((Step) rlp).isAbbreviatedDot()) {
RESULT = nodeStep; // Remove './/' from the beginning
}
else {
RESULT = new ParentLocationPath((RelativeLocationPath) rlp,
nodeStep);
}
}
else {
// Expand 'rlp//step' into 'rlp/descendant-or-self::node()/step'
nodeStep = new Step(Axis.DESCENDANTORSELF,
NodeTest.ANODE, null);
RESULT = new ParentLocationPath(
new ParentLocationPath((RelativeLocationPath) rlp,
nodeStep), step);
}
:};
AbbreviatedAbsoluteLocationPath ::= DSLASH RelativeLocationPath:rlp
{:
// GTM bug fix 2553; 3360 (handles predicates in nodeStep2).
AbsoluteLocationPath absLocPath = null;
if (rlp instanceof ParentLocationPath) {
// GTM, bug fix 3312
Step nodeStep1 = new Step(Axis.DESCENDANTORSELF, -1, null);
ParentLocationPath parLocPath = new ParentLocationPath(nodeStep1,
rlp);
absLocPath = new AbsoluteLocationPath(parLocPath);
}
else {
int nodeType = NodeTest.ELEMENT;
int axis = Axis.CHILD;
Vector predicates = null;
if (rlp instanceof Step) {
nodeType = ((Step)rlp).getNodeType();
axis = ((Step)rlp).getAxis();
predicates = ((Step)rlp).getPredicates();
}
// create the new abs location path
Step nodeStep1 = new Step(Axis.DESCENDANTORSELF, -1, null);
Step nodeStep2 = new Step(axis, nodeType, predicates);
absLocPath = new AbsoluteLocationPath(
new ParentLocationPath(nodeStep1, nodeStep2));
}
RESULT = new FilteredAbsoluteLocationPath(absLocPath);
:};
Step ::= NodeTest:ntest
{: RESULT = new Step(Axis.CHILD,
parser.findNodeType(Axis.CHILD, ntest),
null);
:}
| NodeTest:ntest Predicates:pp
{: 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
{:
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 {
node = null;
}
}
if (node == null) {
RESULT = parser.DummyVarRef;
parser.addError(new ErrorMsg(ErrorMsg.VARUNDEF_ERR,
parser.getLineNumber(), 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);
}
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; :};
/* Is insertElement ok ? */
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); :}
| 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"); :}
| CHILD
{: RESULT = parser.getQName("child"); :}
| PARENT
{: RESULT = parser.getQName("parent"); :}
| PRECEDING
{: RESULT = parser.getQName("preceding"); :}
| ATTRIBUTE
{: RESULT = parser.getQName("attribute"); :}
| SELF
{: RESULT = parser.getQName("self"); :}
| ID
{: RESULT = parser.getQName("id"); :};