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.acewiki.gf;
016    
017    import java.util.ArrayList;
018    import java.util.HashSet;
019    import java.util.List;
020    import java.util.Set;
021    
022    import org.grammaticalframework.parser.ParseState;
023    
024    import ch.uzh.ifi.attempto.base.ConcreteOption;
025    import ch.uzh.ifi.attempto.base.NextTokenOptions;
026    import ch.uzh.ifi.attempto.base.PredictiveParser;
027    import ch.uzh.ifi.attempto.base.SimpleConcreteOption;
028    import ch.uzh.ifi.attempto.base.SimpleNextTokenOptions;
029    
030    /**
031     * This is a predictive parser connecting to the JPGF implementation of GF.
032     * 
033     * @author Tobias Kuhn
034     */
035    public class GFPredictiveParser implements PredictiveParser {
036            
037            private List<String> tokens = new ArrayList<String>();
038            private ParseState parseState;
039            private NextTokenOptions nextTokenOptions;
040            private GFGrammar gfGrammar;
041            private String language;
042            
043            /**
044             * Creates a new parser object for the given language.
045             * 
046             * @param gfGrammar The grammar object.
047             * @param language The language.
048             */
049            public GFPredictiveParser(GFGrammar gfGrammar, String language) {
050                    this.gfGrammar = gfGrammar;
051                    this.language = language;
052                    update();
053            }
054            
055            private ParseState getParseState() {
056                    if (parseState == null) {
057                            parseState = gfGrammar.parse(getTokensArray(), language);
058                    }
059                    return parseState;
060            }
061            
062            private void update() {
063                    // lazy parsing
064                    parseState = null;
065                    nextTokenOptions = null;
066            }
067            
068            public void addToken(String token) {
069                    tokens.add(token);
070                    update();
071            }
072            
073            public void addTokens(List<String> tokens) {
074                    this.tokens.addAll(tokens);
075                    update();
076            }
077            
078            public void removeToken() {
079                    tokens.remove(tokens.size()-1);
080                    update();
081            }
082            
083            public void removeAllTokens() {
084                    tokens.clear();
085                    update();
086            }
087            
088            public void setTokens(List<String> tokens) {
089                    this.tokens.clear();
090                    this.tokens.addAll(tokens);
091                    update();
092            }
093            
094            public List<String> getTokens() {
095                    return tokens;
096            }
097            
098            private String[] getTokensArray() {
099                    return tokens.toArray(new String[] {});
100            }
101            
102            public int getTokenCount() {
103                    return tokens.size();
104            }
105            
106            public NextTokenOptions getNextTokenOptions() {
107                    if (nextTokenOptions == null) {
108                            Set<ConcreteOption> options = new HashSet<ConcreteOption>();
109                            for (String s : getParseState().predict()) {
110                                    options.add(new SimpleConcreteOption(s));
111                            }
112                            nextTokenOptions = new SimpleNextTokenOptions(options);
113                    }
114                    return nextTokenOptions;
115            }
116            
117            public boolean isPossibleNextToken(String token) {
118                    return getNextTokenOptions().containsToken(token);
119            }
120            
121            public boolean isComplete() {
122                    return getParseState().getTrees().length > 0;
123            }
124            
125            public int getReference() {
126                    return -1;
127            }
128    
129    }