/*
* Vitry, copyright (C) Hans Hoglund 2011
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING.txt for details.
*/
package vitry.runtime.parse;
import java.util.Iterator;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import vitry.runtime.*;
import vitry.runtime.error.*;
import vitry.runtime.struct.*;
import vitry.runtime.StandardFunction.Unary;
/**
* Reflects antlr syntax trees into Vitry. Each node is a Product containing
* its children. The head token is the first child.
*
* @author Hans Hoglund
*/
class VitryTree extends CommonTree implements Product
{
private final Product delegee = VitryRuntime.productFrom(this);
private Seq<Pattern> seq = null;
private boolean generated = false;
public VitryTree(Token payload) {
super(payload);
}
public Pattern head()
{
if (!generated)
{
generate();
}
if (hasPayload())
{
return wrap(token);
}
else
{
return (seq == null) ? null : seq.head();
}
}
public Seq<Pattern> tail()
{
if (!generated)
{
generate();
}
if (hasPayload())
{
return seq;
}
else
{
return (seq == null) ? null : seq.tail();
}
}
public boolean hasTail()
{
if (hasPayload())
{
return seq != null;
}
else
{
return seq != null && seq.tail() != null;
}
}
public boolean hasPayload()
{
return token != null;
}
public Iterator<Pattern> iterator()
{
return new SeqIterator<Pattern>(this);
}
/**
* Converts the child list to a sequence.
* Replaces singleton with the token they contain.
*/
private void generate()
{
Iterable<Pattern> children = (Iterable<Pattern>) this.children;
if (children == null)
{
this.seq = null;
}
else
{
this.seq = Seqs.from(children).map(new Unary()
{
public Object apply(Object o) throws InvocationError
{
CommonTree t = (CommonTree) o;
if (t.getChildCount() == 0 && t.getToken() != null)
{
return wrap(t.getToken());
}
else
{
return t;
}
}
});
}
this.generated = true;
}
private static VitryToken wrap(Token t)
{
return new VitryToken(t);
}
// Delegate rest of interface
public boolean eq(Object o)
{
return delegee.eq(o);
}
public Product mapProduct(Function fn)
{
return delegee.mapProduct(fn);
}
public boolean eq(Atom o)
{
return delegee.eq(o);
}
public Product prepend(Pattern p)
{
return delegee.prepend(p);
}
public boolean eq(Tagged o)
{
return delegee.eq(o);
}
public boolean eq(Product o)
{
return delegee.eq(o);
}
public <U> Seq<U> map(Function fn)
{
return delegee.map(fn);
}
public boolean eq(Function p)
{
return delegee.eq(p);
}
public boolean eq(List p)
{
return delegee.eq(p);
}
public SeqIterator<Pattern> seqIterator()
{
return delegee.seqIterator();
}
public boolean eq(Set o)
{
return delegee.eq(o);
}
public boolean eq(Union o)
{
return delegee.eq(o);
}
public boolean eq(Intersection o)
{
return delegee.eq(o);
}
public boolean eq(Type o)
{
return delegee.eq(o);
}
public boolean match(Object o)
{
return delegee.match(o);
}
public boolean match(Atom o)
{
return delegee.match(o);
}
public boolean match(Tagged o)
{
return delegee.match(o);
}
public boolean match(Product p)
{
return delegee.match(p);
}
public boolean match(Function p)
{
return delegee.match(p);
}
public boolean match(List p)
{
return delegee.match(p);
}
public boolean match(Set p)
{
return delegee.match(p);
}
public boolean match(Union p)
{
return delegee.match(p);
}
public boolean match(Intersection p)
{
return delegee.match(p);
}
public boolean match(Type p)
{
return delegee.match(p);
}
public boolean eqFor(Pattern o)
{
return delegee.eqFor(o);
}
public boolean matchFor(Pattern p)
{
return delegee.matchFor(p);
}
public String toString()
{
return delegee.toString();
}
public boolean canDestruct()
{
return delegee.canDestruct();
}
public Seq<Pattern> destruct()
{
return delegee.destruct();
}
}