📄 syntaxtreenode.java
字号:
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); } } } /** * Return true if the node represents a simple RTF. * * A node is a simple RTF if all children only produce Text value. * * @param node A node * @return true if the node content can be considered as a simple RTF. */ private boolean isSimpleRTF(SyntaxTreeNode node) { Vector contents = node.getContents(); for (int i = 0; i < contents.size(); i++) { SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i); if (!isTextElement(item, false)) return false; } return true; } /** * Return true if the node represents an adaptive RTF. * * A node is an adaptive RTF if each children is a Text element * or it is <xsl:call-template> or <xsl:apply-templates>. * * @param node A node * @return true if the node content can be considered as an adaptive RTF. */ private boolean isAdaptiveRTF(SyntaxTreeNode node) { Vector contents = node.getContents(); for (int i = 0; i < contents.size(); i++) { SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i); if (!isTextElement(item, true)) return false; } return true; } /** * Return true if the node only produces Text content. * * A node is a Text element if it is Text, xsl:value-of, xsl:number, * or a combination of these nested in a control instruction (xsl:if or * xsl:choose). * * If the doExtendedCheck flag is true, xsl:call-template and xsl:apply-templates * are also considered as Text elements. * * @param node A node * @param doExtendedCheck If this flag is true, <xsl:call-template> and * <xsl:apply-templates> are also considered as Text elements. * * @return true if the node of Text type */ private boolean isTextElement(SyntaxTreeNode node, boolean doExtendedCheck) { if (node instanceof ValueOf || node instanceof Number || node instanceof Text) { return true; } else if (node instanceof If) { return doExtendedCheck ? isAdaptiveRTF(node) : isSimpleRTF(node); } else if (node instanceof Choose) { Vector contents = node.getContents(); for (int i = 0; i < contents.size(); i++) { SyntaxTreeNode item = (SyntaxTreeNode)contents.elementAt(i); if (item instanceof Text || ((item instanceof When || item instanceof Otherwise) && ((doExtendedCheck && isAdaptiveRTF(item)) || (!doExtendedCheck && isSimpleRTF(item))))) continue; else return false; } return true; } else if (doExtendedCheck && (node instanceof CallTemplate || node instanceof ApplyTemplates)) return true; else return false; } /** * 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(); boolean isSimple = isSimpleRTF(this); boolean isAdaptive = false; if (!isSimple) { isAdaptive = isAdaptiveRTF(this); } int rtfType = isSimple ? DOM.SIMPLE_RTF : (isAdaptive ? DOM.ADAPTIVE_RTF : DOM.TREE_RTF); // 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 RTF_INITIAL_SIZE nodes) //int index = cpg.addMethodref(DOM_IMPL, "<init>", "(I)V"); //il.append(new NEW(cpg.addClass(DOM_IMPL))); il.append(methodGen.loadDOM()); int index = cpg.addInterfaceMethodref(DOM_INTF, "getResultTreeFrag", "(IIZ)" + DOM_INTF_SIG); il.append(new PUSH(cpg, RTF_INITIAL_SIZE)); il.append(new PUSH(cpg, rtfType)); il.append(new PUSH(cpg, stylesheet.callsNodeset())); il.append(new INVOKEINTERFACE(index,4)); il.append(DUP); // Overwrite old handler with DOM handler index = cpg.addInterfaceMethodref(DOM_INTF, "getOutputDomBuilder", "()" + TRANSLET_OUTPUT_SIG); il.append(new INVOKEINTERFACE(index,1)); 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. // DOMAdapter is not needed if the RTF is a simple RTF and the nodeset() // function is not used. if (stylesheet.callsNodeset() && !DOM_CLASS.equals(DOM_IMPL_CLASS)) { // new com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter(DOMImpl,String[]); index = cpg.addMethodref(DOM_ADAPTER_CLASS, "<init>", "("+DOM_INTF_SIG+ "["+STRING_SIG+ "["+STRING_SIG+ "[I"+ "["+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(DUP); il.append(new ICONST(0)); il.append(new NEWARRAY(BasicType.INT)); il.append(SWAP); 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, URIS_INDEX, URIS_INDEX_SIG))); il.append(ALOAD_0); il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS, TYPES_INDEX, TYPES_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, String 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, String errorCode, String message) { final ErrorMsg error = new ErrorMsg(errorCode, message, element); parser.reportError(Constants.WARNING, error); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -