org.snapscript.compile.assemble.OperationTraverser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snap Show documentation
Show all versions of snap Show documentation
Dynamic scripting for the JVM
package org.snapscript.compile.assemble;
import java.util.List;
import org.snapscript.core.error.InternalStateException;
import org.snapscript.core.module.Path;
import org.snapscript.core.type.Type;
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 OperationTraverser {
private final OperationResolver resolver;
private final OperationBuilder builder;
private final Object[] empty;
public OperationTraverser(OperationBuilder builder, OperationResolver resolver) {
this.empty = new Object[]{};
this.resolver = resolver;
this.builder = builder;
}
public Object create(SyntaxNode node, Path path) throws Exception {
return create(node, path, 0);
}
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;
}
}