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

org.modelcc.language.factory.MemberSpecificationFactory 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.factory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;

import org.modelcc.Position;
import org.modelcc.SeparatorPolicy;
import org.modelcc.language.metamodel.CompositeLanguageElement;
import org.modelcc.language.metamodel.LanguageMember;
import org.modelcc.language.metamodel.MemberPositionMetadata;

/**
 * Member specification factory
 * 
 * @author Luis Quesada ([email protected]), refactored by Fernando Berzal ([email protected]) 
 */
public class MemberSpecificationFactory 
{
	// Process composite element
	
	public List create (CompositeLanguageElement ce) 
	{
		List> nodes = new ArrayList>();
		
		nodes.add(new ArrayList());

		for (LanguageMember current: ce.getMembers())
			nodes = processMember(nodes, current);
            
		for (Entry currentPosition: ce.getPositions().entrySet())
			nodes = processPosition(nodes, currentPosition);

		if (ce.isFreeOrder())
			nodes = processFreeOrder(nodes);
		
		return processContent(nodes);
	}
	
	private List processContent (List> nodes) 
	{
		List result = new ArrayList();
		
		for (List current: nodes) {
			MemberSpecification mn = new MemberSpecification();
			for (MemberSpecification curMemberNode: current)
				mn.add(curMemberNode);
			result.add(mn);
		}
		
		return result;
	}

	private List> processPosition (
			List> nodes,
			Entry currentPosition ) 
	{
		MemberPositionMetadata posInfo = currentPosition.getValue();
		LanguageMember source = currentPosition.getKey();
		LanguageMember target = posInfo.getMember();
		List> newNodes = new ArrayList>();
		for (List curNodes: nodes) {
			if (posInfo.contains(Position.BEFORE)) {
				processBefore(newNodes,curNodes,source,target);
			}
			if (posInfo.contains(Position.AFTER)) {
				processAfter(newNodes,curNodes,source,target);
			}
			if (posInfo.contains(Position.WITHIN)) {
				processInside(newNodes,curNodes,source,target,Position.WITHIN,posInfo.getSeparatorPolicy());
			}
			else if (posInfo.contains(Position.BEFORELAST)) {
				processInside(newNodes,curNodes,source,target,Position.BEFORELAST,posInfo.getSeparatorPolicy());
			}
			processNoSource(newNodes,curNodes,source,target);
		}
		return newNodes;
	}

	private void processAfter (
			List> newNodes,
			List curNodes, 
			LanguageMember source,
			LanguageMember target ) 
	{
		int sourceIndex = searchFront(curNodes,source);
		int targetIndex = searchBack(curNodes,target);
		if (sourceIndex != -1 && targetIndex != -1) {
        	MemberSpecification mn = new MemberSpecification(curNodes.get(targetIndex));
        	mn.clear();
    		mn.addAll(curNodes.get(targetIndex).getMembers());
    		mn.addAll(curNodes.get(sourceIndex).getMembers());
        	List curNodesCopy = new ArrayList();
        	curNodesCopy.addAll(curNodes);
    		curNodesCopy.set(targetIndex,mn);
    		curNodesCopy.remove(sourceIndex);
    		newNodes.add(curNodesCopy);
		}
	}

	private void processBefore (
			List> newNodes,
			List curNodes, 
			LanguageMember source,
			LanguageMember target ) 
	{
		int sourceIndex = searchBack(curNodes,source);
		int targetIndex = searchFront(curNodes,target);
		if (sourceIndex != -1 && targetIndex != -1) {
        	MemberSpecification mn = new MemberSpecification(curNodes.get(targetIndex));
        	mn.clear();
    		mn.addAll(curNodes.get(sourceIndex).getMembers());
    		mn.addAll(curNodes.get(targetIndex).getMembers());
        	List curNodesCopy = new ArrayList();
        	curNodesCopy.addAll(curNodes);
    		curNodesCopy.set(targetIndex,mn);
    		curNodesCopy.remove(sourceIndex);
    		newNodes.add(curNodesCopy);
		}
	}

	private void processInside ( 
			List> newNodes,
			List curNodes, 
			LanguageMember source, 
			LanguageMember target,
			int position, 
			SeparatorPolicy separatorPolicy ) 
	{
		int sourceIndex = searchBack(curNodes,source);
		int targetIndex = searchFront(curNodes,target);
		if (sourceIndex != -1 && targetIndex != -1) {
        	MemberSpecification mn = new MemberSpecification(curNodes.get(targetIndex));
        	mn.setContent(target,new MemberContent(position,separatorPolicy,source));
        	List curNodesCopy = new ArrayList();
        	curNodesCopy.addAll(curNodes);
    		curNodesCopy.set(targetIndex,mn);
    		curNodesCopy.remove(sourceIndex);
    		newNodes.add(curNodesCopy);
		}		
	}

	private void processNoSource (
			List> newNodes,
            List curNodes,
            LanguageMember source,
            LanguageMember target ) 
    {
	    int sourceIndex = searchBack(curNodes,source);
	    if (sourceIndex == -1) {
		    List curNodesCopy = new ArrayList();
		    curNodesCopy.addAll(curNodes);
		    newNodes.add(curNodesCopy);
	    }
	}
	
	private List> processMember (
			List> nodes, LanguageMember current ) 
	{
		List> newNodes = new ArrayList>();
		for (List curNodes: nodes) {
			List noOpt = new ArrayList();
			for (int i = 0;i < curNodes.size();i++)
				noOpt.add(new MemberSpecification(curNodes.get(i)));
			noOpt.add(new MemberSpecification(current));
			newNodes.add(noOpt);
			if (current.isOptional())
				newNodes.add(curNodes);
		}
		return newNodes;
	}

	private List> processFreeOrder (List> nodes) 
	{
		List> newNodes = new ArrayList>();
		
		for (List current: nodes) {
			// Current production
			List> combinations = new ArrayList>(); 

			// Empty production
			if (current.isEmpty())
				combinations.add(new ArrayList());

			for (MemberSpecification mn: current) {
				if (combinations.isEmpty()) { // If first element, add it
		    		List currentCombination = new ArrayList();
		    		currentCombination.add(mn);
					combinations.add(currentCombination);
				} else { // If other element, add it to every position
		        	List> newCombinations = new ArrayList>(); 
					for (List currentCombination: combinations) {
						for (int i = 0;i <= currentCombination.size();i++) {
		            		List newCombination = new ArrayList();
		            		newCombination.addAll(currentCombination);
		            		newCombination.add(i,mn);
		            		newCombinations.add(newCombination);
						}
					}
					combinations = newCombinations;
				}
			}
			newNodes.addAll(combinations);
		}
		return newNodes;
	}

	// Search
	
	private int searchBack (List curNodes, LanguageMember source) 
	{
    	int found = -1;
		for (int i = 0;i < curNodes.size();i++) {
			if (curNodes.get(i).getBack() == source) {
				if (found == -1) {
					found = i;
				} else {
					return -1;
				}
			}
		}
		return found;		
	}

    private int searchFront (List curNodes, LanguageMember source) 
    {
    	int found = -1;
		for (int i = 0;i < curNodes.size();i++) {
			if (curNodes.get(i).getFront() == source) {
				if (found == -1) {
					found = i;
				} else {
					return -1;
				}
			}
		}
		return found;		
	}    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy