001/* A visitor that writes parse trees. 002 003 Copyright (c) 2002-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 OR RESEARCH IN MOTION 012 LIMITED BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, 013 INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS 014 SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA 015 OR RESEARCH IN MOTION LIMITED HAVE BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION LIMITED 019 SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 020 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 021 PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 022 BASIS, AND THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION 023 LIMITED HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 024 ENHANCEMENTS, OR MODIFICATIONS. 025 026 027 */ 028package ptolemy.data.expr; 029 030import java.io.PrintWriter; 031import java.io.StringWriter; 032import java.util.Iterator; 033import java.util.List; 034 035import ptolemy.data.StringToken; 036import ptolemy.kernel.util.IllegalActionException; 037 038/////////////////////////////////////////////////////////////////// 039//// ParseTreeWriter 040 041/** 042 This class implements a visitor that writes parse trees in the 043 expression language. 044 045 @author Steve Neuendorffer 046 @version $Id$ 047 @since Ptolemy II 2.1 048 @Pt.ProposedRating Red (neuendor) 049 @Pt.AcceptedRating Red (cxh) 050 @see ptolemy.data.expr.ASTPtRootNode 051 */ 052public class ParseTreeWriter extends AbstractParseTreeVisitor { 053 public void displayParseTree(ASTPtRootNode root) { 054 _writer = new PrintWriter(System.out); 055 056 try { 057 root.visit(this); 058 } catch (IllegalActionException ex) { 059 _writer.println(ex); 060 ex.printStackTrace(_writer); 061 } 062 } 063 064 /** Produce an expression for this parse tree. 065 * @param root The root of the parse tree. 066 * @return The expression. 067 * @exception IllegalActionException If the parse tree has an error. 068 */ 069 public String parseTreeToExpression(ASTPtRootNode root) 070 throws IllegalActionException { 071 StringWriter writer = new StringWriter(); 072 _writer = new PrintWriter(writer); 073 root.visit(this); 074 return writer.toString(); 075 } 076 077 /** Return an expression for this parse tree, or a description 078 * of the exception if an exception occurs. 079 * @param root The root of the parse tree. 080 * @return The expression. 081 */ 082 public String printParseTree(ASTPtRootNode root) { 083 StringWriter writer = new StringWriter(); 084 _writer = new PrintWriter(writer); 085 086 try { 087 root.visit(this); 088 } catch (IllegalActionException ex) { 089 _writer.println(ex); 090 ex.printStackTrace(_writer); 091 } 092 093 return writer.toString(); 094 } 095 096 /** Specify whether the expression to write is in string mode. 097 * FIXME string mode has only been implemented for leaf and sum nodes. 098 * @param stringMode True to put the expression to write in string mode. 099 */ 100 public void setStringMode(boolean stringMode) { 101 _isStringMode = stringMode; 102 } 103 104 /////////////////////////////////////////////////////////////////// 105 //// public methods //// 106 @Override 107 public void visitArrayConstructNode(ASTPtArrayConstructNode node) 108 throws IllegalActionException { 109 _writer.print("{"); 110 _printChildrenSeparated(node, ", "); 111 _writer.print("}"); 112 } 113 114 @Override 115 public void visitBitwiseNode(ASTPtBitwiseNode node) 116 throws IllegalActionException { 117 _writer.print("("); 118 _printChildrenSeparated(node, node.getOperator().image); 119 _writer.print(")"); 120 } 121 122 @Override 123 public void visitFunctionApplicationNode(ASTPtFunctionApplicationNode node) 124 throws IllegalActionException { 125 _printChild(node, 0); 126 _writer.print("("); 127 128 int n = node.jjtGetNumChildren(); 129 130 for (int i = 1; i < n - 1; ++i) { 131 _printChild(node, i); 132 _writer.print(", "); 133 } 134 135 if (n > 1) { 136 _printChild(node, n - 1); 137 } 138 139 _writer.print(")"); 140 } 141 142 @Override 143 public void visitFunctionDefinitionNode(ASTPtFunctionDefinitionNode node) 144 throws IllegalActionException { 145 // This code is duplicated with the FunctionToken. 146 _writer.print("(function("); 147 148 List args = node.getArgumentNameList(); 149 ptolemy.data.type.Type[] argTypes = node.getArgumentTypes(); 150 int n = args.size(); 151 152 for (int i = 0; i < n; i++) { 153 if (i > 0) { 154 _writer.print(", "); 155 } 156 157 _writer.print((String) args.get(i)); 158 159 ptolemy.data.type.Type type = argTypes[i]; 160 161 if (type != ptolemy.data.type.BaseType.GENERAL) { 162 _writer.print(":"); 163 _writer.print(type.toString()); 164 } 165 } 166 167 _writer.print(") "); 168 node.getExpressionTree().visit(this); 169 _writer.print(")"); 170 } 171 172 @Override 173 public void visitFunctionalIfNode(ASTPtFunctionalIfNode node) 174 throws IllegalActionException { 175 _writer.print("("); 176 _printChild(node, 0); 177 _writer.print("?"); 178 _printChild(node, 1); 179 _writer.print(":"); 180 _printChild(node, 2); 181 _writer.print(")"); 182 } 183 184 @Override 185 public void visitLeafNode(ASTPtLeafNode node) 186 throws IllegalActionException { 187 if (node.isConstant() && node.isEvaluated()) { 188 ptolemy.data.Token token = node.getToken(); 189 if (_isStringMode && (token instanceof StringToken)) { 190 _writer.print(((StringToken) token).stringValue()); 191 } else { 192 _writer.print(token.toString()); 193 } 194 } else { 195 _writer.print(node.getName()); 196 } 197 } 198 199 @Override 200 public void visitLogicalNode(ASTPtLogicalNode node) 201 throws IllegalActionException { 202 _writer.print("("); 203 _printChildrenSeparated(node, node.getOperator().image); 204 _writer.print(")"); 205 } 206 207 @Override 208 public void visitMatrixConstructNode(ASTPtMatrixConstructNode node) 209 throws IllegalActionException { 210 _writer.print("["); 211 212 int n = 0; 213 int rowCount = node.getRowCount(); 214 int columnCount = node.getColumnCount(); 215 216 for (int i = 0; i < rowCount; i++) { 217 for (int j = 0; j < columnCount; j++) { 218 _printChild(node, n++); 219 220 if (j < columnCount - 1) { 221 _writer.print(", "); 222 } 223 } 224 225 if (i < rowCount - 1) { 226 _writer.print("; "); 227 } 228 } 229 230 _writer.print("]"); 231 } 232 233 @Override 234 public void visitMethodCallNode(ASTPtMethodCallNode node) 235 throws IllegalActionException { 236 _printChild(node, 0); 237 _writer.print("."); 238 _writer.print(node.getMethodName()); 239 _writer.print("("); 240 241 if (node.jjtGetNumChildren() > 1) { 242 _printChild(node, 1); 243 244 for (int i = 2; i < node.jjtGetNumChildren(); i++) { 245 _writer.print(", "); 246 _printChild(node, i); 247 } 248 } 249 250 _writer.print(")"); 251 } 252 253 @Override 254 public void visitPowerNode(ASTPtPowerNode node) 255 throws IllegalActionException { 256 _printChildrenSeparated(node, "^"); 257 } 258 259 @Override 260 public void visitProductNode(ASTPtProductNode node) 261 throws IllegalActionException { 262 _writer.print("("); 263 _printChildrenSeparated(node, node.getLexicalTokenList()); 264 _writer.print(")"); 265 } 266 267 @Override 268 public void visitRecordConstructNode(ASTPtRecordConstructNode node) 269 throws IllegalActionException { 270 Iterator names = node.getFieldNames().iterator(); 271 if (node instanceof ASTPtOrderedRecordConstructNode) { 272 _writer.print("["); 273 } else { 274 _writer.print("{"); 275 } 276 277 if (node.jjtGetNumChildren() > 0) { 278 _writer.print(names.next()); 279 _writer.print("="); 280 _printChild(node, 0); 281 282 for (int i = 1; i < node.jjtGetNumChildren(); i++) { 283 _writer.print(", "); 284 _writer.print(names.next()); 285 _writer.print("="); 286 _printChild(node, i); 287 } 288 } 289 290 if (node instanceof ASTPtOrderedRecordConstructNode) { 291 _writer.print("]"); 292 } else { 293 _writer.print("}"); 294 } 295 } 296 297 @Override 298 public void visitRelationalNode(ASTPtRelationalNode node) 299 throws IllegalActionException { 300 _writer.print("("); 301 _printChildrenSeparated(node, node.getOperator().image); 302 _writer.print(")"); 303 } 304 305 @Override 306 public void visitShiftNode(ASTPtShiftNode node) 307 throws IllegalActionException { 308 _writer.print("("); 309 _printChildrenSeparated(node, node.getOperator().image); 310 _writer.print(")"); 311 } 312 313 @Override 314 public void visitSumNode(ASTPtSumNode node) throws IllegalActionException { 315 if (!_isStringMode) { 316 _writer.print("("); 317 } 318 _printChildrenSeparated(node, node.getLexicalTokenList()); 319 if (!_isStringMode) { 320 _writer.print(")"); 321 } 322 } 323 324 @Override 325 public void visitUnaryNode(ASTPtUnaryNode node) 326 throws IllegalActionException { 327 if (node.isMinus()) { 328 _writer.print("-"); 329 } else if (node.isNot()) { 330 _writer.print("!"); 331 } else { 332 _writer.print("~"); 333 } 334 335 _printChild(node, 0); 336 } 337 338 protected PrintWriter _writer = new PrintWriter(System.out); 339 340 private void _printChild(ASTPtRootNode node, int index) 341 throws IllegalActionException { 342 ASTPtRootNode child = (ASTPtRootNode) node.jjtGetChild(index); 343 child.visit(this); 344 } 345 346 private void _printChildrenSeparated(ASTPtRootNode node, List separatorList) 347 throws IllegalActionException { 348 Iterator separators = separatorList.iterator(); 349 350 if (node.jjtGetNumChildren() > 0) { 351 _printChild(node, 0); 352 353 for (int i = 1; i < node.jjtGetNumChildren(); i++) { 354 Token separator = (Token) separators.next(); 355 if (!_isStringMode || separator.image != null) { 356 _writer.print(separator.image); 357 } 358 _printChild(node, i); 359 } 360 } 361 } 362 363 private void _printChildrenSeparated(ASTPtRootNode node, String string) 364 throws IllegalActionException { 365 if (node.jjtGetNumChildren() > 0) { 366 _printChild(node, 0); 367 368 for (int i = 1; i < node.jjtGetNumChildren(); i++) { 369 _writer.print(string); 370 _printChild(node, i); 371 } 372 } 373 } 374 375 /** Indicates if string mode is on. */ 376 private boolean _isStringMode = false; 377 378}