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}