    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    }