001 // This file is part of AceWiki.
002 // Copyright 2008-2012, AceWiki developers.
003 //
004 // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
005 // Lesser General Public License as published by the Free Software Foundation, either version 3 of
006 // the License, or (at your option) any later version.
007 //
008 // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009 // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
010 // Lesser General Public License for more details.
011 //
012 // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
013 // not, see http://www.gnu.org/licenses/.
014
015 package ch.uzh.ifi.attempto.chartparser;
016
017 import java.util.ArrayList;
018 import java.util.List;
019
020 import ch.uzh.ifi.attempto.base.AbstractOption;
021
022 /**
023 * This class represents an abstract option for the chart parser. Such an abstract option consists
024 * of a category that represents possible next tokens and of a set of zero or more exceptions, also
025 * in the form of categories. The categories can be terminal or pre-terminal, but not non-terminal.
026 *
027 * @author Tobias Kuhn
028 */
029 public class CPAbstractOption implements AbstractOption {
030
031 private final Category category;
032 private final Category[] exceptions;
033 private final String identifier;
034
035 CPAbstractOption(Grammar grammar, Category category, Category[] exceptions) {
036 this.category = category;
037 if (exceptions != null) {
038 this.exceptions = exceptions;
039 } else {
040 this.exceptions = new Category[] {};
041 }
042 identifier = calculateIdentifier(grammar.getFeatureNamesArray());
043 }
044
045 CPAbstractOption(Grammar grammar, Category category, List<Category> exceptions) {
046 this(grammar, category, exceptions.toArray(new Category[] {}));
047 }
048
049 CPAbstractOption(Grammar grammar, Category category) {
050 this(grammar, category, (Category[]) null);
051 }
052
053 /**
054 * Returns the terminal or pre-terminal category that represents possible next tokens.
055 *
056 * @return The terminal or pre-terminal category.
057 */
058 public Category getCategory() {
059 return category;
060 }
061
062 public String getCategoryName() {
063 return category.getName();
064 }
065
066 /**
067 * This method returns the exceptions.
068 *
069 * @return The exceptions in the form of categories.
070 */
071 public Category[] getExceptions() {
072 return exceptions;
073 }
074
075 /**
076 * Returns true if the given category is fulfilled by this option.
077 *
078 * @param c The category.
079 * @return true if it is fulfilled by this option.
080 */
081 public boolean isFulfilledBy(Category c) {
082 if (!category.subsumes(c)) return false;
083 if (exceptions == null) return true;
084 for (Category x : exceptions) {
085 if (x.subsumes(c)) return false;
086 }
087 return true;
088 }
089
090 String calculateIdentifier(String[] usedFeatureNames) {
091 List<Integer> vars = new ArrayList<Integer>();
092 List<Integer> mvars = new ArrayList<Integer>();
093 String id = "";
094
095 vars.clear();
096 mvars.clear();
097 category.collectVars(vars, mvars);
098 id += category.getIdentifier(mvars, usedFeatureNames) + " / ";
099
100 if (exceptions != null) {
101 for (Category x : exceptions) {
102 vars.clear();
103 mvars.clear();
104 x.collectVars(vars, mvars);
105 id += x.getIdentifier(mvars, usedFeatureNames) + " ";
106 }
107 }
108 return id;
109 }
110
111 public boolean equals(Object obj) {
112 if (!(obj instanceof CPAbstractOption)) return false;
113 CPAbstractOption other = (CPAbstractOption) obj;
114 return this.identifier.equals(other.identifier);
115 }
116
117 public int hashCode() {
118 return identifier.hashCode();
119 }
120
121 public String toString() {
122 String s = "";
123 s += category + "";
124 if (exceptions.length > 0) {
125 s += " except";
126 for (Category x : exceptions) {
127 s += " " + x;
128 }
129 }
130 return s;
131 }
132
133 }