org.modelcc.language.syntax.ReferencePostBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ModelCC Show documentation
Show all versions of ModelCC Show documentation
ModelCC is a model-based parser generator (a.k.a. compiler compiler) that decouples language specification from language processing, avoiding some of the problems caused by grammar-driven parser generators. ModelCC receives a conceptual model as input, along with constraints that annotate it. It is then able to create a parser for the desired textual language and the generated parser fully automates the instantiation of the language conceptual model. ModelCC also includes a built-in reference resolution mechanism that results in abstract syntax graphs, rather than mere abstract syntax trees.
The newest version!
/*
* ModelCC, distributed under ModelCC Shared Software License, www.modelcc.org
*/
package org.modelcc.language.syntax;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.modelcc.io.java.Reflection;
import org.modelcc.language.factory.SymbolIdentifier;
import org.modelcc.language.metamodel.LanguageElement;
import org.modelcc.language.metamodel.CompositeLanguageElement;
import org.modelcc.language.metamodel.LanguageModel;
import org.modelcc.language.metamodel.LanguageMember;
/**
* Reference symbol builder
*
* @author Luis Quesada ([email protected]) & Fernando Berzal ([email protected])
*/
public final class ReferencePostBuilder extends SymbolBuilder implements Serializable
{
/**
* Constructor
*/
public ReferencePostBuilder(LanguageModel model)
{
super(model);
}
/**
* Build a symbol
* @param t symbol to be built.
* @param data the parser metadata.
* @return true if the symbol is valid, false if not
*/
@Override
public boolean build (Symbol t, ParserMetadata data)
{
if (!data.getLazyReferences().contains(t))
return true;
SymbolIdentifier eid = (SymbolIdentifier)t.getType();
CompositeLanguageElement ce = (CompositeLanguageElement) eid.getElement();
Object o = null;
try {
if (!ce.getKeyMembers().isEmpty()) {
o = instantiateReference(ce, t);
if (o!=null) {
Class c = ce.getElementClass();
Map idmap = data.getKeys(c);
ObjectWrapper kw = ObjectWrapper.createKeyWrapper(o, getModel(), data.getMap());
if (idmap.containsKey(kw)) {
t.setUserData(idmap.get(kw));
if (data.getUsed().get(t) != null) {
for (Symbol sym: data.getUsed().get(t)) {
propagateChanges(sym,t,data.getUsed(),0);
}
}
} else {
o = null;
}
}
}
} catch (Exception ex) {
log(Level.SEVERE, "Reference resolution exception", ex);
o = null;
}
return (o!=null);
}
private void propagateChanges(Symbol t, Symbol updated, Map> usedIn, int array)
throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException
{
if (t.equals(updated))
return;
Object tData = getData(t);
Object uData = getData(updated);
if (((SymbolIdentifier)(t.getRule().getLeft().getType())).getElement().getClass().equals(LanguageElement.class)) {
t.setUserData(uData);
propagateChanges(t, usedIn, 0);
} else if (tData.getClass().isArray() && !uData.getClass().isArray()) {
Object[] atData = (Object[])tData;
if (!uData.equals(atData[0])) {
atData[0] = uData;
propagateChanges(t, usedIn, array+1);
}
} else if (tData.getClass().isArray() && uData.getClass().isArray()) {
Object[] atData = (Object[])tData;
Object[] auData = (Object[])uData;
if (atData.length>array) {
if (!auData[0].equals(atData[array])) {
atData[array] = auData[array-1];
propagateChanges(t, usedIn, array+1);
}
} else {
propagateChanges(t, usedIn, array);
}
} else if (!tData.getClass().isArray() && uData.getClass().isArray()) {
int index = t.getContents().indexOf(updated);
RuleSymbol re = t.getElement(index);
LanguageMember ct = re.getLanguageMember();
Field fld = Reflection.findField(tData.getClass(),ct.getID());
Object content = fld.get(tData);
Object[] auData = (Object[])uData;
Object[] aContent = (Object[])content;
if (!auData[array-1].equals(aContent[array-1])) {
aContent[array-1] = auData[array-1];
for (int i = 0;i < aContent.length;i++) {
propagateChanges(t, usedIn, 0);
}
}
} else { // tData is not array and uData is not array
int index = t.getContents().indexOf(updated);
RuleSymbol re = t.getElement(index);
LanguageMember ct = re.getLanguageMember();
Field fld = Reflection.findField(tData.getClass(),ct.getID());
fld.setAccessible(true);
Object content = fld.get(tData);
if (!uData.equals(content)) {
fld.set(tData,uData);
propagateChanges(t, usedIn, 0);
}
}
}
private void propagateChanges(Symbol t, Map> usedIn, int pos)
throws IllegalAccessException, NoSuchFieldException
{
if (usedIn.get(t) != null) {
for (Symbol s: usedIn.get(t)) {
propagateChanges(s,t,usedIn,pos);
}
}
}
private Object getData(Symbol t)
{
Object tData = t.getUserData();
if (tData.getClass().equals(ObjectCollection.class)) {
tData = ((ObjectCollection)tData).getContent();
}
return tData;
}
}