//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // 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(); } } }