001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2004-2007 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: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.parser;
020:
021: import java.io.IOException;
022:
023: import xtc.Constants;
024:
025: import xtc.util.Utilities;
026:
027: /**
028: * A nonterminal.
029: *
030: * @author Robert Grimm
031: * @version $Revision: 1.22 $
032: */
033: public class NonTerminal extends Element {
034:
035: /** The name. */
036: public final String name;
037:
038: /**
039: * Create a new nonterminal with the specified name.
040: *
041: * @param name The name.
042: */
043: public NonTerminal(String name) {
044: this .name = name;
045: }
046:
047: /**
048: * Create a new nonterminal that is a copy of the specified
049: * nonterminal.
050: *
051: * @param nt The nonterminal.
052: */
053: public NonTerminal(NonTerminal nt) {
054: this .name = nt.name;
055: }
056:
057: public Tag tag() {
058: return Tag.NONTERMINAL;
059: }
060:
061: public int hashCode() {
062: return name.hashCode();
063: }
064:
065: public boolean equals(Object o) {
066: if (this == o)
067: return true;
068: if (!(o instanceof NonTerminal))
069: return false;
070: return name.equals(((NonTerminal) o).name);
071: }
072:
073: /**
074: * Determine whether this nonterminal is qualified.
075: *
076: * @return <code>true</code> if this nonterminal is qualified.
077: */
078: public boolean isQualified() {
079: return Utilities.isQualified(name);
080: }
081:
082: /**
083: * Get this nonterminal's qualifier. If this nonterminal is
084: * qualified, this method returns the qualifier. Otherwise, it
085: * returns <code>null</code>.
086: *
087: * @return The qualifier.
088: */
089: public String getQualifier() {
090: return Utilities.getQualifier(name);
091: }
092:
093: /**
094: * Qualify this nonterminal. If this nonterminal is not qualified,
095: * this method returns a new nonterminal representing a fully
096: * qualified name. Otherwise, it returns this nonterminal.
097: *
098: * @param module The module name.
099: * @return The corresponding, qualified nonterminal.
100: */
101: public NonTerminal qualify(String module) {
102: if (Utilities.isQualified(name)) {
103: return this ;
104: } else {
105: return new NonTerminal(Utilities.qualify(module, name));
106: }
107: }
108:
109: /**
110: * Unqualify this nonterminal. If this nonterminal is qualified,
111: * this method returns a new nonterminal representing the
112: * unqualified name. Otherwise, it returns this nonterminal.
113: *
114: * @return The corresponding, unqualified nonterminal.
115: */
116: public NonTerminal unqualify() {
117: if (Utilities.isQualified(name)) {
118: return new NonTerminal(Utilities.getName(name));
119: } else {
120: return this ;
121: }
122: }
123:
124: /**
125: * Rename this nonterminal. If this nonterminal is qualified and
126: * the qualifier is a key in the specified module map, this method
127: * returns a new nonterminal with the mapping's value as the new
128: * qualifier. The new nonterminal's {@link Constants#ORIGINAL
129: * original} property is set to be this nonterminal's original name
130: * (i.e., this nonterminal's original property if it has that
131: * property or this nonterminal if it does not). Otherwise, this
132: * method returns this nonterminal.
133: *
134: * @param renaming The module map.
135: * @return The renamed nonterminal.
136: */
137: public NonTerminal rename(ModuleMap renaming) {
138: if (Utilities.isQualified(name)) {
139: String qualifier = Utilities.getQualifier(name);
140:
141: if (renaming.containsKey(qualifier)) {
142: NonTerminal original = this
143: .hasProperty(Constants.ORIGINAL) ? (NonTerminal) this
144: .getProperty(Constants.ORIGINAL)
145: : this ;
146: NonTerminal replacement = new NonTerminal(Utilities
147: .qualify(renaming.get(qualifier), Utilities
148: .getName(name)));
149: replacement.setProperty(Constants.ORIGINAL, original);
150: replacement.setLocation(this ); // Preserve for debugging.
151: return replacement;
152: }
153: }
154:
155: // Nothing changed. Move on.
156: return this ;
157: }
158:
159: /**
160: * Convert this nonterminal to the corresponding Java identifier.
161: *
162: * @return The corresponding Java identifier.
163: */
164: public String toIdentifier() {
165: return Utilities.toIdentifier(name);
166: }
167:
168: public void write(Appendable out) throws IOException {
169: out.append(name);
170: }
171:
172: public String toString() {
173: return name;
174: }
175:
176: }
|