001/* A visitor for parse trees of the expression language that collects the set of free variables. 002 003 Copyright (c) 1998-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 025 */ 026package ptolemy.data.expr; 027 028import java.util.HashSet; 029import java.util.Set; 030 031import ptolemy.kernel.util.IllegalActionException; 032 033/////////////////////////////////////////////////////////////////// 034//// ParseTreeFreeVariableCollector 035 036/** 037 This class visits parse trees and collects the set of free variables 038 in the expression. Generally speaking, free variables are any lone 039 identifiers, and any function applications where the name of the 040 function is valid in the scope of the expression. 041 042 @author Steve Neuendorffer 043 @version $Id$ 044 @since Ptolemy II 2.1 045 @Pt.ProposedRating Red (neuendor) 046 @Pt.AcceptedRating Red (cxh) 047 @see ptolemy.data.expr.ASTPtRootNode 048 */ 049public class ParseTreeFreeVariableCollector extends AbstractParseTreeVisitor { 050 /////////////////////////////////////////////////////////////////// 051 //// public methods //// 052 053 /** Return the set of names of free variables in the given parse 054 * tree. 055 * @param node the node. 056 * @return A set of strings. 057 * @exception IllegalActionException If thrown while collecting 058 * the variables 059 */ 060 public Set collectFreeVariables(ASTPtRootNode node) 061 throws IllegalActionException { 062 return collectFreeVariables(node, null); 063 } 064 065 public Set collectFreeVariables(ASTPtRootNode node, ParserScope scope) 066 throws IllegalActionException { 067 Set set = new HashSet(); 068 _set = set; 069 _scope = scope; 070 node.visit(this); 071 _scope = null; 072 _set = null; 073 return set; 074 } 075 076 @Override 077 public void visitArrayConstructNode(ASTPtArrayConstructNode node) 078 throws IllegalActionException { 079 _visitAllChildren(node); 080 } 081 082 @Override 083 public void visitBitwiseNode(ASTPtBitwiseNode node) 084 throws IllegalActionException { 085 _visitAllChildren(node); 086 } 087 088 @Override 089 public void visitFunctionApplicationNode(ASTPtFunctionApplicationNode node) 090 throws IllegalActionException { 091 _visitAllChildren(node); 092 } 093 094 @Override 095 public void visitFunctionDefinitionNode(ASTPtFunctionDefinitionNode node) 096 throws IllegalActionException { 097 node.getExpressionTree().visit(this); 098 _set.removeAll(node.getArgumentNameList()); 099 } 100 101 @Override 102 public void visitFunctionalIfNode(ASTPtFunctionalIfNode node) 103 throws IllegalActionException { 104 _visitAllChildren(node); 105 } 106 107 @Override 108 public void visitLeafNode(ASTPtLeafNode node) 109 throws IllegalActionException { 110 if (node.isConstant() && node.isEvaluated()) { 111 return; 112 } 113 114 _set.add(node.getName()); 115 } 116 117 @Override 118 public void visitLogicalNode(ASTPtLogicalNode node) 119 throws IllegalActionException { 120 _visitAllChildren(node); 121 } 122 123 @Override 124 public void visitMatrixConstructNode(ASTPtMatrixConstructNode node) 125 throws IllegalActionException { 126 _visitAllChildren(node); 127 } 128 129 @Override 130 public void visitMethodCallNode(ASTPtMethodCallNode node) 131 throws IllegalActionException { 132 _visitAllChildren(node); 133 } 134 135 @Override 136 public void visitPowerNode(ASTPtPowerNode node) 137 throws IllegalActionException { 138 _visitAllChildren(node); 139 } 140 141 @Override 142 public void visitProductNode(ASTPtProductNode node) 143 throws IllegalActionException { 144 _visitAllChildren(node); 145 } 146 147 @Override 148 public void visitRecordConstructNode(ASTPtRecordConstructNode node) 149 throws IllegalActionException { 150 _visitAllChildren(node); 151 } 152 153 @Override 154 public void visitRelationalNode(ASTPtRelationalNode node) 155 throws IllegalActionException { 156 _visitAllChildren(node); 157 } 158 159 @Override 160 public void visitShiftNode(ASTPtShiftNode node) 161 throws IllegalActionException { 162 _visitAllChildren(node); 163 } 164 165 @Override 166 public void visitSumNode(ASTPtSumNode node) throws IllegalActionException { 167 _visitAllChildren(node); 168 } 169 170 @Override 171 public void visitUnaryNode(ASTPtUnaryNode node) 172 throws IllegalActionException { 173 _visitAllChildren(node); 174 } 175 176 /////////////////////////////////////////////////////////////////// 177 //// protected methods //// 178 179 /** Return true if the given identifier is valid. 180 * @param name The identifier 181 * @return True if the given identifier is valid. 182 * @exception IllegalActionException If thrown while getting 183 * the type for the name from the scope. 184 */ 185 protected boolean _isValidName(String name) throws IllegalActionException { 186 if (_scope != null) { 187 try { 188 return _scope.getType(name) != null; 189 } catch (Exception ex) { 190 return false; 191 } 192 } else { 193 return false; 194 } 195 } 196 197 /** Loop through all of the children of this node, 198 * visiting each one of them, which will cause their token 199 * value to be determined. 200 */ 201 @Override 202 protected void _visitAllChildren(ASTPtRootNode node) 203 throws IllegalActionException { 204 int numChildren = node.jjtGetNumChildren(); 205 206 for (int i = 0; i < numChildren; i++) { 207 _visitChild(node, i); 208 } 209 } 210 211 /** Visit the child with the given index of the given node. 212 * This is usually called while visiting the given node. 213 */ 214 @Override 215 protected void _visitChild(ASTPtRootNode node, int i) 216 throws IllegalActionException { 217 ASTPtRootNode child = (ASTPtRootNode) node.jjtGetChild(i); 218 child.visit(this); 219 } 220 221 /////////////////////////////////////////////////////////////////// 222 //// protected variables //// 223 protected ParserScope _scope; 224 225 protected Set _set; 226}