/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.grammars.parsers;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.whole.lang.grammars.codebase.GrammarsRegistry;
import org.whole.lang.grammars.model.As;
import org.whole.lang.grammars.model.DataTerminal;
import org.whole.lang.grammars.model.Grammar;
import org.whole.lang.grammars.model.LiteralTerminal;
import org.whole.lang.grammars.model.NonTerminal;
import org.whole.lang.grammars.model.Production;
import org.whole.lang.grammars.model.Rule;
import org.whole.lang.grammars.reflect.GrammarsEntityDescriptorEnum;
import org.whole.lang.grammars.util.GrammarsUtils;
import org.whole.lang.iterators.IEntityIterator;
import org.whole.lang.iterators.IteratorFactory;
import org.whole.lang.matchers.Matcher;
import org.whole.lang.model.EnumValue;
import org.whole.lang.parsers.ForwardStrategyDataTypeParser;
import org.whole.lang.reflect.EntityDescriptor;
import org.whole.lang.reflect.EntityDescriptorEnum;
import org.whole.lang.reflect.ILanguageKit;
import org.whole.lang.reflect.ReflectionFactory;
import org.whole.lang.util.EntityUtils;
/**
* @author Enrico Persiani
*/
public class GrammarBasedDataTypeParser extends ForwardStrategyDataTypeParser {
private String grammarURI;
private String delimiter = "";
private String space = " ";
private String newLine = "\n";
private String indent = " ";
private Locale locale;
private Map<EntityDescriptor<?>, DataTerminal> dataTerminals;
private Map<EnumValue, Rule> enumRules;
public GrammarBasedDataTypeParser(String grammarUri) {
this(grammarUri, Locale.getDefault());
}
public GrammarBasedDataTypeParser(String grammarUri, Locale locale) {
this.grammarURI = grammarUri;
Grammar grammar = GrammarsRegistry.instance().getGrammar(grammarUri);
LiteralTerminal lt = grammar.getDelimiter();
if (EntityUtils.isNotResolver(lt))
delimiter = lt.getLiteral().getValue();
space = EntityUtils.safeStringValue(grammar.getSpaceLiteral(), space);
indent = EntityUtils.safeStringValue(grammar.getIndentLiteral(), indent);
newLine = EntityUtils.safeStringValue(grammar.getNewLineLiteral(), newLine);
this.locale = locale;
this.dataTerminals = new HashMap<EntityDescriptor<?>, DataTerminal>();
this.enumRules = new HashMap<EnumValue, Rule>();
Map<String, Rule> productions = new HashMap<String, Rule>();
IEntityIterator<Production> pi = IteratorFactory.<Production>childIterator();
pi.reset(grammar.getPhraseStructure());
for (Production p : pi)
productions.put(p.getName().getValue(), p.getRule());
Map<String, Rule> lexicon = new HashMap<String, Rule>();
IEntityIterator<Production> li = IteratorFactory.<Production>childIterator();
li.reset(grammar.getLexicalStructure());
for (Production p : li)
lexicon.put(p.getName().getValue(), p.getRule());
ILanguageKit languageKit = ReflectionFactory.getLanguageKit(GrammarsUtils.getLanguageURI(grammar), false, null);
EntityDescriptorEnum edEnum = languageKit.getEntityDescriptorEnum();
for (EntityDescriptor<?> ed : edEnum)
if (EntityUtils.isData(ed)) {
Rule production = productions.get(ed.getName());
if(ed.getDataKind().isEnumValue()) {
for (int i=0, size=production.wSize(); i<size; i++) {
As as = EntityUtils.clone((As) production.wGet(i));
IEntityIterator<Rule> iterator = IteratorFactory.<Rule>descendantOrSelfMatcherIterator().withPattern(GrammarsEntityDescriptorEnum.NonTerminal);
iterator.reset(as);
while (iterator.hasNext()) {
NonTerminal nt = (NonTerminal) iterator.next();
iterator.set(EntityUtils.clone(lexicon.get(nt.getValue())));
}
enumRules.put(ed.getDataEnumType().valueOf(as.getName().getValue()), as.getRule());
}
} else {
DataTerminal dataTerminal = Matcher.find(GrammarsEntityDescriptorEnum.DataTerminal, production, false);
if (dataTerminal == null) {
NonTerminal nonTerminal = Matcher.find(GrammarsEntityDescriptorEnum.NonTerminal, production, false);
dataTerminal = Matcher.find(GrammarsEntityDescriptorEnum.DataTerminal, lexicon.get(nonTerminal.getValue()), false);
}
dataTerminals.put(ed, EntityUtils.clone(dataTerminal));
}
}
setStrategy(new GrammarsDefaultDataTypeParser(this));
}
public String getGrammarURI() {
return grammarURI;
}
public String getDelimiter() {
return delimiter;
}
public String getSpace() {
return space;
}
public String getIndent() {
return indent;
}
public String getNewLine() {
return newLine;
}
public DataTerminal getDataTerminal(EntityDescriptor<?> ed) {
return dataTerminals.get(ed);
}
public Rule getEnumRule(EnumValue value) {
return enumRules.get(value);
}
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
}