001/* ASTPtUnionConstructNode represents record construction in the parse tree. 002 003 Copyright (c) 2006-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 027 028 Created : June 2005 029 030 */ 031package ptolemy.data.expr; 032 033import java.util.HashSet; 034import java.util.Iterator; 035import java.util.LinkedList; 036import java.util.List; 037import java.util.Map; 038import java.util.Set; 039 040import ptolemy.kernel.util.IllegalActionException; 041 042////////////////////////////////////////////////////////////////////////// 043////ASTPtUnionConstructNode 044 045/** 046 The parse tree created from the expression string consists of a 047 hierarchy of node objects. This class represents union construction using 048 the following syntax: <code>{|foo = "abc"|}</code>. The result of 049 parsing and evaluating this expression is a union token with the label 050 <i>foo</i>, and the corresponding value is a StringToken of value "abc". 051 052 When using an expression to specify a union type, multiple labels 053 are allowed: <code>{|foo = string, bar = int|}</code>, which is a union 054 type with two alternatives: one labeled <i>foo</i> with type string, one 055 labeled <i>bar</i> with type integer. 056 057 FIXME: ambiguity 058 059 @author Xiaojun Liu 060 @version $Id$ 061 @since Ptolemy II 5.2 062 @Pt.ProposedRating Yellow (liuxj) 063 @Pt.AcceptedRating Red (cxh) 064 @see ptolemy.data.expr.ASTPtRootNode 065 @see ptolemy.data.expr.PtParser 066 @see ptolemy.data.Token 067 */ 068public class ASTPtUnionConstructNode extends ASTPtRootNode { 069 public ASTPtUnionConstructNode(int id) { 070 super(id); 071 } 072 073 public ASTPtUnionConstructNode(PtParser p, int id) { 074 super(p, id); 075 } 076 077 /** Return the list of label names for this union construct. 078 * The order of the list is not meaningful. 079 * @return The list of label names. 080 */ 081 public List getLabelNames() { 082 return _labelNames; 083 } 084 085 /** Return true if this node is (hierarchically) congruent to the 086 * given node, under the given renaming of bound identifiers. 087 * Derived classes should extend this method to add additional 088 * necessary congruency checks. 089 * @param node The node to compare to. 090 * @param renaming A map from String to String that gives a 091 * renaming from identifiers in this node to identifiers in the 092 * given node. 093 */ 094 @Override 095 public boolean isCongruent(ASTPtRootNode node, Map renaming) { 096 // Note: we don't call super.isCongruent(), which checks for ordered 097 // congruence of the children. 098 // Check to see that they are the same kind of node. 099 if (node._id != _id) { 100 return false; 101 } 102 103 ASTPtRecordConstructNode recordNode = (ASTPtRecordConstructNode) node; 104 105 // Empty records are allowed (Are they?) 106 if (recordNode._fieldNames == null && _labelNames == null) { 107 return true; 108 } 109 110 // But both must be empty 111 if (recordNode._fieldNames == null || _labelNames == null) { 112 return false; 113 } 114 115 // Check that they have the same number of fields. 116 if (recordNode._fieldNames.size() != _labelNames.size()) { 117 return false; 118 } 119 120 // The field names must be the same. 121 // Not use set for unordered comparison. 122 // Note that field names are not renamed! 123 Set nameSet = new HashSet(_labelNames); 124 Set nodeNameSet = new HashSet( 125 ((ASTPtRecordConstructNode) node)._fieldNames); 126 127 if (!nameSet.equals(nodeNameSet)) { 128 return false; 129 } 130 131 // Check that their children are congruent, under renaming. 132 Iterator fieldNames = _labelNames.iterator(); 133 Iterator children = _children.iterator(); 134 135 while (fieldNames.hasNext()) { 136 String fieldName = (String) fieldNames.next(); 137 ASTPtRootNode child = (ASTPtRootNode) children.next(); 138 int nodeIndex = recordNode._fieldNames.indexOf(fieldName); 139 ASTPtRootNode nodeChild = (ASTPtRootNode) recordNode._children 140 .get(nodeIndex); 141 142 if (!child.isCongruent(nodeChild, renaming)) { 143 return false; 144 } 145 } 146 147 return true; 148 } 149 150 /** Traverse this node with the given visitor. 151 */ 152 @Override 153 public void visit(ParseTreeVisitor visitor) throws IllegalActionException { 154 visitor.visitUnionConstructNode(this); 155 } 156 157 /** The list of field names for the record. 158 */ 159 protected LinkedList _labelNames = new LinkedList(); 160}