/*
 * @(#)$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 G. Todd Miller
 * @author Morten Jorensen
 * @author Erwin Bolwidt <ejb@klomp.org>
 * @author John Howard <JohnH@schemasoft.com>
 *
 */

package org.apache.xalan.xsltc.compiler;

import java.util.Vector;
import java.util.Enumeration;
import java.util.Hashtable;
import java.net.URL;

import javax.xml.parsers.*;

import org.xml.sax.*;

import org.apache.xalan.xsltc.compiler.util.Type;
import org.apache.xalan.xsltc.compiler.util.ReferenceType;
import org.apache.bcel.generic.*;
import org.apache.xalan.xsltc.compiler.util.*;


public abstract class SyntaxTreeNode implements Constants {

    // Reference to the AST parser
    private Parser _parser;

    // AST navigation pointers
    protected SyntaxTreeNode _parent;          // Parent node
    private Stylesheet       _stylesheet;      // Stylesheet ancestor node
    private Template         _template;        // Template ancestor node
    private final Vector _contents = new Vector(2); // Child nodes

    // Element description data
    protected QName _qname;                    // The element QName
    private int _line;                         // Source file line number
    protected Attributes _attributes = null;   // Attributes of this element
    private   Hashtable _prefixMapping = null; // Namespace declarations

    // Sentinel - used to denote unrecognised syntaxt tree nodes.
    protected static final SyntaxTreeNode Dummy = new AbsolutePathPattern(null);

    // These two are used for indenting nodes in the AST (debug output)
    protected static final int IndentIncrement = 4;
    private static final char[] _spaces = 
	"                                                       ".toCharArray();

    /**
     * Creates a new SyntaxTreeNode with a 'null' QName and no source file
     * line number reference.
     */
    public SyntaxTreeNode() {
	_line = 0;
	_qname = null;
    }

    /**
     * Creates a new SyntaxTreeNode with a 'null' QName.
     * @param line Source file line number reference
     */
    public SyntaxTreeNode(int line) {
	_line = line;
	_qname = null;
    }

    /**
     * Creates a new SyntaxTreeNode with no source file line number reference.
     * @param uri The element's namespace URI
     * @param prefix The element's namespace prefix
     * @param local The element's local name
     */
    public SyntaxTreeNode(String uri, String prefix, String local) {
	_line = 0;
	setQName(uri, prefix, local);
    }

    /**
     * Set the source file line number for this element
     * @param line The source file line number.
     */
    protected final void setLineNumber(int line) {
	_line = line;
    }

    /**
     * Get the source file line number for this element
     * @return The source file line number.
     */
    public final int getLineNumber() {
	return _line;
    }

    /**
     * Set the QName for the syntax tree node.
     * @param qname The QName for the syntax tree node
     */
    protected void setQName(QName qname) {
	_qname = qname;
    }

    /**
     * Set the QName for the SyntaxTreeNode
     * @param uri The element's namespace URI
     * @param prefix The element's namespace prefix
     * @param local The element's local name
     */
    protected void setQName(String uri, String prefix, String localname) {
	_qname = new QName(uri, prefix, localname);
    }

    /**
     * Set the QName for the SyntaxTreeNode
     * @param qname The QName for the syntax tree node
     */
    protected QName getQName() {
	return(_qname);
    }

    /**
     * Set the attributes for this SyntaxTreeNode.
     * @param attributes Attributes for the element. Must be passed in as an
     *                   implementation of org.xml.sax.Attributes.
     */
    protected void setAttributes(Attributes attributes) {
	_attributes = attributes;
    }

    /**
     * Returns a value for an attribute from the source element.
     * @param qname The QName of the attribute to return.
     * @return The value of the attribute of name 'qname'.
     */
    protected String getAttribute(String qname) {
	if (_attributes == null) {
	    return EMPTYSTRING;
	}
	final String value = _attributes.getValue(qname);
	return (value == null || value.equals(EMPTYSTRING)) ? 
	    EMPTYSTRING : value;
    }

    protected boolean hasAttribute(String qname) {
	return (_attributes != null && _attributes.getValue(qname) != null);
    }

    /**
     * Returns a list of all attributes declared for the element represented by
     * this syntax tree node.
     * @return Attributes for this syntax tree node
     */
    protected Attributes getAttributes() {
	return(_attributes);
    }

    /**
     * Sets the prefix mapping for the namespaces that were declared in this
     * element. This does not include all prefix mappings in scope, so one
     * may have to check ancestor elements to get all mappings that are in
     * in scope. The prefixes must be passed in as a Hashtable that maps
     * namespace prefixes (String objects) to namespace URIs (also String).
     * @param mapping The Hashtable containing the mappings.
     */
    protected void setPrefixMapping(Hashtable mapping) {
	_prefixMapping = mapping;
    }

    /**
     * Returns a Hashtable containing the prefix mappings that were declared
     * for this element. This does not include all prefix mappings in scope,
     * so one may have to check ancestor elements to get all mappings that are
     * in in scope. 
     * @return Prefix mappings (for this element only).
     */
    protected Hashtable getPrefixMapping() {
	return _prefixMapping;
    }

    /**
     * Adds a single prefix mapping to this syntax tree node.
     * @param prefix Namespace prefix.
     * @param uri Namespace URI.
     */
    protected void addPrefixMapping(String prefix, String uri) {
	if (_prefixMapping == null)
	    _prefixMapping = new Hashtable();
	_prefixMapping.put(prefix, uri);
    }

    /**
     * Returns any namespace URI that is in scope for a given prefix. This
     * method checks namespace mappings for this element, and if necessary
     * for ancestor elements as well (ie. if the prefix maps to an URI in this
     * scope then you'll definately get the URI from this method).
     * @param prefix Namespace prefix.
     * @return Namespace URI.
     */
    protected String lookupNamespace(String prefix) {
	// Initialise the output (default is 'null' for undefined)
	String uri = null;

	// First look up the prefix/uri mapping in our own hashtable...
	if (_prefixMapping != null)
	    uri = (String)_prefixMapping.get(prefix);
	// ... but if we can't find it there we ask our parent for the mapping
	if ((uri == null) && (_parent != null)) {
	    uri = _parent.lookupNamespace(prefix);
	    if ((prefix == Constants.EMPTYSTRING) && (uri == null))
		uri = Constants.EMPTYSTRING;
	}
	// ... and then we return whatever URI we've got.
	return(uri);
    }

    /**
     * Returns any namespace prefix that is mapped to a prefix in the current
     * scope. This method checks namespace mappings for this element, and if
     * necessary for ancestor elements as well (ie. if the URI is declared
     * within the current scope then you'll definately get the prefix from
     * this method). Note that this is a very slow method and consequentially
     * it should only be used strictly when needed.
     * @param uri Namespace URI.
     * @return Namespace prefix.
     */
    protected String lookupPrefix(String uri) {
	// Initialise the output (default is 'null' for undefined)
	String prefix = null;

	// First look up the prefix/uri mapping in our own hashtable...
	if ((_prefixMapping != null) &&
	    (_prefixMapping.contains(uri))) {
	    Enumeration prefixes = _prefixMapping.keys();
	    while (prefixes.hasMoreElements()) {
		prefix = (String)prefixes.nextElement();
		String mapsTo = (String)_prefixMapping.get(prefix);
		if (mapsTo.equals(uri)) return(prefix);
	    }
	}
	// ... but if we can't find it there we ask our parent for the mapping
	else if (_parent != null) {
	    prefix = _parent.lookupPrefix(uri);
	    if ((uri == Constants.EMPTYSTRING) && (prefix == null))
		prefix = Constants.EMPTYSTRING;
	}
	return(prefix);
    }

    /**
     * Set this node's parser. The parser (the XSLT parser) gives this
     * syntax tree node access to the symbol table and XPath parser.
     * @param parser The XSLT parser.
     */
    protected void setParser(Parser parser) {
	_parser = parser;
    }

    /**
     * Returns this node's XSLT parser.
     * @return The XSLT parser.
     */
    public final Parser getParser() {
	return _parser;
    }

    /**
     * Set this syntax tree node's parent node
     * @param parent The parent node.
     */
    protected void setParent(SyntaxTreeNode parent) {
	if (_parent == null)
	    _parent = parent;
    }

    /**
     * Returns this syntax tree node's parent node.
     * @return The parent syntax tree node.
     */
    protected final SyntaxTreeNode getParent() {
	return _parent;
    }

    /**
     * Returns 'true' if this syntax tree node is the Sentinal node.
     * @return 'true' if this syntax tree node is the Sentinal node.
     */
    protected final boolean isDummy() {
        return this == Dummy;
    }

    /**
     * Get the import precedence of this element. The import precedence equals
     * the import precedence of the stylesheet in which this element occured.
     * @return The import precedence of this syntax tree node.
     */
    protected int getImportPrecedence() {
	Stylesheet stylesheet = getStylesheet();
	if (stylesheet == null) return Integer.MIN_VALUE;
	return stylesheet.getImportPrecedence();
    }

    /**
     * Get the Stylesheet node that represents the <xsl:stylesheet/> element
     * that this node occured under.
     * @return The Stylesheet ancestor node of this node.
     */
    public Stylesheet getStylesheet() {
	if (_stylesheet == null) {
	    SyntaxTreeNode parent = this;
	    while (parent != null) {
		if (parent instanceof Stylesheet)
		    return((Stylesheet)parent);
		parent = parent.getParent();
	    }
	    _stylesheet = (Stylesheet)parent;
	}
	return(_stylesheet);
    }

    /**
     * Get the Template node that represents the <xsl:template/> element
     * that this node occured under. Note that this method will return 'null'
     * for nodes that represent top-level elements.
     * @return The Template ancestor node of this node or 'null'.
     */
    protected Template getTemplate() {
	if (_template == null) {
	    SyntaxTreeNode parent = this;
	    while ((parent != null) && (!(parent instanceof Template)))
		parent = parent.getParent();
	    _template = (Template)parent;
	}
	return(_template);
    }

    /**
     * Returns a reference to the XSLTC (XSLT compiler) in use.
     * @return XSLTC - XSLT compiler.
     */
    protected final XSLTC getXSLTC() {
	return _parser.getXSLTC();
    }

    /**
     * Returns the XSLT parser's symbol table.
     * @return Symbol table.
     */
    protected final SymbolTable getSymbolTable() {
	if (_parser != null)
	    return _parser.getSymbolTable();
	else
	    return null;
    }

    /**
     * Local variables that are accessible from a given syntax tree node will
     * be put on the JVM's stack. A closure is a record that contains a pointer
     * to a node's outer variable frame (not only global variables, but also
     * variables in parent nodes). This method returns true if this node's code
     * is implemented by code outside of ApplyTemplates (the only such case is
     * the Predicates class). This methid is only called by the VariableRef).
     * @return 'true' if node's code is implemented outside of ApplyTemplates
     */
    protected boolean isClosureBoundary() {
	return false;
    }

    /**
     * Parse the contents of this syntax tree nodes (child nodes, XPath
     * expressions, patterns and functions). The default behaviour is to parser
     * the syntax tree node's children (since there are no common expressions,
     * patterns, etc. that can be handled in this base class.
     * @param parser reference to the XSLT parser
     */
    public void parseContents(Parser parser) {
	parseChildren(parser);
    }

    /**
     * Parse all children of this syntax tree node. This method is normally
     * called by the parseContents() method.
     * @param parser reference to the XSLT parser
     */
    protected final void parseChildren(Parser parser) {

	Vector locals = null;	// only create when needed
	
	final int count = _contents.size();
	for (int i=0; i<count; i++) {
	    SyntaxTreeNode child = (SyntaxTreeNode)_contents.elementAt(i);
	    parser.getSymbolTable().setCurrentNode(child);
	    child.parseContents(parser);
	    // if variable or parameter, add it to scope
	    final QName varOrParamName = updateScope(parser, child);
	    if (varOrParamName != null) {
		if (locals == null) {
		    locals = new Vector(2);
		}
		locals.addElement(varOrParamName);
	    }
	}

	parser.getSymbolTable().setCurrentNode(this);

	// after the last element, remove any locals from scope
	if (locals != null) {
	    final int nLocals = locals.size();
	    for (int i = 0; i < nLocals; i++) {
		parser.removeVariable((QName)locals.elementAt(i));
	    }
	}
    }
   
    /**
     * Add a node to the current scope and return name of a variable or
     * parameter if the node represents a variable or a parameter.
     */
    protected QName updateScope(Parser parser, SyntaxTreeNode node) {
	if (node instanceof Variable) {
	    final Variable var = (Variable)node;
	    parser.addVariable(var);
	    return var.getName();
	}
	else if (node instanceof Param) {
	    final Param param = (Param)node;
	    parser.addParameter(param);
	    return param.getName();
	}
	else {
	    return null;
	}
    }

    /**
     * Type check the children of this node. The type check phase may add
     * coercions (CastExpr) to the AST.
     * @param stable The compiler/parser's symbol table
     */
    public abstract Type typeCheck(SymbolTable stable) throws TypeCheckError;

    /**
     * Call typeCheck() on all child syntax tree nodes.
     * @param stable The compiler/parser's symbol table
     */
    protected Type typeCheckContents(SymbolTable stable) throws TypeCheckError {
	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
	    item.typeCheck(stable);
	}
	return Type.Void;
    }

    /**
     * Translate this abstract syntax tree node into JVM bytecodes.
     * @param classGen BCEL Java class generator
     * @param methodGen BCEL Java method generator
     */
    public abstract void translate(ClassGenerator classGen,
				   MethodGenerator methodGen);

    /**
     * Call translate() on all child syntax tree nodes.
     * @param classGen BCEL Java class generator
     * @param methodGen BCEL Java method generator
     */
    protected void translateContents(ClassGenerator classGen,
				     MethodGenerator methodGen) {
	// Call translate() on all child nodes
	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
	    item.translate(classGen, methodGen);
	}

	// After translation, unmap any registers for any variables/parameters
	// that were declared in this scope. Performing this unmapping in the
	// same AST scope as the declaration deals with the problems of
	// references falling out-of-scope inside the for-each element.
	// (the cause of which being 'lazy' register allocation for references)
	for (int i = 0; i < n; i++) {
	    if( _contents.elementAt(i) instanceof VariableBase) {
		final VariableBase var = (VariableBase)_contents.elementAt(i);
		var.unmapRegister(methodGen);
	    }
	}
    }

    /**
     * Utility method used by parameters and variables to store result trees
     * @param classGen BCEL Java class generator
     * @param methodGen BCEL Java method generator
     */
    protected void compileResultTree(ClassGenerator classGen,
				     MethodGenerator methodGen) 
    {
	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = methodGen.getInstructionList();
	final Stylesheet stylesheet = classGen.getStylesheet();

	// Save the current handler base on the stack
	il.append(methodGen.loadHandler());

	final String DOM_CLASS = classGen.getDOMClass();

	// Create new instance of DOM class (with 64 nodes)
	int index = cpg.addMethodref(DOM_IMPL, "<init>", "(I)V");
	il.append(new NEW(cpg.addClass(DOM_IMPL)));
	il.append(DUP);
	il.append(DUP);
	il.append(new PUSH(cpg, 64));
	il.append(new INVOKESPECIAL(index));

	// Overwrite old handler with DOM handler
	index = cpg.addMethodref(DOM_IMPL,
				 "getOutputDomBuilder",
				 "()" + TRANSLET_OUTPUT_SIG);

	il.append(new INVOKEVIRTUAL(index));
	il.append(DUP);
	il.append(methodGen.storeHandler());

	// Call startDocument on the new handler
	il.append(methodGen.startDocument());

	// Instantiate result tree fragment
	translateContents(classGen, methodGen);

	// Call endDocument on the new handler
	il.append(methodGen.loadHandler());
	il.append(methodGen.endDocument());

	// Check if we need to wrap the DOMImpl object in a DOMAdapter object
	if (!DOM_CLASS.equals(DOM_IMPL_CLASS)) {
	    // new org.apache.xalan.xsltc.dom.DOMAdapter(DOMImpl,String[]);
	    index = cpg.addMethodref(DOM_ADAPTER_CLASS,
				     "<init>",
				     "("+DOM_IMPL_SIG+
				     "["+STRING_SIG+
				     "["+STRING_SIG+")V");
	    il.append(new NEW(cpg.addClass(DOM_ADAPTER_CLASS)));
	    il.append(new DUP_X1());
	    il.append(SWAP);

	    /*
	     * Give the DOM adapter an empty type mapping if the nodeset
	     * extension function is never called.
	     */
	    if (!stylesheet.callsNodeset()) {
		il.append(new ICONST(0));
		il.append(new ANEWARRAY(cpg.addClass(STRING)));
		il.append(DUP);
		il.append(new INVOKESPECIAL(index));
	    }
	    else {
		// Push name arrays on the stack
		il.append(ALOAD_0);
		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
					   NAMES_INDEX,
					   NAMES_INDEX_SIG))); 
		il.append(ALOAD_0);
		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
					   NAMESPACE_INDEX,
					   NAMESPACE_INDEX_SIG)));

		// Initialized DOM adapter
		il.append(new INVOKESPECIAL(index));

		// Add DOM adapter to MultiDOM class by calling addDOMAdapter()
		il.append(DUP);
		il.append(methodGen.loadDOM());
		il.append(new CHECKCAST(cpg.addClass(classGen.getDOMClass())));
		il.append(SWAP);
		index = cpg.addMethodref(MULTI_DOM_CLASS,
					 "addDOMAdapter",
					 "(" + DOM_ADAPTER_SIG + ")I");
		il.append(new INVOKEVIRTUAL(index));
		il.append(POP);		// ignore mask returned by addDOMAdapter
	    }
	}

	// Restore old handler base from stack
	il.append(SWAP);
	il.append(methodGen.storeHandler());
    }

    /**
     * Returns true if this expression/instruction depends on the context. By 
     * default, every expression/instruction depends on the context unless it 
     * overrides this method. Currently used to determine if result trees are 
     * compiled using procedures or little DOMs (result tree fragments).
     * @return 'true' if this node depends on the context.
     */
    protected boolean contextDependent() {
	return true;
    }

    /**
     * Return true if any of the expressions/instructions in the contents of
     * this node is context dependent.
     * @return 'true' if the contents of this node is context dependent.
     */
    protected boolean dependentContents() {
	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    final SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
	    if (item.contextDependent()) {
		return true;
	    }
	}
	return false;
    }

    /**
     * Adds a child node to this syntax tree node.
     * @param element is the new child node.
     */
    protected final void addElement(SyntaxTreeNode element) {
	_contents.addElement(element);
	element.setParent(this);
    }

    /**
     * Inserts the first child node of this syntax tree node. The existing
     * children are shifted back one position.
     * @param element is the new child node.
     */
    protected final void setFirstElement(SyntaxTreeNode element) {
	_contents.insertElementAt(element,0);
	element.setParent(this);
    }

    /**
     * Removed a child node of this syntax tree node.
     * @param element is the child node to remove.
     */
    protected final void removeElement(SyntaxTreeNode element) {
	_contents.remove(element);
	element.setParent(null);
    }

    /**
     * Returns a Vector containing all the child nodes of this node.
     * @return A Vector containing all the child nodes of this node.
     */
    protected final Vector getContents() {
	return _contents;
    }

    /**
     * Tells you if this node has any child nodes.
     * @return 'true' if this node has any children.
     */
    protected final boolean hasContents() {
	return elementCount() > 0;
    }

    /**
     * Returns the number of children this node has.
     * @return Number of child nodes.
     */
    protected final int elementCount() {
	return _contents.size();
    }

    /**
     * Returns an Enumeration of all child nodes of this node.
     * @return An Enumeration of all child nodes of this node.
     */
    protected final Enumeration elements() {
	return _contents.elements();
    }

    /**
     * Returns a child node at a given position.
     * @param pos The child node's position.
     * @return The child node.
     */
    protected final Object elementAt(int pos) {
	return _contents.elementAt(pos);
    }

    /**
     * Returns this element's last child
     * @return The child node.
     */
    protected final SyntaxTreeNode lastChild() {
	if (_contents.size() == 0) return null;
	return (SyntaxTreeNode)_contents.lastElement();
    }

    /**
     * Displays the contents of this syntax tree node (to stdout).
     * This method is intended for debugging _only_, and should be overridden
     * by all syntax tree node implementations.
     * @param indent Indentation level for syntax tree levels.
     */
    public void display(int indent) {
	displayContents(indent);
    }

    /**
     * Displays the contents of this syntax tree node (to stdout).
     * This method is intended for debugging _only_ !!!
     * @param indent Indentation level for syntax tree levels.
     */
    protected void displayContents(int indent) {
	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    SyntaxTreeNode item = (SyntaxTreeNode)_contents.elementAt(i);
	    item.display(indent);
	}
    }

    /**
     * Set the indentation level for debug output.
     * @param indent Indentation level for syntax tree levels.
     */
    protected final void indent(int indent) {
	System.out.print(new String(_spaces, 0, indent));
    }

    /**
     * Report an error to the parser.
     * @param element The element in which the error occured (normally 'this'
     * but it could also be an expression/pattern/etc.)
     * @param parser The XSLT parser to report the error to.
     * @param error The error code (from util/ErrorMsg).
     * @param message Any additional error message.
     */
    protected void reportError(SyntaxTreeNode element, Parser parser,
			       int errorCode, String message) {
	final ErrorMsg error = new ErrorMsg(errorCode, message, element);
        parser.reportError(Constants.ERROR, error);
    }

    /**
     * Report a recoverable error to the parser.
     * @param element The element in which the error occured (normally 'this'
     * but it could also be an expression/pattern/etc.)
     * @param parser The XSLT parser to report the error to.
     * @param error The error code (from util/ErrorMsg).
     * @param message Any additional error message.
     */
    protected  void reportWarning(SyntaxTreeNode element, Parser parser,
				  int errorCode, String message) {
	final ErrorMsg error = new ErrorMsg(errorCode, message, element);
        parser.reportError(Constants.WARNING, error);
    }

}
