|
PsiTerm.java
|
// FILE. . . . . /home/hak/hlt/src/hlt/osf/base/PsiTerm.java // EDIT BY . . . Hassan Ait-Kaci // ON MACHINE. . Hp-Dv7 // STARTED ON. . Sun Dec 16 01:34:12 2012
This is the class of ψ-terms as explained in the specification.
|
package hlt.osf.base;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
import hlt.language.tools.Misc;
import hlt.language.util.ArrayList;
public class PsiTerm extends OsfExpression
{
| This ψ-term's tag. |
private Tag _tag;
| This ψ-term's sort expression. |
private SortExpression _sort;
| This ψ-term's positional subterms if any. |
private ArrayList _positions;
| This ψ-term's featured subterms, if any. |
private HashMap _features;
| This is the next position where to store a new implicitly contiguous positional subterms (counting positions starting at 1 instead of 0). Since we may not rely on add to add contiguous positional subterms (they are set using the set method), we need to update this value for adding a new inplicitly contiguous positional subterm and must always ensure that the capacity is sufficient. This does not mean that it is a free position since a subterm may have already been stored there using an explicit feature position (in which case the new and old subterm must be merged). This value and _maxPosition must be ketp consistent. |
private int _nextContiguousPosition = 0;
| This is the highest position that has an actual positional subterm for this ψ-term (counting postions starting at 1 instead of 0). Since subterms may be also stored using explicit positions that may be out of order and non-contiguous using the set method, this value must be updated explicit. We must always ensure that the capasity is sufficient. |
private int _maxPosition = 0;
/* ************************************************************************ */
public PsiTerm ()
{
_sort = new SymbolSortExpression("@");
}
public PsiTerm (Tag tag)
{
setTag(tag);
}
public PsiTerm (String sortName)
{
_sort = new SymbolSortExpression(sortName);
}
public PsiTerm (SortExpression sort)
{
_sort = sort;
}
/* ************************************************************************ */
public Tag tag ()
{
return _tag;
}
public PsiTerm deref ()
{
return _tag.deref().term();
}
| Set this tag's ψ-term to the specified tag, sets the specified tag's term to this ψ-term, and returns this tag. |
public PsiTerm setTag (Tag tag)
{
_tag = tag;
tag.setTerm(this);
return this;
}
/* ************************************************************************ */
| Returns the sort expression of this ψ-term, or null if none has been set for it yet. |
public SortExpression sort ()
{
return _sort;
}
| Sets this ψ-term's sort expression to the provided one and returns this ψ-term. |
public PsiTerm setSort (SortExpression sort)
{
_sort = sort;
return this;
}
/* ************************************************************************ */
public ArrayList positions ()
{
return _positions;
}
public HashMap features ()
{
return _features;
}
/* ************************************************************************ */
public int maxPosition ()
{
return _maxPosition;
}
| Returns the subterm at the next contiguous position if any, or null if there isn't any. |
public PsiTerm getNextContiguousPositionSubterm ()
{
if (_positions == null || _nextContiguousPosition == 0)
return null;
return (PsiTerm)_positions.get(_nextContiguousPosition);
}
| This stores the provided term at the next contiguous position, whether or not a term is already stored there. |
public void addContiguousPositionSubterm (PsiTerm psiterm)
{
if (_positions == null)
_positions = new ArrayList(3);
_positions.ensureCapacity(_nextContiguousPosition+1);
_positions.set(_nextContiguousPosition,psiterm);
_nextContiguousPosition++;
_maxPosition = Math.max(_maxPosition,_nextContiguousPosition);
}
| This returns the subterm at the given position if there is one stored there, or null otherwise, where positions are counted sarting from 1. |
public PsiTerm getSubterm (int position)
{
if (_positions == null || position > _maxPosition)
return null;
return (PsiTerm)_positions.get(position-1); // -1 since positions are counted from 1
}
| This stores the provided ψ-term at the specified position (counting positions from 1), whether or not a term is already stored there. |
public void setSubterm (int position, PsiTerm psiterm)
{
if (_positions == null)
_positions = new ArrayList(position);
_positions.ensureCapacity(position);
_positions.set(position-1,psiterm); // -1 since positions are counted from 1
_maxPosition = Math.max(_maxPosition,position);
}
| This returns the subterm for the specified feature (which may be null). |
public PsiTerm getSubterm (Feature feature)
{
if (_features == null || _features.isEmpty())
return null;
return (PsiTerm)_features.get(feature);
}
| This stores the provided term for the specified feature, whether or not a term is already stored there. |
public void setSubterm (Feature feature, PsiTerm psiterm)
{
if (_features == null)
_features = new HashMap();
_features.put(feature,psiterm);
}
/* ************************************************************************ */
| This merges the uninterpreted structure of the specified ψ-term into this one's as explained in the specification, and returns this ψ-term resulting after the merging. This assumes that the specified ψ-term has been dereferenced to its true identity. NB: Merging subterms must ensure dereferencing them first. |
public PsiTerm merge (PsiTerm other)
{
// if these are the same psiterm, no need to do anything:
if (this == other)
return this;
// merge the tags, binding the other term's tag to this one's:
other.tag().bind(_tag);
// merge the sort expressions if needed (i.e., ignoring top):
if (_sort.isSymbol() && ((SymbolSortExpression)_sort).sort().isTop())
_sort = other.sort();
else
if (!(other.sort().isSymbol() && ((SymbolSortExpression)other.sort()).sort().isTop()))
_sort = new AndSortExpression(_sort, other.sort());
// merge the features:
if (_features == null)
_features = other.features();
if (other.features() != null)
for (Iterator it=other.features().keySet().iterator(); it.hasNext();)
{
Feature feature = (Feature)it.next();
PsiTerm subterm = (PsiTerm)_features.get(feature);
PsiTerm otherSubterm = (PsiTerm)other.features().get(feature);
if (subterm == null)
{
if (otherSubterm != null)
_features.put(feature,otherSubterm.deref());
}
else
{
if (otherSubterm != null)
_features.put(feature,subterm.deref().merge(otherSubterm.deref()));
}
}
// merge the positions:
if (_positions == null)
_positions = other.positions();
if (other.positions() != null)
for (int i = other.maxPosition(); i-->0;)
{
PsiTerm subterm = (i < _maxPosition) ? (PsiTerm)_positions.get(i) : null;
PsiTerm otherSubterm = (PsiTerm)other.positions().get(i);
if (subterm == null)
{
if (otherSubterm != null)
setSubterm(i,otherSubterm.deref());
}
else
{
if (otherSubterm != null)
_positions.set(i,subterm.deref().merge(otherSubterm.deref()));
}
}
return this;
}
/* ************************************************************************ */
| Returns a pretty-printed form of this ψ-term. |
public String displayForm ()
{
return deref().prettyPrint(0,new HashSet()).toString();
}
/* ************************************************************************ */
| Flag to determine whether or not to evaluate sort expressions. This is false by default. |
private static boolean _evalSorts = false;
| Returns the current sort expression evaluation flag's value. |
public static boolean evaluateSorts ()
{
return _evalSorts;
}
| Toggles sort expression evaluation. |
public static void toggleSortEvaluation ()
{
_evalSorts = !_evalSorts;
}
| Returns a pretty printed form of this ψ-term, starting at the specified margin width and the array list of already processed tags. |
public StringBuffer prettyPrint (int margin, HashSet tags)
{
StringBuffer buf = new StringBuffer();
if (tags.contains(_tag))
buf.append(_tag.name());
else
{
String header = _evalSorts
? _sort.maxLowerBound() // the header is the interpreted sort expression
: _sort.toString(); // the header is the uninterpreted sort expression
if (_tag.isShared())
{ // this is a shared tag, so the header must start with tagging:
header = _tag.name() + " : " + header;
// since in this case the sort expression is preceded by
// tagging, the margin is augmented with the length of the tag
// and the 3 characters " : " that follow it:
margin += _tag.name().length() + 3;
}
tags.add(_tag);
buf.append(header);
if (_positions != null || _features != null)
{ // When this psiterm has a body, the open and closed
// parentheses, as well as the comma between subterms, are
// always aligned vertically under the first character of the
// sort expression whether tagged or not. So we must compute
// the marginal offset depending on whether or not the sort
// expression is preceded by a tag
String offset = Misc.repeat(margin,' ');
buf.append('\n' + offset + "( ");
// do the positions
if (_positions != null)
{
int index = 0;
// as long as there is no gap -> no feature needed
for (index=0; index<_maxPosition; index++)
{
PsiTerm subterm = (PsiTerm)_positions.get(index);
if (subterm == null)
break;
// pretty-print the subterm with a margin augmented with
// the 2 characters of the initial "( " or ", "
buf.append(subterm.deref().prettyPrint(margin+2,tags));
buf.append('\n');
if (index<_maxPosition-1)
buf.append(offset + ", ");
}
// above a gap up to maxPosition, print the position as a
// feature for non null subterms
for (;index<_maxPosition; index++)
{
PsiTerm subterm = (PsiTerm)_positions.get(index);
if (subterm != null)
{
int position = index+1;
subterm = subterm.deref();
buf.append(position + " => ");
// pretty-print the subterm with a margin augmented
// with the width of the position + the 2 characters
// of the initial "( " or ", " + the 4 characters of
// " => "
buf.append(subterm.prettyPrint(margin+Misc.numWidth(position)+6,tags));
buf.append('\n');
if (index<_maxPosition-1)
buf.append(offset + ", ");
}
}
}
// do the features
if (_features != null)
for (Iterator it=_features.keySet().iterator(); it.hasNext();)
{
Feature feature = (Feature)it.next();
PsiTerm subterm = ((PsiTerm)_features.get(feature)).deref();
buf.append(feature.name() + " => ");
// pretty-print the subterm with a margin augmented with
// the length of the feature name + the 2 characters of the
// initial "( " or ", " + the 4 characters of " => "
buf.append(subterm.prettyPrint(margin+feature.name().length()+6,tags));
buf.append('\n');
if (it.hasNext())
buf.append(offset + ", ");
}
buf.append(offset + ')');
}
}
return buf;
}
}
This file was generated on Fri Sep 06 18:27:34 CEST 2013 from file PsiTerm.java
by the hlt.language.tools.Hilite Java tool written by Hassan Aït-Kaci