//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// PLEASE DO NOT EDIT WITHOUT THE EXPLICIT CONSENT OF THE AUTHOR! \\
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
using System;
using System.IO;
using System.Text;
using System.Collections;
using Ilog.Language.Util;
using Ilog.Language.Tools;
namespace Ilog.Language.Parsing
{
/**
* This class is the type of objects pushed on the semantic evaluation
* stack along with parser's states. It comes with two predefined
* properties that may be used in a rule's semantic action: a numeric
* one (NValue) of type double, and a symbolic one
* (SValue) of type string. The boolean property
* IsInteger is true whenever the NValue is actually
* an integer. If properties or fields of other types are needed, one
* may use the %nodeclass command for the appropriate symbol,
* which has for effect to make the type of the value it returns a
* subclass of this one containing the new fields.
*
*
*
* It is also the root of the parse tree which is built automatically
* when using the parser method call Parse(true).
*
* @see GenericParser
*
* @version Last modified on Wed Jun 01 08:07:34 2005 by hak
* @author Hassan Aït-Kaci
* @copyright © 2000 ILOG, S.A.
*/
public class ParseNode : Locatable
{
/**
* Constructs an uninitialized ParseNode object.
*/
public ParseNode ()
{
}
/**
* Constructs an anonymous ParseNode object (i.e.,
* with a null symbol), and sets its SValue
* property to the specified string. This is used in
* DynamicParser when a symbol that has been read is not
* a known terminal symbol, but may be a potential dynamic
* operator.
*/
public ParseNode (string value)
{
svalue = value;
}
/**
* Constructs a ParseNode object with its Symbol
* property set to the specified symbol. This is used by a
* DynamicParser when reading a new token and wrapping it
* into a DynamicToken where it can be restored in its
* original for upon backtracking.
*
* @see DynamicParser
* @see DynamicToken
*/
public ParseNode (Symbol symbol)
{
this.symbol = symbol;
}
/**
* Constructs a ParseNode object with its Symbol
* property set to the specified symbol, and NValue
* property set to the specified double value.
*/
public ParseNode (Symbol symbol, double value)
{
this.symbol = symbol;
nvalue = value;
}
/**
* Constructs a ParseNode object with its Symbol
* property set to the specified symbol, and NValue
* property set to the specified integer value.
*/
public ParseNode (Symbol symbol, int value)
{
this.symbol = symbol;
nvalue = value;
isInteger = true;
}
/**
* Constructs a ParseNode object with its Symbol
* property set to the specified symbol and SValue
* property set to the specified string.
*/
public ParseNode (Symbol symbol, string value)
{
this.symbol = symbol;
svalue = value;
}
/**
* Constructs a ParseNode object that is a (shallow) copy of
* of the specified ParseNode.
*/
public ParseNode (ParseNode node)
{
symbol = node.symbol;
svalue = node.svalue;
nvalue = node.nvalue;
isInteger = node.isInteger;
alternatives = node.alternatives;
children = node.children;
span = node.span;
}
/**
* This property is false by default and overridden to
* true in DynamicToken.
*
* @see DynamicToken
*/
internal virtual bool IsDynamic
{
get { return false; }
}
/**
* This parse node symbol.
*/
private Symbol symbol;
public Symbol @Symbol
{
get { return symbol; }
set { symbol = value; }
}
/**
* This holds this parse node numeric value if any. Its default
* value is Double.NaN.
*/
private double nvalue = Double.NaN;
public double NValue
{
get { return nvalue; }
set { nvalue = value; }
}
/**
* This is true iff the value in NValue is an integer.
* The default is false.
*/
private bool isInteger = false;
public bool IsInteger
{
get { return isInteger; }
set { isInteger = value; }
}
/**
* This holds a string that can be set for a parse node to carry a
* symbolic value. Its default is null.
*/
private string svalue = null;
public string SValue
{
get { return svalue; }
set { svalue = value; }
}
/**
* When non-null, this holds potential alternative forms for this
* parse node when non-deterministic. It is null by default.
*/
private ArrayList alternatives;
public ArrayList Alternatives
{
get { return alternatives; }
}
/**
* Add the specified parse node as an alternative form for this
* parse node.
*/
public void AddAlternative (ParseNode alternative)
{
if (alternatives == null)
alternatives = new ArrayList(2);
alternatives.Add(alternative);
}
/**
* This is true iff this parse node has one or more
* alternative forms.
*/
public bool HasAlternatives
{
get { return alternatives != null; }
}
/**
* This is true iff this parse node symbol has been set to a
* non-null value.
*/
public bool IsKnown
{
get { return symbol != null; }
}
/**
* This true iff this parse node's symbol is an error symbol.
*/
public bool IsError
{
get { return IsKnown && symbol.Name == "error"; }
}
/**
* This is true iff this parse node's symbol is the end of input.
*/
public bool IsEOI
{
get { return IsKnown && symbol.Name == "$E_O_I$"; }
}
/**
* This is this parse node location extent, if known.
*/
private Span span;
/**
* Returns this node' location extent if it is known, or a new
* uninitialized span.
*/
public Span @Span ()
{
return span == null ? span = new Span() : span;
}
/**
* Returns this node' location extent if it is known, or null.
*/
public Span GetSpan ()
{
return span;
}
/**
* Sets this node's location extent from the specified handle,
* and returns this parse node.
*/
internal ParseNode SetSpan (StackElement[] handle)
{
ParseNode start = null;
ParseNode end = null;
for (int i=0; i0;)
{
end = handle[i].Node;
if (end.IsLocated)
break;
}
if (start != null)
if (end != null)
SetSpan(start,end);
else
SetSpan(start);
else
if (end !=null)
SetSpan(end);
Locate();
return this;
}
/**
* This method (by default empty) is invoked anytime this node's
* span is set. It is meant to be overridden for locating
* specific Locatable members using the span of this
* parse node as the extent (either implicitly using the
* locates option of a %nodeclass declaration,
* or explicitly in the body of such a declaration).
*/
public virtual void Locate ()
{
}
/**
* Resets this parse node's location extent to unknown.
*/
internal void ResetSpan ()
{
span = null;
}
/**
* Sets this parse node's location extent to have the same start
* location as the specified start parse node's and the
* same end location as the end parse node's. Returns
* this parse node.
*/
internal Locatable SetSpan (ParseNode start, ParseNode end)
{
return SetStart(start.GetStart()).SetEnd(end.GetEnd());
}
/**
* Sets this parse node's location extent to the specified
* start and end locations, and returns this parse node.
*/
internal Locatable SetSpan (Location start, Location end)
{
return SetStart(start).SetEnd(end);
}
/**
* Sets the this parse node's location extent to that of
* the specified parse node.
*/
public Locatable SetSpan (ParseNode node)
{
return SetStart(node.GetStart()).SetEnd(node.GetEnd());
}
/**
* This is true iff this parse node's location extent is known.
*/
public bool IsLocated
{
get { return Span().IsKnown(); }
}
/**
* Returns this node's location extent start location.
*/
public Location GetStart ()
{
return Span().Start();
}
/**
* Sets this node's location extent start location to the
* specified location, and returns this parse node.
*/
public Locatable SetStart (Location location)
{
Span().SetStart(location);
return this;
}
/**
* Returns this node's location extent end location.
*/
public Location GetEnd ()
{
return Span().End();
}
/**
* Sets this node's location extent end location to the specified
* location, and returns this parse node.
*/
public Locatable SetEnd (Location location)
{
Span().SetEnd(location);
return this;
}
/**
* Returns the file name where this node's constituents start from if
* any; or null
*/
public string GetFile ()
{
return Span().GetStartFile();
}
/**
* Returns the line number in the input stream corresponding to the
* start location of this node's extent.
*/
public int GetLineNumber ()
{
return Span().GetStartLine();
}
/**
* Sets the file name where this node's constituents are, and returns
* this parse node.
*/
public ParseNode SetFile (string file)
{
Span().SetStartFile(file);
Span().SetEndFile(file);
return this;
}
/**
* Sets the line number in the input stream corresponding to this
* node's location extent start, and returns this parse node. This
* is a dangerous method to use as it can set the start line number
* to a value inconsistent with its end's. Therefore, a warning is
* issued.
*/
public ParseNode SetLineNumber (int line)
{
Syntax.Grammar.LoudWarning
("Setting the line number of a ParseNode should not be done! "
+ NodeInfo());
Span().SetStartLine(line);
return this;
}
/**
* This is the sequence of parse nodes that are the constituents of
* this parse node when a parse tree is built. It is null by default.
*/
private ArrayList children;
public ArrayList Children
{
get { return children; }
set { children = value; }
}
/**
* Returns true iff this node has children.
*/
public bool HasChildren
{
get { return children != null; }
}
/**
* Returns the number of constituents of this node.
*/
public int NumberOfChildren
{
get { return children == null ? 0 : children.Count; }
}
/**
* If a parse tree has been built, this returns the i-th
* element in the sequence of parse nodes that are this node's
* constituents. Otherwise, returns null. NB: the
* argument i ranges from 1 to
* NumberOfChildren.
*/
public ParseNode Child (int i)
{
if (children == null)
return null;
return (ParseNode)children[i-1];
}
/**
* If a parse tree has been built, this is the first element in the
* sequence of parse nodes that are this node's constituents.
* Otherwise, it is null.
*/
public ParseNode FirstChild
{
get { return Child(1); }
}
/**
* If a parse tree has been built, this is the last element in the
* sequence of parse nodes that are this node's constituents.
* Otherwise, it is null.
*/
public ParseNode LastChild
{
get { return children == null ? null : (ParseNode)children[children.Count-1]; }
}
/**
* When this parse node is a dynamic operator, this is the operator.
* It is null otherwise.
*/
private Operator @operator;
public Operator @Operator
{
get { return @operator; }
set { @operator = value; }
}
/**
* This is true iff this pare node is a dynamic operator.
*/
public bool IsOperator
{
get { return @operator != null; }
}
/**
* When this parse node stands for an operator or a terminal, this is
* its precedence value. Otherwise, Syntax.Grammar.MIN_PRECEDENCE.
*/
public int Precedence
{
get
{
if (IsOperator)
return @operator.Precedence;
if (IsTerminal)
return ((Terminal)symbol).Precedence;
return Syntax.Grammar.MIN_PRECEDENCE;
}
}
/**
* When this parse node stands for an operator or a terminal, this is
* its associativity value. Otherwise, Syntax.Grammar.NON_ASSOCIATIVE.
*/
public int Associativity
{
get
{
if (IsOperator)
return @operator.Associativity;
if (IsTerminal)
return ((Terminal)symbol).Associativity;
return Syntax.Grammar.NON_ASSOCIATIVE;
}
}
/**
* When this parse node stands for an operator, this is its fixity
* value. Otherwise, -1.
*/
public int Fixity
{
get { return IsOperator ? @operator.Fixity : -1; }
}
/**
* Returns an almost complete copy of the specified node by
* copying the values of all its properties except Symbol,
* Children, and Span. The symbol of the copy is
* set to that of this parse node (not the specified node), and the
* children and span are set to null.
*/
public ParseNode Copy (ParseNode node)
{
ParseNode copy = new ParseNode(node);
copy.symbol = symbol;
copy.children = null;
copy.span = null;
return copy;
}
/**
* Returns a shallow copy of this parse node.
*/
public ParseNode Copy ()
{
return (ParseNode)MemberwiseClone();
}
/**
* Spawns a framed graphical display of the parse tree rooted in this
* node.
*/
public void Display ()
{
// new TreeDisplay(this);
}
/**
* Spawns a framed graphical display of the parse tree rooted in this
* node and corresponding to the specified source file.
*/
public void Display (string source)
{
// new TreeDisplay(this,source);
}
/**
* Prints the parse tree rooted in this node on stdout.
*/
public void Show ()
{
Show(0,Console.Out);
}
/**
* Prints the parse tree rooted in this node on the specified
* output stream.
*/
public void Show (TextWriter stream)
{
Show(0,stream);
}
/**
* Prints the parse tree rooted in this node on the specified output
* stream with the given initial margin.
*/
public void Show (int margin, TextWriter stream)
{
for (int i=0; iParseNode to the set of constituents
* of this node to build a parse tree.
*/
internal void AddChild (ParseNode kid)
{
if (children == null)
children = new ArrayList();
children.Add(kid);
}
/**
* If type is GenericParser.FULL_TREE, adds the
* specified child as is; otherwise, adds a child that is a "leaner"
* tree structure than the raw syntax tree of the specified child
* node obtained from it by eliminating empty reduction branches,
* collapsing single-child branches into a node labeled like its
* lowermost node, and flattenning immediate symbol recursion
* (i.e., a nonterminal occurring in the RHS of a rule having
* it as LHS).
*/
internal void AddChild (ParseNode kid, int type)
{
if (type == GenericParser.FULL_TREE || kid.IsLeafNode)
{
AddChild(kid);
return;
}
if (kid.IsEmptyNode)
return;
if (kid.NumberOfChildren == 1)
{
AddChild((ParseNode)kid.children[0]);
return;
}
if (symbol.Name == kid.symbol.Name)
for (int j=0; jtrue iff this node corresponds to a terminal
* symbol.
*/
public bool IsTerminal
{
get { return symbol is Terminal; }
}
/**
* This is true iff this node is a leaf in the parse tree
* (i.e., iff it corresponds to a terminal symbol or an
* anonymous symbol).
*/
public bool IsLeafNode
{
get { return IsTerminal || !IsKnown; }
}
/**
* This is true iff this node is an inner node in the parse
* tree (i.e., iff it corresponds to a nonterminal symbol).
*/
public bool IsInnerNode
{
get { return symbol is NonTerminal; }
}
/**
* This is true iff this node is a null inner node
* (i.e., iff it corresponds to an empty derivation). These
* nodes have no children.
*/
public bool IsEmptyNode
{
get { return IsInnerNode && children == null; }
}
/**
* This is true iff this node carries a value (which is
* either in its SValue or NValue field).
*/
public bool HasValue
{
get { return svalue != null || !Double.IsNaN(nvalue); }
}
/**
* Returns an explicit string for this node's location.
*/
public string LocationString ()
{
return Misc.LocationString(this);
}
/**
* Returns a string representation of this node's information
* contents: its string form and its location if known.
*/
public string NodeInfo ()
{
if (!IsLocated)
return ToString();
return new StringBuilder()
.Append(this).Append(": ").Append(Span()).ToString();
}
/**
* Two ParseNodes are considered equal iff they carry the same info.
*/
public override bool Equals (Object other)
{
if (!(other is ParseNode) || other == null)
return false;
ParseNode that = (ParseNode)other;
return this.NodeInfo().Equals(that.NodeInfo());
// if (IsLocated && !that.IsLocated || !IsLocated && that.IsLocated)
// return false;
// if (!span.Equals(that.span))
// return false;
// if (IsOperator)
// return that.IsOperator && @operator.Equals(that.@operator);
// if (IsKnown && !that.IsKnown || !IsKnown && that.IsKnown)
// return false;
// if (IsKnown && symbol.Index != that.symbol.Index)
// return false;
// if (svalue != null)
// return that.svalue.Equals(svalue);
// if (!Double.IsNaN(nvalue))
// return that.nvalue == nvalue;
// return false;
}
/**
* Returns a hash code for this parse node.
*/
public override int GetHashCode ()
{
int code = 0;
if (IsLocated)
code ^= span.GetHashCode();
if (IsOperator)
code ^= @operator.GetHashCode();
else
{
if (IsKnown)
code ^= symbol.GetHashCode();
if (svalue != null)
code ^= svalue.GetHashCode();
if (!Double.IsNaN(nvalue))
code ^= (int)nvalue;
}
return code;
}
/**
* Returns a string representation of this node as a single
* alternative.
*/
private String StringForm ()
{
if (IsOperator)
return @operator.ToString();
StringBuilder s = new StringBuilder
(symbol == null ? "'DYNAMIC'" : symbol.ToString());
if (IsLeafNode && HasValue)
{
s.Append("(");
if (svalue != null)
{
s.Append(SValue);
if (!Double.IsNaN(NValue))
s.Append(",");
}
if (!Double.IsNaN(NValue))
if (isInteger)
s.Append(((int)NValue));
else
s.Append(NValue);
s.Append(")");
}
return s.ToString();
}
/**
* Returns a string representation of this node, along, possibly, with
* all its alternatives if any.
*/
public override string ToString ()
{
StringBuilder s = new StringBuilder(StringForm());
// if (HasAlternatives)
// foreach (ParseNode node in alternatives)
// s.Append(" | ").Append(node.StringForm());
return s.ToString();
}
}
}