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    }