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