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.HashMap;
018 import java.util.HashSet;
019 import java.util.Map;
020 import java.util.Set;
021
022 import ch.uzh.ifi.attempto.base.NextTokenOptions;
023
024 /**
025 * This class represents a set of options that describe how a partial text can be continued
026 * according to a given grammar, and contains specific code for its use in the chart parser.
027 *
028 * @author Tobias Kuhn
029 */
030 public class CPNextTokenOptions implements NextTokenOptions {
031
032 private Set<CPAbstractOption> aOptions;
033 private Set<CPConcreteOption> cOptions;
034 private Map<String,Set<CPAbstractOption>> categoryMap;
035 private Set<String> tokens;
036
037 /**
038 * Generates a new object with the given abstract and concrete options.
039 *
040 * @param aOptions The set of abstract options.
041 * @param cOptions The set of concrete options.
042 */
043 CPNextTokenOptions(Set<CPAbstractOption> aOptions, Set<CPConcreteOption> cOptions) {
044 this.aOptions = aOptions;
045 this.cOptions = cOptions;
046 }
047
048 public Set<CPAbstractOption> getAbstractOptions() {
049 return aOptions;
050 }
051
052 /**
053 * Returns the abstract options that have a pre-terminal category with the specified name.
054 *
055 * @param categoryName The name of the category.
056 * @return The set of abstract options with the respective category name.
057 */
058 public Set<CPAbstractOption> getAbstractOptions(String categoryName) {
059 createCategoryCache();
060 Set<CPAbstractOption> s = categoryMap.get(categoryName);
061 if (s == null) {
062 s = new HashSet<CPAbstractOption>();
063 categoryMap.put(categoryName, s);
064 }
065 return s;
066 }
067
068 public Set<CPConcreteOption> getConcreteOptions() {
069 return cOptions;
070 }
071
072 public boolean containsToken(String token) {
073 createTokenCache();
074 return tokens.contains(token);
075 }
076
077 public boolean containsCategory(String categoryName) {
078 createCategoryCache();
079 return categoryMap.containsKey(categoryName);
080 }
081
082 /**
083 * Returns true if the given pre-terminal category represents a possible next token.
084 *
085 * @param c The pre-terminal category.
086 * @return true if it represents a possible next token.
087 */
088 public boolean containsCategory(Preterminal c) {
089 createCategoryCache();
090 if (!categoryMap.containsKey(c.getName())) return false;
091 for (CPAbstractOption o : getAbstractOptions(c.getName())) {
092 if (o.isFulfilledBy(c)) {
093 return true;
094 }
095 }
096 return false;
097 }
098
099 private void createTokenCache() {
100 if (tokens != null) return;
101
102 tokens = new HashSet<String>();
103 for (CPConcreteOption o : cOptions) {
104 tokens.add(o.getWord());
105 }
106 }
107
108 private void createCategoryCache() {
109 if (categoryMap != null) return;
110
111 categoryMap = new HashMap<String, Set<CPAbstractOption>>();
112 for (CPAbstractOption o : aOptions) {
113 if (o.getCategory() instanceof Preterminal) {
114 String n = o.getCategory().getName();
115 Set<CPAbstractOption> s = categoryMap.get(n);
116 if (s == null) {
117 s = new HashSet<CPAbstractOption>();
118 categoryMap.put(n, s);
119 }
120 s.add(o);
121 }
122 }
123 }
124
125 }