001: /* Copyright (c) 2006, Sun Microsystems, Inc.
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * * Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * * Redistributions in binary form must reproduce the above copyright
010: * notice, this list of conditions and the following disclaimer in the
011: * documentation and/or other materials provided with the distribution.
012: * * Neither the name of the Sun Microsystems, Inc. nor the names of its
013: * contributors may be used to endorse or promote products derived from
014: * this software without specific prior written permission.
015: *
016: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
017: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
018: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
019: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
020: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
021: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
022: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
023: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
024: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
025: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
026: * THE POSSIBILITY OF SUCH DAMAGE.
027: */
028: package org.javacc.jjtree;
029:
030: import java.util.Enumeration;
031: import java.util.Hashtable;
032:
033: public class NodeScope {
034: private ASTProduction production;
035: private ASTNodeDescriptor node_descriptor;
036:
037: private String closedVar;
038: private String exceptionVar;
039: private String nodeVar;
040: private int scopeNumber;
041:
042: NodeScope(ASTProduction p, ASTNodeDescriptor n) {
043: production = p;
044:
045: if (n == null) {
046: String nm = production.name;
047: if (JJTreeOptions.getNodeDefaultVoid()) {
048: nm = "void";
049: }
050: node_descriptor = ASTNodeDescriptor.indefinite(nm);
051: } else {
052: node_descriptor = n;
053: }
054:
055: scopeNumber = production.getNodeScopeNumber(this );
056: nodeVar = constructVariable("n");
057: closedVar = constructVariable("c");
058: exceptionVar = constructVariable("e");
059: }
060:
061: boolean isVoid() {
062: return node_descriptor.isVoid();
063: }
064:
065: ASTNodeDescriptor getNodeDescriptor() {
066: return node_descriptor;
067: }
068:
069: String getNodeDescriptorText() {
070: return node_descriptor.getDescriptor();
071: }
072:
073: String getNodeVariable() {
074: return nodeVar;
075: }
076:
077: private String constructVariable(String id) {
078: String s = "000" + scopeNumber;
079: return "jjt" + id + s.substring(s.length() - 3, s.length());
080: }
081:
082: boolean usesCloseNodeVar() {
083: return true;
084: }
085:
086: void insertOpenNodeDeclaration(IO io, String indent) {
087: insertOpenNodeCode(io, indent);
088: }
089:
090: void insertOpenNodeCode(IO io, String indent) {
091: String type = node_descriptor.getNodeType();
092: final String nodeClass;
093: if (JJTreeOptions.getNodeClass().length() > 0
094: && !JJTreeOptions.getMulti()) {
095: nodeClass = JJTreeOptions.getNodeClass();
096: } else {
097: nodeClass = type;
098: }
099:
100: /* Ensure that there is a template definition file for the node
101: type. */
102: NodeFiles.ensure(io, type);
103:
104: io.print(indent + nodeClass + " " + nodeVar + " = ");
105: String p = JJTreeOptions.getStatic() ? "null" : "this";
106: String parserArg = JJTreeOptions.getNodeUsesParser() ? (p + ", ")
107: : "";
108:
109: if (JJTreeOptions.getNodeFactory().equals("*")) {
110: // Old-style multiple-implementations.
111: io.println("(" + nodeClass + ")" + nodeClass
112: + ".jjtCreate(" + parserArg
113: + node_descriptor.getNodeId() + ");");
114: } else if (JJTreeOptions.getNodeFactory().length() > 0) {
115: io.println("(" + nodeClass + ")"
116: + JJTreeOptions.getNodeFactory() + ".jjtCreate("
117: + parserArg + node_descriptor.getNodeId() + ");");
118: } else {
119: io.println("new " + nodeClass + "(" + parserArg
120: + node_descriptor.getNodeId() + ");");
121: }
122:
123: if (usesCloseNodeVar()) {
124: io.println(indent + "boolean " + closedVar + " = true;");
125: }
126: io.println(indent + node_descriptor.openNode(nodeVar));
127: if (JJTreeOptions.getNodeScopeHook()) {
128: io
129: .println(indent + "jjtreeOpenNodeScope(" + nodeVar
130: + ");");
131: }
132:
133: if (JJTreeOptions.getTrackTokens()) {
134: io.println(indent + nodeVar
135: + ".jjtSetFirstToken(getToken(1));");
136: }
137: }
138:
139: void insertCloseNodeCode(IO io, String indent, boolean isFinal) {
140: io.println(indent + node_descriptor.closeNode(nodeVar));
141: if (usesCloseNodeVar() && !isFinal) {
142: io.println(indent + closedVar + " = false;");
143: }
144: if (JJTreeOptions.getNodeScopeHook()) {
145: io.println(indent + "jjtreeCloseNodeScope(" + nodeVar
146: + ");");
147: }
148:
149: if (JJTreeOptions.getTrackTokens()) {
150: io.println(indent + nodeVar
151: + ".jjtSetLastToken(getToken(0));");
152: }
153: }
154:
155: void insertOpenNodeAction(IO io, String indent) {
156: io.println(indent + "{");
157: insertOpenNodeCode(io, indent + " ");
158: io.println(indent + "}");
159: }
160:
161: void insertCloseNodeAction(IO io, String indent) {
162: io.println(indent + "{");
163: insertCloseNodeCode(io, indent + " ", false);
164: io.println(indent + "}");
165: }
166:
167: private void insertCatchBlocks(IO io, Enumeration thrown_names,
168: String indent) {
169: String thrown;
170: if (thrown_names.hasMoreElements()) {
171: io.println(indent + "} catch (Throwable " + exceptionVar
172: + ") {");
173:
174: if (usesCloseNodeVar()) {
175: io.println(indent + " if (" + closedVar + ") {");
176: io.println(indent + " jjtree.clearNodeScope("
177: + nodeVar + ");");
178: io.println(indent + " " + closedVar + " = false;");
179: io.println(indent + " } else {");
180: io.println(indent + " jjtree.popNode();");
181: io.println(indent + " }");
182: }
183:
184: while (thrown_names.hasMoreElements()) {
185: thrown = (String) thrown_names.nextElement();
186: io.println(indent + " if (" + exceptionVar
187: + " instanceof " + thrown + ") {");
188: io.println(indent + " throw (" + thrown + ")"
189: + exceptionVar + ";");
190: io.println(indent + " }");
191: }
192: /* This is either an Error or an undeclared Exception. If it's
193: an Error then the cast is good, otherwise we want to force
194: the user to declare it by crashing on the bad cast. */
195: io.println(indent + " throw (Error)" + exceptionVar + ";");
196: }
197:
198: }
199:
200: void tryTokenSequence(IO io, String indent, Token first, Token last) {
201: io.println(indent + "try {");
202: JJTreeNode.closeJJTreeComment(io);
203:
204: /* Print out all the tokens, converting all references to
205: `jjtThis' into the current node variable. */
206: for (Token t = first; t != last.next; t = t.next) {
207: TokenUtils.print(t, io, "jjtThis", nodeVar);
208: }
209:
210: JJTreeNode.openJJTreeComment(io, null);
211: io.println();
212:
213: Enumeration thrown_names = production.throws_list.elements();
214: insertCatchBlocks(io, thrown_names, indent);
215:
216: io.println(indent + "} finally {");
217: if (usesCloseNodeVar()) {
218: io.println(indent + " if (" + closedVar + ") {");
219: insertCloseNodeCode(io, indent + " ", true);
220: io.println(indent + " }");
221: }
222: io.println(indent + "}");
223: JJTreeNode.closeJJTreeComment(io);
224: }
225:
226: private static void findThrown(Hashtable thrown_set,
227: JJTreeNode expansion_unit) {
228: if (expansion_unit instanceof ASTBNFNonTerminal) {
229: /* Should really make the nonterminal explicitly maintain its
230: name. */
231: String nt = expansion_unit.getFirstToken().image;
232: ASTProduction prod = (ASTProduction) JJTreeGlobals.productions
233: .get(nt);
234: if (prod != null) {
235: Enumeration e = prod.throws_list.elements();
236: while (e.hasMoreElements()) {
237: String t = (String) e.nextElement();
238: thrown_set.put(t, t);
239: }
240: }
241: }
242: for (int i = 0; i < expansion_unit.jjtGetNumChildren(); ++i) {
243: JJTreeNode n = (JJTreeNode) expansion_unit.jjtGetChild(i);
244: findThrown(thrown_set, n);
245: }
246: }
247:
248: void tryExpansionUnit(IO io, String indent,
249: JJTreeNode expansion_unit) {
250: io.println(indent + "try {");
251: JJTreeNode.closeJJTreeComment(io);
252:
253: expansion_unit.print(io);
254:
255: JJTreeNode.openJJTreeComment(io, null);
256: io.println();
257:
258: Hashtable thrown_set = new Hashtable();
259: findThrown(thrown_set, expansion_unit);
260: Enumeration thrown_names = thrown_set.elements();
261: insertCatchBlocks(io, thrown_names, indent);
262:
263: io.println(indent + "} finally {");
264: if (usesCloseNodeVar()) {
265: io.println(indent + " if (" + closedVar + ") {");
266: insertCloseNodeCode(io, indent + " ", true);
267: io.println(indent + " }");
268: }
269: io.println(indent + "}");
270: JJTreeNode.closeJJTreeComment(io);
271: }
272:
273: static NodeScope getEnclosingNodeScope(Node node) {
274: if (node instanceof ASTBNFDeclaration) {
275: return ((ASTBNFDeclaration) node).node_scope;
276: }
277: for (Node n = node.jjtGetParent(); n != null; n = n
278: .jjtGetParent()) {
279: if (n instanceof ASTBNFDeclaration) {
280: return ((ASTBNFDeclaration) n).node_scope;
281: } else if (n instanceof ASTBNFNodeScope) {
282: return ((ASTBNFNodeScope) n).node_scope;
283: } else if (n instanceof ASTExpansionNodeScope) {
284: return ((ASTExpansionNodeScope) n).node_scope;
285: }
286: }
287: return null;
288: }
289:
290: }
291:
292: /*end*/
|