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 and 022 * a sequence of categories as its body. Furthermore, a rule can be accessible for anaphoric references 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 for references by any category outside of the body. 025 * 026 * @author Tobias Kuhn 027 */ 028 public class Rule { 029 030 private final Nonterminal head; 031 private final boolean accessible; 032 private final Category[] body; 033 034 /** 035 * Creates a new rule. 036 * 037 * @param head The head category. 038 * @param accessible Defines whether the rule is accessible or not. 039 * @param body The body category sequence. 040 */ 041 public Rule(Nonterminal head, boolean accessible, Category... body) { 042 this.head = head; 043 this.body = body; 044 this.accessible = accessible; 045 } 046 047 /** 048 * Creates a new rule that is accessible. 049 * 050 * @param head The head category. 051 * @param body The body category sequence. 052 */ 053 public Rule(Nonterminal head, Category... body) { 054 this(head, true, body); 055 } 056 057 /** 058 * Creates a new rule. 059 * 060 * @param categories The first category of this list stands for the head category (it has to be 061 * a Nonterminal object). The rest stands for the body categories. 062 * @param accessible Defines whether the rule is accessible or not. 063 */ 064 public Rule(List<Category> categories, boolean accessible) { 065 this.accessible = accessible; 066 this.head = (Nonterminal) categories.get(0); 067 categories.remove(0); 068 this.body = categories.toArray(new Category[0]); 069 } 070 071 /** 072 * Creates a new rule that is accessible. 073 * 074 * @param categories The first category of this list stands for the head category (it has to be 075 * a Nonterminal object). The rest stands for the body categories. 076 */ 077 public Rule(List<Category> categories) { 078 this(categories, true); 079 } 080 081 /** 082 * Returns the head category of this rule. 083 * 084 * @return The head category. 085 */ 086 public Nonterminal getHead() { 087 return head; 088 } 089 090 /** 091 * Returns the body category sequence of this rule. 092 * 093 * @return The body category sequence. 094 */ 095 public Category[] getBody() { 096 return body; 097 } 098 099 /** 100 * Returns true if the body is empty (i.e. it is an epsilon-rule). 101 * 102 * @return true if the body is empty. 103 */ 104 public boolean hasEmptyBody() { 105 return body.length == 0; 106 } 107 108 /** 109 * Returns the first category of the body. 110 * 111 * @return The first category of the body. 112 */ 113 public Category getFirst() { 114 return body[0]; 115 } 116 117 /** 118 * Returns true if the rule is accessible. 119 * 120 * @return true if the rule is accessible. 121 */ 122 public boolean isAccessible() { 123 return accessible; 124 } 125 126 /** 127 * Creates an edge on the basis of this rule. Such edges are used by the chart parser. 128 * 129 * @param pos The position of the edge to be created. 130 * @return The edge. 131 */ 132 Edge createEdge(int pos) { 133 return new Edge(pos, pos, getHead(), getBody(), accessible); 134 } 135 136 /** 137 * Creates a deep copy of this rule. 138 * 139 * @return A deep copy. 140 */ 141 public Rule deepCopy() { 142 return deepCopy(new HashMap<Integer, StringEntity>()); 143 } 144 145 /** 146 * Creates a deep copy of this rule using the given string entities. This method is 147 * usually called form another deepCopy-method. 148 * 149 * @param entities The string entities to be used. 150 * @return A deep copy. 151 */ 152 Rule deepCopy(HashMap<Integer, StringEntity> entities) { 153 Nonterminal headC = (Nonterminal) head.deepCopy(entities); 154 Category[] bodyC = new Category[body.length]; 155 for (int i=0; i < body.length ; i++) { 156 bodyC[i] = body[i].deepCopy(entities); 157 } 158 return new Rule(headC, accessible, bodyC); 159 } 160 161 public String toString() { 162 String s = head + " "; 163 if (accessible) { 164 s += "=>"; 165 } else { 166 s += "~>"; 167 } 168 for (Category c : body) { 169 s += " " + c; 170 } 171 return s; 172 } 173 174 }