package org.rascalmpl.parser.uptr;
import java.net.URI;
import org.rascalmpl.interpreter.asserts.Ambiguous;
import org.rascalmpl.parser.gtd.location.PositionStore;
import org.rascalmpl.parser.gtd.result.out.INodeConstructorFactory;
import org.rascalmpl.parser.gtd.util.ArrayList;
import org.rascalmpl.value.IConstructor;
import org.rascalmpl.value.IList;
import org.rascalmpl.value.IListWriter;
import org.rascalmpl.value.ISetWriter;
import org.rascalmpl.value.ISourceLocation;
import org.rascalmpl.values.ValueFactoryFactory;
import org.rascalmpl.values.uptr.ITree;
import org.rascalmpl.values.uptr.ProductionAdapter;
import org.rascalmpl.values.uptr.RascalValueFactory;
import org.rascalmpl.values.uptr.TreeAdapter;
public class UPTRNodeFactory implements INodeConstructorFactory<ITree, ISourceLocation>{
private final static RascalValueFactory VF = (RascalValueFactory) ValueFactoryFactory.getValueFactory();
private boolean allowAmb;
public UPTRNodeFactory(boolean allowAmbiguity){
super();
this.allowAmb = allowAmbiguity;
}
public ITree createCharNode(int charNumber){
return VF.character(charNumber);
}
public ITree createLiteralNode(int[] characters, Object production){
IListWriter listWriter = VF.listWriter();
for(int i = characters.length - 1; i >= 0; --i){
listWriter.insert(VF.character(characters[i]));
}
return VF.appl((IConstructor) production, listWriter.done());
}
private static ITree buildAppl(ArrayList<ITree> children, Object production){
return VF.appl((IConstructor) production, children);
}
public ITree createSortNode(ArrayList<ITree> children, Object production){
return buildAppl(children, production);
}
public ITree createSubListNode(ArrayList<ITree> children, Object production){
return buildAppl(children, production);
}
public ITree createListNode(ArrayList<ITree> children, Object production){
return buildAppl(children, production);
}
private static ITree buildAmbiguityNode(ArrayList<ITree> alternatives, boolean allowAmb){
ISetWriter ambSublist = VF.setWriter();
for(int i = alternatives.size() - 1; i >= 0; --i){
ambSublist.insert(alternatives.get(i));
}
if (allowAmb) {
return VF.amb(ambSublist.done());
}
else {
throw new Ambiguous(VF.amb(ambSublist.done()));
}
}
public ITree createAmbiguityNode(ArrayList<ITree> alternatives){
return buildAmbiguityNode(alternatives, allowAmb);
}
public ITree createSubListAmbiguityNode(ArrayList<ITree> alternatives){
return buildAmbiguityNode(alternatives, allowAmb);
}
public ITree createListAmbiguityNode(ArrayList<ITree> alternatives){
return buildAmbiguityNode(alternatives, allowAmb);
}
private static ITree buildCycle(int depth, Object production){
return VF.cycle(ProductionAdapter.getType((IConstructor) production), depth);
}
public ITree createCycleNode(int depth, Object production){
return buildCycle(depth, production);
}
public ITree createSubListCycleNode(Object production){
return buildCycle(1, production);
}
public ITree createRecoveryNode(int[] characters){
IListWriter listWriter = VF.listWriter();
for(int i = characters.length - 1; i >= 0; --i){
listWriter.insert(VF.character(characters[i]));
}
return VF.appl(VF.constructor(RascalValueFactory.Production_Skipped), listWriter.done());
}
public ISourceLocation createPositionInformation(URI input, int offset, int endOffset, PositionStore positionStore){
int beginLine = positionStore.findLine(offset);
int endLine = positionStore.findLine(endOffset);
return VF.sourceLocation(input, offset, endOffset - offset, beginLine + 1, endLine + 1, positionStore.getColumn(offset, beginLine), positionStore.getColumn(endOffset, endLine));
}
public ITree addPositionInformation(ITree node, ISourceLocation location){
return (ITree) node.asAnnotatable().setAnnotation(RascalValueFactory.Location, location);
}
public ArrayList<ITree> getChildren(ITree node){
IList args = TreeAdapter.getArgs(node);
ArrayList<ITree> children = new ArrayList<>(args.length());
for(int i = 0; i < args.length(); ++i){
children.add((ITree) args.get(i));
}
return children;
}
public Object getRhs(Object production){
return ProductionAdapter.getType((IConstructor) production);
}
public boolean isAmbiguityNode(ITree node){
return TreeAdapter.isAmb(node);
}
public Object getProductionFromNode(ITree node){
return TreeAdapter.getProduction(node);
}
}