All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.modelcc.language.syntax.ReferencePostBuilder Maven / Gradle / Ivy

Go to download

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;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy