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

org.modelcc.parser.fence.FenceAssociativityConstraints 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!
package org.modelcc.parser.fence;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.modelcc.AssociativityType;
import org.modelcc.language.syntax.Grammar;
import org.modelcc.language.syntax.Rule;
import org.modelcc.language.syntax.Symbol;
import org.modelcc.language.syntax.InputSymbol;
import org.modelcc.language.syntax.SyntaxConstraints;

/**
 * Fence associativity constraints
 * 
 * @author Luis Quesada ([email protected]), refactored by Fernando Berzal ([email protected])
 */

public class FenceAssociativityConstraints 
{
	private SyntaxConstraints constraints;
	
    private Map indirectAssociativities;

    private Set isIndirectAssociative;

    private Set hasAnyAssociativity;

    private Set hasAnyAssociativityRule;
	
    private Set associateds;
	
    
	public FenceAssociativityConstraints (Grammar g, SyntaxConstraints constraints)
	{
		this.constraints = constraints;
		
		indirectAssociativities = new HashMap();
		isIndirectAssociative = new HashSet();
		hasAnyAssociativity = new HashSet();
		hasAnyAssociativityRule = new HashSet();                 
		associateds = new HashSet();		

        // indirectAssociativities
		
		Map associativities = constraints.getAssociativities();

		indirectAssociativities.putAll(associativities);

        for (Object pe: associativities.keySet()) {
    		if (indirectAssociativities.get(pe)!=null) {
    			if (indirectAssociativities.get(pe)!=AssociativityType.UNDEFINED) {
    				isIndirectAssociative.add(pe);
    				indirectAssociativities.put(pe, indirectAssociativities.get(pe));
    			}
    		}
        }
        
        // hasAnyAssociativity
        
        for (Rule r: g.getRules()) {
            int assocs = 0;
            for (int i = 0;i < r.getRight().size();i++) {
            	if (isIndirectAssociative.contains(r.getRight().get(i).getType()))
            		assocs++;
            }            
            if (assocs>=1) {
            	hasAnyAssociativity.add(r.getLeft().getType());
            	hasAnyAssociativityRule.add(r);
            }
        }

	}

	
	// Accessors
	
	
	private boolean hasAssociativity (Object type)
	{
		return hasAnyAssociativity.contains(type);
	}
	
	private boolean hasAssociativity (Rule rule)
	{
		return hasAnyAssociativityRule.contains(rule);
	}
	
	private boolean isAssociative (Object type)
	{
		return isIndirectAssociative.contains(type);
	}
	
    private AssociativityType associativity (InputSymbol ps) 
    {
    	return indirectAssociativities.get(ps.getType());
    }	
    

    
	// "Associated" symbols
	
	public boolean isAssociate(Symbol s1) 
	{
		boolean associate = false;
	
		for (int i=0; i 0) {
		            if (s1.getRule().equals(s1.getContent(i-1).getRelevantRule()))
		                recLeft = true;
		            if (associateds.contains(s1.getContent(i-1))) {
		                aux = recLeft;
		                recLeft = true;
		                Set compc = constraints.getCompositionPrecedences(s1.getContent(i-1).getRelevantRule());
		                if (compc != null) {
		                    if (compc.contains(r)) {
		                        recLeft = aux;
		                    }
		                }
		            }
		        }
		        if (i < s1.size()-1) {
		            if (s1.getRule().equals(s1.getContent(i+1).getRelevantRule()))
		                recRight = true;
		            if (associateds.contains(s1.getContent(i+1))) {
		                aux = recRight;
		                recRight = true;
		                Set compc = constraints.getCompositionPrecedences(s1.getContent(i+1).getRelevantRule());
		                if (compc != null) {
		                    if (compc.contains(r)) {
		                        recRight = aux;
		                    }
		                }
		            }
		        }

		        switch (indirectAssociativities.get(s1.getContent(i).getType())) {
		            case LEFT_TO_RIGHT:
		                if (recRight)
		                    inhibited = true;
		                break;
		            case RIGHT_TO_LEFT:
		                if (recLeft)
		                    inhibited = true;
		                break;
		            case NON_ASSOCIATIVE:
		                if (recRight || recLeft)
		                    inhibited = true;
		                break;
		            case UNDEFINED:
		                break;
		        }
		    }
		}
		return inhibited;
	}
	
	
	// Tuples
	
	public void searchTuples(InputSymbol ps, Set ets) 
	{
		Set rules;
	
		if (hasAssociativity(ps.getType())) {
        	// Sacar de ets todas las tuplas que usan una regla con elemento asociativo.
        	Set etsas = new HashSet();
        	rules = new HashSet();
        	for (Iterator ite = ets.iterator();ite.hasNext();) {
        		Tuple et = ite.next();
        		if (hasAssociativity(et.getRule())) {
        			ite.remove();
        			etsas.add(et);
        			rules.add(et.getRule());
        		}
        	}
        	// Si todas están formadas usando la misma regla:
        	if (rules.size()==1) {
        		Rule rx = rules.iterator().next();
        		// Buscar el número de elemento que es asociativo.
        		int elm = -1;
        		for (int i = 0;i < rx.getRight().size();i++) {
        			if (isAssociative(rx.getRight().get(i).getType()))
                        elm = i;
                }
                if (elm != -1) {
                    int min = -1;
                    int max = -1;
                    AssociativityType ac = null;
                    boolean ok = true;
                    for (Tuple et: etsas) {
                        InputSymbol asoc = et.getSymbol(elm);
                        AssociativityType acn = associativity(asoc);
                        if (ac != null && acn != ac)
                            ok = false;
                        ac = acn;
                        if (asoc.getStartIndex()max)
                            max = asoc.getEndIndex();
                    }
                    
                    if (ac != null && ok && etsas.size()>1) {
                        // Localizar el elemento asociativo en todas, + localizar máximo (=end maximo) y mínimo (=start mínimo).
                        // Si la asociatividad del elemento asociativo es IGUAL en todas:

                        // Si NON_ASSOCIATIVE y hay más de una, borrar todas.
                        if (ac == AssociativityType.NON_ASSOCIATIVE) {
                            etsas.clear();
                        }

                        // Si LEFT_TO_RIGHT: Eliminar todas cuyo elemento con asociatividad.end != end maximo                       
                        if (ac == AssociativityType.LEFT_TO_RIGHT) {
                            for (Iterator ite = etsas.iterator();ite.hasNext();) {
                                Tuple et = ite.next();
                                if (et.getSymbol(elm).getEndIndex()!=max) {
                                    ite.remove();
                                }
                            }
                        }

                        // Si RIGHT_TO_LEFT: Eliminar todas cuyo elemento con asociatividad.start != start minimo
                        if (ac == AssociativityType.RIGHT_TO_LEFT) {
                            for (Iterator ite = etsas.iterator();ite.hasNext();) {
                                Tuple et = ite.next();
                                if (et.getSymbol(elm).getStartIndex()!=min) {
                                    ite.remove();
                                }
                            }
                        }

                    }
                }
                
            }
            // En cualquier caso: devolver a ets.
            ets.addAll(etsas);
        }
	}
	
}