001 // This file is part of the Attempto Java Packages.
002 // Copyright 2008, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch).
003 //
004 // The Attempto Java Packages is free software: you can redistribute it and/or modify it under the
005 // terms of the GNU Lesser General Public License as published by the Free Software Foundation,
006 // either version 3 of the License, or (at your option) any later version.
007 //
008 // The Attempto Java Packages is distributed in the hope that it will be useful, but WITHOUT ANY
009 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
010 // PURPOSE. See the GNU Lesser General Public License for more details.
011 //
012 // You should have received a copy of the GNU Lesser General Public License along with the Attempto
013 // Java Packages. If not, see http://www.gnu.org/licenses/.
014
015 package ch.uzh.ifi.attempto.chartparser;
016
017 import java.util.HashMap;
018 import java.util.List;
019
020 /**
021 * This class represents a grammar rule. A rule consists of a nonterminal category as its head,
022 * a sequence of categories as its body, and a boolean value that describes whether it is accessible
023 * or not. If a rule is not accessible then this means that no category of the body and no subcategory
024 * of those categories is accessible by any category outside of the body. This can be used to define
025 * which parts of the sentence are accessible for anaphoric references from a given position.
026 *
027 * @author Tobias Kuhn
028 */
029 public class Rule {
030
031 private final Nonterminal head;
032 private final Category[] body;
033 private final boolean accessible;
034
035 /**
036 * Creates a new rule.
037 *
038 * @param head The head category.
039 * @param accessible Defines whether the rule is accessible or not.
040 * @param body The body category sequence.
041 */
042 public Rule(Nonterminal head, boolean accessible, Category... body) {
043 this.head = head;
044 this.body = body;
045 this.accessible = accessible;
046 }
047
048 /**
049 * Creates a new rule that is accessible.
050 *
051 * @param head The head category.
052 * @param body The body category sequence.
053 */
054 public Rule(Nonterminal head, Category... body) {
055 this(head, true, body);
056 }
057
058 /**
059 * Creates a new rule.
060 *
061 * @param categories The first category of this list stands for the head category (it has to be
062 * a Nonterminal object). The rest stands for the body categories.
063 * @param accessible Defines whether the rule is accessible or not.
064 */
065 public Rule(List<Category> categories, boolean accessible) {
066 this.accessible = accessible;
067 this.head = (Nonterminal) categories.get(0);
068 categories.remove(0);
069 this.body = categories.toArray(new Category[0]);
070 }
071
072 /**
073 * Creates a new rule that is accessible.
074 *
075 * @param categories The first category of this list stands for the head category (it has to be
076 * a Nonterminal object). The rest stands for the body categories.
077 */
078 public Rule(List<Category> categories) {
079 this(categories, true);
080 }
081
082 /**
083 * Returns the head category of this rule.
084 *
085 * @return The head category.
086 */
087 public Nonterminal getHead() {
088 return head;
089 }
090
091 /**
092 * Returns the body category sequence of this rule.
093 *
094 * @return The body category sequence.
095 */
096 public Category[] getBody() {
097 return body;
098 }
099
100 /**
101 * Returns true if the body is empty (i.e. it is an epsilon-rule).
102 *
103 * @return true if the body is empty.
104 */
105 public boolean hasEmptyBody() {
106 return body.length == 0;
107 }
108
109 /**
110 * Returns the first category of the body.
111 *
112 * @return The first category of the body.
113 */
114 public Category getFirst() {
115 return body[0];
116 }
117
118 /**
119 * Returns true if the rule is accessible.
120 *
121 * @return true if the rule is accessible.
122 */
123 public boolean isAccessible() {
124 return accessible;
125 }
126
127 /**
128 * Creates an edge on the basis of this rule. Such edges are used by the chart parser.
129 *
130 * @param pos The position of the edge to be created.
131 * @return The edge.
132 */
133 Edge createEdge(int pos) {
134 return new Edge(pos, pos, getHead(), getBody(), accessible);
135 }
136
137 /**
138 * Creates a deep copy of this rule.
139 *
140 * @return A deep copy.
141 */
142 public Rule deepCopy() {
143 return deepCopy(new HashMap<Integer, StringEntity>());
144 }
145
146 /**
147 * Creates a deep copy of this rule using the given string entities. This method is
148 * usually called form another deepCopy-method.
149 *
150 * @param entities The string entities to be used.
151 * @return A deep copy.
152 */
153 public Rule deepCopy(HashMap<Integer, StringEntity> entities) {
154 Nonterminal headC = (Nonterminal) head.deepCopy(entities);
155 Category[] bodyC = new Category[body.length];
156 for (int i=0; i < body.length ; i++) {
157 bodyC[i] = body[i].deepCopy(entities);
158 }
159 return new Rule(headC, accessible, bodyC);
160 }
161
162 public String toString() {
163 String s = head + " ";
164 if (accessible) {
165 s += "=>";
166 } else {
167 s += "~>";
168 }
169 for (Category c : body) {
170 s += " " + c;
171 }
172 return s;
173 }
174
175 }