org.modelcc.language.syntax.SyntaxConstraintsFactory 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.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.modelcc.AssociativityType;
import org.modelcc.language.CyclicPrecedenceException;
import org.modelcc.language.metamodel.LanguageModel;
/**
* Constraint factory.
*
* @author Luis Quesada ([email protected]), refactored by Fernando Berzal ([email protected])
*/
public final class SyntaxConstraintsFactory implements Serializable
{
private SyntaxConstraints constraints;
/**
* Default constructor.
*/
public SyntaxConstraintsFactory()
{
constraints = new SyntaxConstraints();
}
/**
* Set an associativity constraint for an object type.
* @param type the object type.
* @param as the associativity constraint.
*/
public void setAssociativity(Object type, AssociativityType as)
{
constraints.setAssociativity(type, as);
}
/**
* Adds a composition precedence between rules.
* @param ts1 the rule that precedes.
* @param ts2 the rule that is preceded.
*/
public void addCompositionPrecedences(Rule ts1,Rule ts2)
{
constraints.addCompositionPrecedences(ts1, ts2);
}
/**
* Adds a start precedence between rules.
* @param ts1 the rule that precedes.
* @param ts2 the rule that is preceded.
*/
public void addStartPrecedences(Rule ts1,Rule ts2)
{
constraints.addStartPrecedences(ts1, ts2);
}
/**
* Removes a composition precedence between rules.
* @param ts1 the rule that precedes.
* @param ts2 the rule that is preceded.
*/
public void removeCompositionPrecedences(Rule ts1,Rule ts2)
{
constraints.removeCompositionPrecedences(ts1, ts2);
}
/**
* Adds an selection precedence between rules.
* @param ts1 the rule that precedes.
* @param ts2 the rule that is preceded.
*/
public void addSelectionPrecedences(Rule ts1,Rule ts2)
{
constraints.addSelectionPrecedences(ts1, ts2);
}
/**
* Removes an selection precedence between rules.
* @param ts1 the rule that precedes.
* @param ts2 the rule that is preceded.
*/
public void removeSelectionPrecedences(Rule ts1,Rule ts2)
{
constraints.removeSelectionPrecedences(ts1, ts2);
}
/**
* Generates a syntactic specification.
* @throws CyclicCompositionPrecedenceException whenever several rules mutually precede with a composition precedence.
* @throws CyclicSelectionPrecedenceException whenever several rules mutually precede with an selection precedence.
* @return the syntactic specification.
*/
public SyntaxConstraints create()
throws CyclicPrecedenceException
{
return create(null);
}
public SyntaxConstraints create(LanguageModel model)
throws CyclicPrecedenceException
{
checkCompositionPrecedences();
checkSelectionPrecedences();
constraints.setModel(model);
return constraints;
}
// Checkers
public void checkSelectionPrecedences ()
throws CyclicPrecedenceException
{
Set rules = cycle(constraints.getSelectionPrecedences());
if (!rules.isEmpty())
throw new CyclicPrecedenceException("Cyclic selection precedence exception: "+cycleMessage(rules));
}
public void checkCompositionPrecedences()
throws CyclicPrecedenceException
{
Set rules = cycle(constraints.getCompositionPrecedences());
if (!rules.isEmpty())
throw new CyclicPrecedenceException("Cyclic composition precedence exception: "+cycleMessage(rules));
}
public String cycleMessage (Set rules)
{
String list = "";
for (Rule r: rules)
list += " "+r.getLeft().getType();
return list;
}
// Check cyclic precedences
public Set cycle (Map> precedences)
{
Set pool = new HashSet();
Set preceded; // Rules preceded by any rule in the pool.
boolean found;
for (Entry> e: precedences.entrySet()) {
pool.add(e.getKey());
for (Rule r: e.getValue()) {
pool.add(r);
}
}
while (!pool.isEmpty()) {
found = false;
preceded = new HashSet();
for (Rule r: pool) {
if (precedences.get(r) != null)
preceded.addAll(precedences.get(r));
}
Iterator ite = pool.iterator();
while (ite.hasNext()) {
Rule r = ite.next();
if (!preceded.contains(r)) {
ite.remove();
found = true;
}
}
if (!found)
return pool;
}
return pool;
}
}