001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2004 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: */
019: package xtc.tree;
020:
021: import java.util.HashMap;
022: import java.util.Iterator;
023: import java.util.Map;
024: import java.util.NoSuchElementException;
025:
026: /**
027: * A node in an abstract syntax tree or DAG.
028: *
029: * @author Robert Grimm
030: * @version $Revision: 1.1 $
031: */
032: public abstract class Node {
033:
034: /** The properties. */
035: private Map properties;
036:
037: /** The optional source location. */
038: public Location location;
039:
040: /** Create a new node. */
041: public Node() {
042: }
043:
044: /**
045: * Create a new node.
046: *
047: * @param location The source location for the new node.
048: */
049: public Node(Location location) {
050: this .location = location;
051: }
052:
053: /**
054: * Accept the specified visitor.
055: *
056: * <p />Optionally, a visitor may return a value, thus making it
057: * possible, for example, to replace nodes or to construct entirely
058: * new trees. If the specified visitor does not return a value, this
059: * method returns <code>null</code>.
060: *
061: * @param v The visitor.
062: * @return The (optional) return value.
063: * @throws VisitorException
064: * Signals that the specified visitor does not have a matching
065: * <code>visit()</code> method.
066: * @throws VisitingException
067: * Signals an exceptional condition while applying the specified
068: * visitor on this node.
069: */
070: public Object accept(Visitor v) {
071: return v.dispatch(this );
072: }
073:
074: /**
075: * Set the value of a property.
076: *
077: * @param name The property name.
078: * @param value The new property value.
079: * @return The property's old value or <code>null</code> if the
080: * property didn't have a value.
081: */
082: public Object setProperty(String name, Object value) {
083: if (null == properties) {
084: properties = new HashMap();
085: }
086: return properties.put(name, value);
087: }
088:
089: /**
090: * Test if this node has a property.
091: *
092: * @param name The property name.
093: * @return <code>true</code> if this node has a property with the
094: * specified name.
095: */
096: public boolean hasProperty(String name) {
097: if (null == properties) {
098: return false;
099: } else {
100: return properties.containsKey(name);
101: }
102: }
103:
104: /**
105: * Get a property value.
106: *
107: * @param name The property name.
108: * @return The property's value or <code>null</code> if the
109: * property doesn't have a value.
110: */
111: public Object getProperty(String name) {
112: if (null == properties) {
113: return null;
114: } else {
115: return properties.get(name);
116: }
117: }
118:
119: /**
120: * Remove a property.
121: *
122: * @param name The property name.
123: * @return The property's old value or <code>null</code> if the
124: * property didn't have a value.
125: */
126: public Object removeProperty(String name) {
127: if (null == properties) {
128: return null;
129: } else {
130: return properties.remove(name);
131: }
132: }
133:
134: /**
135: * Get an iterator over this node's property names.
136: *
137: * @return An iterator over this node's property names.
138: */
139: public Iterator properties() {
140: if (null == properties) {
141: return new Iterator() {
142: public boolean hasNext() {
143: return false;
144: }
145:
146: public Object next() {
147: throw new NoSuchElementException();
148: }
149:
150: public void remove() {
151: throw new IllegalStateException();
152: }
153: };
154: } else {
155: return properties.keySet().iterator();
156: }
157: }
158:
159: /**
160: * Set the location of this node to the specified values,
161: * <code>iff</code> the location has not been set before.
162: *
163: * @param file The file.
164: * @param line The line number.
165: * @param column The column number.
166: */
167: public void setLocation(String file, int line, int column) {
168: if (null == location) {
169: location = new Location(file, line, column);
170: }
171: }
172:
173: }
|