CS143-Lab/assignments/PA4J/TreeNode.java
2023-03-16 15:55:37 +00:00

336 lines
12 KiB
Java

/*
Copyright (c) 2000 The Regents of the University of California.
All rights reserved.
Permission to use, copy, modify, and distribute this software for any
purpose, without fee, and without written agreement is hereby granted,
provided that the above copyright notice and the following two
paragraphs appear in all copies of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
import java.io.PrintStream;
/** The base class for all AST nodes.
After lexical analysis and parsing, a Cool program is represented
internally by the Cool compiler as an abstract syntax tree. The
project comes with a definition of Cool abstract syntax trees (ASTs)
built in. The AST package is by far the largest piece of code in
the base system and requires the most time to learn. The learning
process is made more complex because the AST code is generated
automatically from a specification in the file
<code>cool-tree.aps</code>. While the generated code is quite simple
and regular in structure, it is also devoid of comments. This
section serves as the documentation for the AST package.
<h3>Phyla and Constructors</h3>
The AST data type provides a class for representing each type of
Cool expression. There is a class for <code>let</code> expressions,
another class of <code>+</code> expressions, and so on. Objects of
these classes are nodes in Cool abstract syntax trees. For example,
an expression <code>e1 + e2</code> is represented by a
<code>+</code> expression object, which has two subtrees: one for
the tree representing the expression <code>e1</code> and one for
the tree representing the expression <code>e2</code>.
<p>
The Cool abstract syntax is specified in a language called APS. In
APS terminology, the various kinds of abstract syntax tree nodes
(<code>let</code>, <code>+</code>, etc.) are called
<em>constructors</em>. (Don't confuse this use of the term
"constructor" with Java constructors; while similar, this is a
slightly different meaning taken from functional languages that
predates Java.) The form of the AST is described by a set of
<em>phyla</em>. Each phylum has one or more constructors.
<p>
Phyla are really just types. That is, instead of having one large
group of undifferentiated constructors, the constructors are grouped
together according to function, so that, for example, the
constructors for expression ASTs are distinguished from the
constructors for class ASTs. The phyla are defined at the beginning
of <code>cool-tree.aps</code>:
<pre>
module COOL begin phylum
Program;
phylum Class_;
phylum Classes = LIST[Class_];
phylum Feature;
phylum Features = LIST[Feature];
phylum Formal;
phylum Formals = LIST[Formal];
phylum Expression;
phylum Expressions = LIST[Expression];
phylum Case;
phylum Cases = LIST[Case];
</pre>
From the definition it can be seen that there are two distinct kinds
of phyla: "normal" phyla and list phyla. "Normal" phyla each
have associated constructors; list phyla have a fixed set of list
operations.
<p>
Each constructor takes typed arguments and returns a typed result.
The types may either be phyla or any ordinary Java type. In fact,
the phyla declarations are themselves compiled into Java class
declarations by an APS compiler. A sample constructor definition is
<pre>
constructor class_(name : AbstractSymbol;
parent : AbstractSymbol;
features : Features;
filename : AbstractSymbol) : Class_;
</pre>
This declaration specifies that the <code>class_</code> constructor
takes four arguments: an <code>AbstractSymbol</code> (a type
identifier) for the class name, an <code>AbstractSymbol</code>
(another type identifier) for the parent class, a
<code>Features</code>, and an <code>AbstractSymbol</code> for the
filename in which the class definition occurs. (the name
<code>class_</code> is chosen to avoid a conflict with the Java
keyword <b>class</b>.) The phylum <code>Features</code> is defined
to be a list of <code>Feature</code>'s by the declaration
<pre>
phylum Features = LIST[Feature];
</pre>
See <a href="ListNode.html">ListNode</a> for a description of the
operations defined on AST lists.
<p>
To invoke the class constructor, you allocate a new node object
supplying it with the right arguments, e.g. <code>new
class_(...)</code>. In <code>cool.cup</code> there is the following
example of a use of the <code>class_</code> constructor:
<pre>
class ::= CLASS TYPEID:n INHERITS TYPEID:p LBRACE optional_feature_list:f RBRACE SEMI
{: RESULT = new class_(curr_lineno(), n, p, f, curr_filename()); :}
</pre>
Allocating a new <code>class_</code> object, builds a
<codeClass_</code> tree node with the four arguments as children.
Because the phyla (types) of the arguments are declared, the Java
type checker enforces that the <code>class_</code> constructor is
applied only to arguments of the appropriate type. See Section 6.5
of the "Tour of Cool Support Code" and <code>cool-tree.aps</code> to
learn the definitions of the other constructors. (Comments
in <code>cool-tree.aps</code> begin with two hyphens "--".)
<p>
NOTE: there is a real danger of getting confused because the same
names are used repeatedly for different entities in different
contexts. In the example just above, small variations of the name
<em>class</em> are used for a terminal (<code>CLASS</code>), a
non-terminal (<code>class</code>), a constructor
(<code>class_</code>), and a phylum (<code>Class_</code>). These
uses are all distinct and mean different things. Most uses are
distinguished consistently by capitalization, but a few are not.
When reading the code it is important to keep in mind the role of
each symbol.
<h3>The AST Class Hierarchy</h3>
All AST classes are derived from this class
(<em>TreeNode</em>). (The list classes are actually derived from <a
href="ListNode.html">ListNode</a>, which is a refinement of
<em>TreeNode</em>.) All of the lists are lists of
<em>TreeNode</em>s.
<p>
The <em>TreeNode</em> class definition contains everything needed in
an abstract syntax tree node except information specific to
particular constructors.
<p>
Each of the constructors is a class derived from the appropriate
phyla.
<h3>Class Members</h3>
Each class definition of the tree package comes with a number of
members. Some of the member functions are discussed below. This
section describes the data members and some more (but not all) of
the rest of the functions, as well as how to add new members to the
classes.
Each constructor has data members defined for each component of that
constructor. The name of the member is the name of the field in the
constructor, and it is only visible to member functions of the
constructor's class or derived classes. For example, the
<code>class_</code> constructor has four data members:
<pre>
Symbol name;
Symbol parent;
Features features;
Symbol filename;
</pre>
Here is a complete use of one member:
<pre>
class class_ extends Class_ {
...
AbstractSymbol getParent() { return parent; }
...
}
...
Class_ c;
AbstractSymbol p;
c = new class(lineno, AbstractTable.idtable.add_string("Foo",3),
AbstractTable.idtable.add_string("Bar"),
new Features(lineno),
AbstractTable.stringtable.add_string("filename"));
p = c->get_parent(); // Sets p to the symbol for "Bar"
...
</pre>
It will be useful in writing a Cool compiler to extend the AST with
new functions such as <code>getParent()</code>. Simply modify the
<code>cool-tree.java</code> file to add functions to the class of
the appropriate phylum or constructor.
<h3>Tips on Using the Tree Package</h3>
There are a few common errors people make using a tree package.
<ul>
<li>The tree package implements an abstract data type. Violating
the interface (e.g., by unwarranted casting, etc.) invites disaster.
Stick to the interface as it is defined. When adding new members to
the class declarations, be careful that those members do not perturb
the interface for the existing functions.
<li>The value <code>null</code> is not a valid component of any AST.
Never use <code>null</code> as an argument to a constructor.
<li>The tree package functions perform checks to ensure that trees
are used correctly. If something bad is detected, the function
<code>Utilities.fatalError()</code> is invoked to terminate
execution and a stack trace is printed to the console.
</ul>
*/
abstract class TreeNode {
/** line in the source file from which this node came. */
protected int lineNumber;
/** Builds a new tree node
*
* @param lineNumber the line in the source file from which this node came.
* */
protected TreeNode(int lineNumber) {
this.lineNumber = lineNumber;
}
/** Creates a copy of this node.
*
* @return a copy of this node
* */
public abstract TreeNode copy();
/** Sets the values of this node object to the values of a given node.
*
* @param other the other node
* @return this node
* */
public TreeNode set(TreeNode other) {
this.lineNumber = other.lineNumber;
return this;
}
/** Retreives the line number from which this node came.
*
* @return the line number
* */
public int getLineNumber() {
return lineNumber;
}
/** Pretty-prints this node to this output stream.
*
* @param out the output stream
* @param n the number of spaces to indent the output
* */
public abstract void dump(PrintStream out, int n);
/** Copies a boolean value.
*
* This method is used internally by the generated AST classes
* */
protected Boolean copy_Boolean(Boolean b) {
return new Boolean(b.booleanValue());
}
/** Copies an AbstractSymbol value.
*
* This method is used internally by the generated AST classes
* */
protected AbstractSymbol copy_AbstractSymbol(AbstractSymbol sym) {
return sym;
}
/** Dumps a printable representation of a boolean value.
*
* This method is used internally by the generated AST classes
* */
protected void dump_Boolean(PrintStream out, int n, Boolean b) {
out.print(Utilities.pad(n));
out.println(b.booleanValue() ? "1" : "0");
}
/** Dumps a printable representation of an AbstactSymbol value.
*
* This method is used internally by the generated AST classes
* */
protected void dump_AbstractSymbol(PrintStream out, int n, AbstractSymbol sym) {
out.print(Utilities.pad(n));
out.println(sym.getString());
}
/** Dumps a printable representation of current line number
*
* This method is used internally by the generated AST classes
* */
protected void dump_line(PrintStream out, int n) {
out.println(Utilities.pad(n) + "#" + lineNumber);
}
}