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    }