001/* A tableau for evaluating expressions interactively. 002 003 Copyright (c) 2003-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 */ 027package ptolemy.actor.gui; 028 029import java.util.Set; 030 031import ptolemy.data.Token; 032import ptolemy.data.expr.ASTPtAssignmentNode; 033import ptolemy.data.expr.ASTPtRootNode; 034import ptolemy.data.expr.ModelScope; 035import ptolemy.data.expr.Parameter; 036import ptolemy.data.expr.ParseTreeEvaluator; 037import ptolemy.data.expr.ParserScope; 038import ptolemy.data.expr.PtParser; 039import ptolemy.data.expr.Variable; 040import ptolemy.graph.InequalityTerm; 041import ptolemy.gui.ShellInterpreter; 042import ptolemy.gui.ShellTextArea; 043import ptolemy.kernel.util.Attribute; 044import ptolemy.kernel.util.IllegalActionException; 045import ptolemy.kernel.util.NameDuplicationException; 046import ptolemy.kernel.util.NamedObj; 047 048/////////////////////////////////////////////////////////////////// 049//// ExpressionShellTableau 050 051/** 052 A tableau that provides an interactive shell for evaluating expressions. 053 054 @author Christopher Hylands and Edward A. Lee 055 @version $Id$ 056 @since Ptolemy II 3.0 057 @Pt.ProposedRating Red (cxh) 058 @Pt.AcceptedRating Red (cxh) 059 @see ShellTextArea 060 @see ExpressionShellEffigy 061 */ 062public class ExpressionShellTableau extends Tableau 063 implements ShellInterpreter { 064 /** Create a new tableau. 065 * The tableau is itself an entity contained by the effigy 066 * and having the specified name. The frame is not made visible 067 * automatically. You must call show() to make it visible. 068 * @param container The containing effigy. 069 * @param name The name of this tableau within the specified effigy. 070 * @exception IllegalActionException If the tableau is not acceptable 071 * to the specified container. 072 * @exception NameDuplicationException If the container already contains 073 * an entity with the specified name. 074 */ 075 public ExpressionShellTableau(ExpressionShellEffigy container, String name) 076 throws IllegalActionException, NameDuplicationException { 077 super(container, name); 078 frame = new ExpressionShellFrame(this); 079 setFrame(frame); 080 frame.setTableau(this); 081 _evaluator = new ParseTreeEvaluator(); 082 } 083 084 /////////////////////////////////////////////////////////////////// 085 //// public methods //// 086 087 /** Evaluate the specified command. 088 * @param command The command. 089 * @return The return value of the command, or null if there is none. 090 * @exception Exception If something goes wrong processing the command. 091 */ 092 @Override 093 public String evaluateCommand(String command) throws Exception { 094 if (command.trim().equals("")) { 095 return ""; 096 } 097 098 PtParser parser = new PtParser(); 099 ASTPtRootNode node = parser.generateSimpleAssignmentParseTree(command); 100 String targetName = null; 101 102 // Figure out if we got an assignment... if so, then get the 103 // identifier name and only evaluated the expression part. 104 if (node instanceof ASTPtAssignmentNode) { 105 ASTPtAssignmentNode assignmentNode = (ASTPtAssignmentNode) node; 106 targetName = assignmentNode.getIdentifier(); 107 node = assignmentNode.getExpressionTree(); 108 } 109 110 final NamedObj model = ((ExpressionShellEffigy) getContainer()) 111 .getModel(); 112 ParserScope scope = new ModelScope() { 113 @Override 114 public ptolemy.data.Token get(String name) 115 throws IllegalActionException { 116 Variable result = getScopedVariable(null, model, name); 117 118 if (result != null) { 119 return result.getToken(); 120 } else { 121 return null; 122 } 123 } 124 125 @Override 126 public ptolemy.data.type.Type getType(String name) 127 throws IllegalActionException { 128 Variable result = getScopedVariable(null, model, name); 129 130 if (result != null) { 131 return result.getType(); 132 } else { 133 return null; 134 } 135 } 136 137 @Override 138 public InequalityTerm getTypeTerm(String name) 139 throws IllegalActionException { 140 Variable result = getScopedVariable(null, model, name); 141 142 if (result != null) { 143 return result.getTypeTerm(); 144 } else { 145 return null; 146 } 147 } 148 149 @Override 150 public Set identifierSet() { 151 return getAllScopedVariableNames(null, model); 152 } 153 }; 154 155 Token result = _evaluator.evaluateParseTree(node, scope); 156 157 // If a target was specified, instantiate a new token. 158 if (targetName != null) { 159 Attribute attribute = model.getAttribute(targetName); 160 161 if (attribute != null && !(attribute instanceof Parameter)) { 162 attribute.setContainer(null); 163 attribute = null; 164 } 165 166 if (attribute == null) { 167 attribute = new Parameter(model, targetName); 168 } 169 170 ((Parameter) attribute).setToken(result); 171 } 172 173 if (result == null) { 174 return ""; 175 } else { 176 return result.toString(); 177 } 178 } 179 180 /** Return true if the specified command is complete (ready 181 * to be interpreted). 182 * @param command The command. 183 * @return True. 184 */ 185 @Override 186 public boolean isCommandComplete(String command) { 187 return true; 188 } 189 190 /////////////////////////////////////////////////////////////////// 191 //// public variables //// 192 193 /** The associated frame. */ 194 public ExpressionShellFrame frame; 195 196 /** The contained shell. */ 197 public ShellTextArea shell; 198 199 /////////////////////////////////////////////////////////////////// 200 //// private variables //// 201 202 /** The parameter used for evaluation. */ 203 private ParseTreeEvaluator _evaluator; 204 205 /////////////////////////////////////////////////////////////////// 206 //// inner classes //// 207 208 /** A factory that creates a control panel to display an Expression Shell. 209 */ 210 public static class Factory extends TableauFactory { 211 /** Create a factory with the given name and container. 212 * @param container The container. 213 * @param name The name. 214 * @exception IllegalActionException If the container is incompatible 215 * with this attribute. 216 * @exception NameDuplicationException If the name coincides with 217 * an attribute already in the container. 218 */ 219 public Factory(NamedObj container, String name) 220 throws IllegalActionException, NameDuplicationException { 221 super(container, name); 222 } 223 224 /////////////////////////////////////////////////////////////////// 225 //// public methods //// 226 227 /** Create a new instance of ExpressionShellTableau in the specified 228 * effigy. It is the responsibility of callers of 229 * this method to check the return value and call show(). 230 * @param effigy The model effigy. 231 * @return A new control panel tableau if the effigy is 232 * a PtolemyEffigy, or null otherwise. 233 * @exception Exception If the factory should be able to create a 234 * tableau for the effigy, but something goes wrong. 235 */ 236 @Override 237 public Tableau createTableau(Effigy effigy) throws Exception { 238 // NOTE: Can create any number of tableaux within the same 239 // effigy. Is this what we want? 240 if (effigy instanceof ExpressionShellEffigy) { 241 return new ExpressionShellTableau( 242 (ExpressionShellEffigy) effigy, 243 "ExpressionShellTableau"); 244 } else { 245 return null; 246 } 247 } 248 } 249}