if (cached != null) {
return cached;
}
if (layoutOfFather == null) {
throw new ImplementationError("layout is null");
}
if (TreeAdapter.isAppl(tree)) {
String cons = TreeAdapter.getConstructorName(tree);
if (cons != null && (cons.equals("hole"))) { // TODO: this is unsafe, what if somebody named their own production "hole"??
return liftHole(tree);
}
boolean lex = lexicalFather ? !TreeAdapter.isSort(tree) : TreeAdapter.isLexical(tree);
IList args = TreeAdapter.getArgs(tree);
String layout = layoutOfFather;
if (cons != null && !lex) {
String newLayout = getLayoutName(TreeAdapter.getProduction(tree));
// this approximation is possibly harmfull. Perhaps there is a chain rule defined in another module, which nevertheless
// switched the applicable layout. Until we have a proper type-analysis there is nothing we can do here.
if (newLayout != null) {
layout = newLayout;
}
}
java.util.List<Expression> kids = new ArrayList<Expression>(args.length());
for (IValue arg : args) {
Expression ast = liftRec((IConstructor) arg, lex, layout);
if (ast == null) {
return null;
}
kids.add(ast);
}
if (TreeAdapter.isLexical(tree)) {
return cache(tree, new Tree.Lexical(tree, kids));
}
else if (TreeAdapter.isList(tree)) {
// TODO: splice element lists (can happen in case of ambiguous lists)
return cache(tree, new Tree.List(tree, kids));
}
else if (TreeAdapter.isOpt(tree)) {
return cache(tree, new Tree.Optional(tree, kids));
}
else {
return cache(tree, new Tree.Appl(tree, kids));
}
}
else if (TreeAdapter.isCycle(tree)) {
return new Tree.Cycle(TreeAdapter.getCycleType(tree), TreeAdapter.getCycleLength(tree));
}
else if (TreeAdapter.isAmb(tree)) {
ISet args = TreeAdapter.getAlternatives(tree);
java.util.List<Expression> kids = new ArrayList<Expression>(args.size());
for (IValue arg : args) {
kids.add(liftRec((IConstructor) arg, lexicalFather, layoutOfFather));
}
if (kids.size() == 0) {
return null;
}
if (kids.size() == 1) {
return kids.get(0);
}
return cache(tree, new Tree.Amb(tree, kids));
}
else {
if (!TreeAdapter.isChar(tree)) {
throw new ImplementationError("unexpected tree type: " + tree);
}
return cache(tree, new Tree.Char(tree));
}
}