KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > bsh > BSHSwitchStatement


1 /*****************************************************************************
2  * *
3  * This file is part of the BeanShell Java Scripting distribution. *
4  * Documentation and updates may be found at http://www.beanshell.org/ *
5  * *
6  * Sun Public License Notice: *
7  * *
8  * The contents of this file are subject to the Sun Public License Version *
9  * 1.0 (the "License"); you may not use this file except in compliance with *
10  * the License. A copy of the License is available at http://www.sun.com *
11  * *
12  * The Original Code is BeanShell. The Initial Developer of the Original *
13  * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
14  * (C) 2000. All Rights Reserved. *
15  * *
16  * GNU Public License Notice: *
17  * *
18  * Alternatively, the contents of this file may be used under the terms of *
19  * the GNU Lesser General Public License (the "LGPL"), in which case the *
20  * provisions of LGPL are applicable instead of those above. If you wish to *
21  * allow use of your version of this file only under the terms of the LGPL *
22  * and not to allow others to use your version of this file under the SPL, *
23  * indicate your decision by deleting the provisions above and replace *
24  * them with the notice and other provisions required by the LGPL. If you *
25  * do not delete the provisions above, a recipient may use your version of *
26  * this file under either the SPL or the LGPL. *
27  * *
28  * Patrick Niemeyer (pat@pat.net) *
29  * Author of Learning Java, O'Reilly & Associates *
30  * http://www.pat.net/~pat/ *
31  * *
32  *****************************************************************************/

33
34 package bsh;
35
36 class BSHSwitchStatement
37     extends SimpleNode
38     implements ParserConstants
39 {
40
41     public BSHSwitchStatement(int id) { super(id); }
42
43     public Object JavaDoc eval( CallStack callstack, Interpreter interpreter )
44         throws EvalError
45     {
46         int numchild = jjtGetNumChildren();
47         int child = 0;
48         SimpleNode switchExp = ((SimpleNode)jjtGetChild(child++));
49         Object JavaDoc switchVal = switchExp.eval( callstack, interpreter );
50
51         /*
52             Note: this could be made clearer by adding an inner class for the
53             cases and an object context for the child traversal.
54         */

55         // first label
56
BSHSwitchLabel label;
57         Object JavaDoc node;
58         ReturnControl returnControl=null;
59
60         // get the first label
61
if ( child >= numchild )
62             throw new EvalError("Empty switch statement.", this, callstack );
63         label = ((BSHSwitchLabel)jjtGetChild(child++));
64
65         // while more labels or blocks and haven't hit return control
66
while ( child < numchild && returnControl == null )
67         {
68             // if label is default or equals switchVal
69
if ( label.isDefault
70                 || primitiveEquals(
71                     switchVal, label.eval( callstack, interpreter ),
72                     callstack, switchExp )
73                 )
74             {
75                 // execute nodes, skipping labels, until a break or return
76
while ( child < numchild )
77                 {
78                     node = jjtGetChild(child++);
79                     if ( node instanceof BSHSwitchLabel )
80                         continue;
81                     // eval it
82
Object JavaDoc value =
83                         ((SimpleNode)node).eval( callstack, interpreter );
84
85                     // should check to disallow continue here?
86
if ( value instanceof ReturnControl ) {
87                         returnControl = (ReturnControl)value;
88                         break;
89                     }
90                 }
91             } else
92             {
93                 // skip nodes until next label
94
while ( child < numchild )
95                 {
96                     node = jjtGetChild(child++);
97                     if ( node instanceof BSHSwitchLabel ) {
98                         label = (BSHSwitchLabel)node;
99                         break;
100                     }
101                 }
102             }
103         }
104
105         if ( returnControl != null && returnControl.kind == RETURN )
106             return returnControl;
107         else
108             return Primitive.VOID;
109     }
110
111     /**
112         Helper method for testing equals on two primitive or boxable objects.
113         yuck: factor this out into Primitive.java
114     */

115     private boolean primitiveEquals(
116         Object JavaDoc switchVal, Object JavaDoc targetVal,
117         CallStack callstack, SimpleNode switchExp )
118         throws EvalError
119     {
120         if ( switchVal instanceof Primitive || targetVal instanceof Primitive )
121             try {
122                 // binaryOperation can return Primitive or wrapper type
123
Object JavaDoc result = Primitive.binaryOperation(
124                     switchVal, targetVal, ParserConstants.EQ );
125                 result = Primitive.unwrap( result );
126                 return result.equals( Boolean.TRUE );
127             } catch ( UtilEvalError e ) {
128                 throw e.toEvalError(
129                     "Switch value: "+switchExp.getText()+": ",
130                     this, callstack );
131             }
132         else
133             return switchVal.equals( targetVal );
134     }
135 }
136
137
Popular Tags