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

org.modelcc.language.syntax.Grammar 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.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.modelcc.language.metamodel.LanguageModel;

/**
 * Language grammar.
 * 
 * @author Luis Quesada ([email protected]) & Fernando Berzal ([email protected])
 */
public final class Grammar implements Serializable 
{
	/**
	 * Language model
	 */
	private LanguageModel model;

    /**
     * Set of rules.
     */
    private Set rules;

    /**
     * Start type.
     */
    private Object startType;

    /**
     * Start rules.
     */
    private Map> startRules;

    /**
     * Kleene's star
     */
    private Map> star;

    /**
     * Set of empty rules.
     */
    private Map> emptyRules;

    /**
     * Map of empty rules.
     */
    private Map emptyRuleMap;

    /**
     * Default constructor
     */
    public Grammar ()
    {
        this.rules = new HashSet();
        this.startType = null;
    }
    

    /**
     * Prepare grammar for use.
     */
    public void prepare ()
    {
    	computeStartRules();
    	computeStar();
    }

	private void computeStartRules() 
	{
		this.startRules = new HashMap>();

		for (Rule r: rules) {
		    int i = 0;
		    do {
		        Set se = startRules.get(r.getRight().get(i).getType());
		        if (se == null) {
		            se = new HashSet();
		            startRules.put(r.getRight().get(i).getType(),se);
		        }
		        se.add(r);
		        i++;
		    } while (emptyRules.containsKey(r.getRight().get(i-1).getType()) && i < r.getRight().size());
		}
	}

	private void computeStar() 
	{
		this.star = new HashMap>();

		Set objs = new HashSet();
		
		for (Rule r: rules) {
		    Set se = getStar(r.getLeft().getType());
		    se.add(r.getLeft().getType());
		    starFill(se,r,0,objs);
		    for (int i = 0;i < r.getRight().size();i++) {
		        se = getStar(r.getRight().get(i).getType());
		        se.add(r.getRight().get(i).getType());
		    }
		}

		boolean updated = true;

		while (updated) {
		    updated = false;
		    for (Object o: objs) {
		        for (Object o2: objs) {
		            if (star.get(o).contains(o2)) {
		            	for (Object o3: star.get(o2)) {
		            		if (!star.get(o).contains(o3)) {
		            			star.get(o).add(o3);
		            			updated = true;
		            		}
		            	}
		            }
		        }
		    }
		}
	}


    private void starFill(Set se, Rule r, int i, Set objs) 
    {
        se.add(r.getRight().get(i).getType());
        objs.add(r.getLeft().getType());
        objs.add(r.getRight().get(i).getType());
        if (emptyRules.containsKey(r.getRight().get(i).getType()) && r.getRight().size()>i+1) 
            starFill(se,r,i+1,objs);
    }

    
    // Getters & setters
    
    public LanguageModel getModel ()
    {
    	return model;
    }
    
    public void setModel (LanguageModel model)
    {
    	this.model = model;
    }

    public Set getRules() 
    {
        return rules;
    }

    public Object getStartType() 
    {
        return startType;
    }
    
    public void setStartType (Object startType)
    {
    	this.startType = startType;
    }
    
    public Set getEmptyRules (Object object)
    {
    	return emptyRules.get(object);
    }
    
    public boolean isNullable (Object object)
    {
    	return emptyRules.containsKey(object);
    }

    public Rule getEmptyRule(Object object) 
    {
        return emptyRuleMap.get(object);
    }

    public Set getStartRules(Object object) 
    {
        return startRules.get(object);
    }

    public Set getStar (Object object) 
    {
    	Set set = star.get(object);
    	
	    if (set == null) {
	        set = new HashSet();
	        star.put(object,set);
	    }
    	
        return set;
    }

    protected void setEmptyRules (Map> emptyRules, Map emptyRuleMap)
    {
    	this.emptyRules = emptyRules;
    	this.emptyRuleMap = emptyRuleMap;
    }
 
    // Grammar rules
    
    /**
     * Adds a rule.
     * @param r the rule to be added.
     */
    public void addRule(Rule r) 
    {
        if (r != null)
         rules.add(r);
    }
    
    /**
     * Removes a rule.
     * @param r the rule to be removed.
     */
    public void removeRule(Rule r) 
    {
        rules.remove(r);
    }
    
    // toString

    @Override
    public String toString() 
    {
        String ret = "";
        for (Rule r: rules)
            ret += r +"\n";
        ret += "\n";
        for (Object o: emptyRules.keySet())
            ret += "empty: "+o+"\n";
        return ret;    
    }

}