org.snapscript.compile.assemble.OperationAssembler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snap-all Show documentation
Show all versions of snap-all Show documentation
Dynamic scripting for the JVM
package org.snapscript.compile.assemble;
import java.util.List;
import org.snapscript.core.Context;
import org.snapscript.core.InternalStateException;
import org.snapscript.core.Path;
import org.snapscript.core.Type;
import org.snapscript.core.stack.ThreadStack;
import org.snapscript.parse.Line;
import org.snapscript.parse.SyntaxNode;
import org.snapscript.parse.Token;
import org.snapscript.tree.Operation;
import org.snapscript.tree.OperationResolver;
public class OperationAssembler implements Assembler {
private final OperationBuilder builder;
private final OperationResolver resolver;
private final Context context;
private final Object[] empty;
public OperationAssembler(Context context) {
this.builder = new OperationBuilder(context);
this.resolver = new OperationResolver(context);
this.empty = new Object[]{};
this.context = context;
}
@Override
public T assemble(SyntaxNode token, Path path) throws Exception {
ThreadStack stack = context.getStack();
Object value = create(token, path, 0);
stack.clear();
return (T)value;
}
private Object create(SyntaxNode node, Path path, int depth) throws Exception {
List children = node.getNodes();
String grammar = node.getGrammar();
Operation type = resolver.resolve(grammar);
int size = children.size();
if (type == null) {
return createChild(node, path, children, type,depth);
}
if (size > 0) {
return createBranch(node, path, children, type,depth);
}
return createLeaf(node, path, children, type,depth);
}
private Object createBranch(SyntaxNode node, Path path, List children, Operation operation, int depth) throws Exception {
Type type = operation.getType();
Line line = node.getLine();
int size = children.size();
if(size > 0) {
Object[] arguments = new Object[size];
for (int i = 0; i < size; i++) {
SyntaxNode child = children.get(i);
Object argument = create(child, path, depth+1);
arguments[i] = argument;
}
return builder.create(type, arguments, line);
}
return builder.create(type, empty, line);
}
private Object createChild(SyntaxNode node, Path path, List children, Operation operation, int depth) throws Exception {
String grammar = node.getGrammar();
int size = children.size();
if (size > 1) {
throw new InternalStateException("No type defined for '" + grammar + "'");
}
if (size > 0) {
SyntaxNode child = children.get(0);
if (child == null) {
throw new InternalStateException("No child for '" + grammar + "'");
}
return create(child, path, depth);
}
if (size > 0) {
return createBranch(node, path, children, operation, depth);
}
return createLeaf(node, path, children, operation, depth);
}
private Object createLeaf(SyntaxNode node, Path path, List children, Operation operation, int depth) throws Exception {
Token token = node.getToken();
Line line = node.getLine();
if (operation != null) {
Type type = operation.getType();
if (token == null) {
return builder.create(type, empty, line); // no line number????
}
return builder.create(type, new Object[]{token}, line);
}
return token;
}
}