001 // This file is part of the Attempto Java Packages. 002 // Copyright 2008-2009, 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 }