/*
* Node.cs
*
* This work 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 2 of the License,
* or (at your option) any later version.
*
* This work 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* As a special exception, the copyright holders of this library give
* you permission to link this library with independent modules to
* produce an executable, regardless of the license terms of these
* independent modules, and to copy and distribute the resulting
* executable under terms of your choice, provided that you also meet,
* for each linked independent module, the terms and conditions of the
* license of that module. An independent module is a module which is
* not derived from or based on this library. If you modify this
* library, you may extend this exception to your version of the
* library, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Copyright (c) 2003 Per Cederberg. All rights reserved.
*/
using System.Collections;
using System.IO;
namespace PerCederberg.Grammatica.Parser {
/**
* An abstract parse tree node. This class is inherited by all
* nodes in the parse tree, i.e. by the token and production
* classes.
*
* @author Per Cederberg, <per at percederberg dot net>
* @version 1.2
*/
public abstract class Node {
/**
* The parent node.
*/
private Node parent = null;
/**
* The computed node values.
*/
private ArrayList values = null;
/**
* Checks if this node is hidden, i.e. if it should not be
* visible outside the parser.
*
* @return true if the node should be hidden, or
* false otherwise
*/
internal virtual bool IsHidden() {
return false;
}
/**
* Returns the node type id. This value is set as a unique
* identifier for each type of node, in order to simplify
* later identification.
*
* @return the node type id
*/
public abstract int GetId();
/**
* Returns the node name.
*
* @return the node name
*/
public abstract string GetName();
/**
* The line number of the first character in this node. If the
* node has child elements, this value will be fetched from
* the first child.
*
* @return the line number of the first character, or
* -1 if not applicable
*/
public virtual int GetStartLine() {
int line;
for (int i = 0; i < GetChildCount(); i++) {
line = GetChildAt(i).GetStartLine();
if (line >= 0) {
return line;
}
}
return -1;
}
/**
* The column number of the first character in this node. If
* the node has child elements, this value will be fetched
* from the first child.
*
* @return the column number of the first token character, or
* -1 if not applicable
*/
public virtual int GetStartColumn() {
int col;
for (int i = 0; i < GetChildCount(); i++) {
col = GetChildAt(i).GetStartColumn();
if (col >= 0) {
return col;
}
}
return -1;
}
/**
* The line number of the last character in this node. If the
* node has child elements, this value will be fetched from
* the last child.
*
* @return the line number of the last token character, or
* -1 if not applicable
*/
public virtual int GetEndLine() {
int line;
for (int i = GetChildCount() -1; i >= 0; i--) {
line = GetChildAt(i).GetEndLine();
if (line >= 0) {
return line;
}
}
return -1;
}
/**
* The column number of the last character in this node. If
* the node has child elements, this value will be fetched
* from the last child.
*
* @return the column number of the last token character, or
* -1 if not applicable
*/
public virtual int GetEndColumn() {
int col;
for (int i = GetChildCount() -1; i >= 0; i--) {
col = GetChildAt(i).GetEndColumn();
if (col >= 0) {
return col;
}
}
return -1;
}
/**
* Returns the parent node.
*
* @return the parent parse tree node
*/
public Node GetParent() {
return parent;
}
/**
* Sets the parent node.
*
* @param parent the new parent node
*/
internal void SetParent(Node parent) {
this.parent = parent;
}
/**
* Returns the number of child nodes.
*
* @return the number of child nodes
*/
public virtual int GetChildCount() {
return 0;
}
/**
* Returns the child node with the specified index.
*
* @param index the child index, 0 <= index < count
*
* @return the child node found, or
* null if index out of bounds
*/
public virtual Node GetChildAt(int index) {
return null;
}
/**
* Returns the number of descendant nodes.
*
* @return the number of descendant nodes
*
* @since 1.2
*/
public int GetDescendantCount() {
int count = 0;
for (int i = 0; i < GetChildCount(); i++) {
count += 1 + GetChildAt(i).GetDescendantCount();
}
return count;
}
/**
* Returns the number of computed values associated with this
* node. Any number of values can be associated with a node
* through calls to AddValue().
*
* @return the number of values associated with this node
*/
public int GetValueCount() {
if (values == null) {
return 0;
} else {
return values.Count;
}
}
/**
* Returns a computed value of this node, if previously set. A
* value may be used for storing intermediate results in the
* parse tree during analysis.
*
* @param pos the value position, 0 <= pos < count
*
* @return the computed node value, or
* null if not set
*/
public object GetValue(int pos) {
if (values == null || pos < 0 || pos >= values.Count) {
return null;
} else {
return values[pos];
}
}
/**
* Returns the list with all the computed values for this
* node. Note that the list is not a copy, so changes will
* affect the values in this node (as it is the same object).
*
* @return a list with all values, or
* null if no values have been set
*/
public ArrayList GetAllValues() {
return values;
}
/**
* Adds a computed value to this node. The computed value may
* be used for storing intermediate results in the parse tree
* during analysis.
*
* @param value the node value
*/
public void AddValue(object value) {
if (value != null) {
if (values == null) {
values = new ArrayList();
}
values.Add(value);
}
}
/**
* Adds a set of computed values to this node.
*
* @param values the vector with node values
*/
public void AddValues(ArrayList values) {
if (values != null) {
for (int i = 0; i < values.Count; i++) {
AddValue(values[i]);
}
}
}
/**
* Removes all computed values stored in this node.
*/
public void RemoveAllValues() {
values = null;
}
/**
* Prints this node and all subnodes to the specified output
* stream.
*
* @param output the output stream to use
*/
public void PrintTo(TextWriter output) {
PrintTo(output, "");
output.Flush();
}
/**
* Prints this node and all subnodes to the specified output
* stream.
*
* @param output the output stream to use
* @param indent the indentation string
*/
private void PrintTo(TextWriter output, string indent) {
output.WriteLine(indent + ToString());
indent = indent + " ";
for (int i = 0; i < GetChildCount(); i++) {
GetChildAt(i).PrintTo(output, indent);
}
}
}
}