blob: f49a4f0c44b688015b905a85b8250272096a6acf [file] [log] [blame]
% Refactoring Support: Source Printing and Program Editing
Aside from the usual front end components (parser and symbol tables), a
refactoring tool requires
\begin{itemize}
\item a means of manipulating the parse tree, i.e., moving nodes around,
deleting them, and inserting new ones; and
\item a means of outputting ``revised'' source code after a parse tree has
been manipulated.
\end{itemize}
We will look at the means of outputting source code first, discussing
the \texttt{Presentation} and \texttt{SourcePrinter} classes.
We will then discuss the \texttt{ProgramEditor}, which allows you to
manipulate the parse tree and \texttt{Presentation}.
\section{The \texttt{Presentation} and the \texttt{Program}}
While the parse tree for a program stores all of the ``important'' tokens
(identifiers, parentheses, etc.), other things---comments, line continuations,
and C preprocessor directives---are not in the Fortran grammar. However,
when the source printer produces source code from a parse tree, it needs to
include these as well.
We refer to these things (comments, line continuations, C preprocessor
directives, Fortran INCLUDE statements, and anything else that does not
end up in a parse tree) as \textit{non-tree tokens}, and we represent them
by the class \texttt{NonTreeToken}. A \texttt{Presentation} is essentially
a list of all the non-tree tokens that appeared in a parse.
A \texttt{Presentation} can be created from a parse by calling the
\texttt{getNonTreeTokens} method on the lexer and passing the resulting
\texttt{List<NonTreeToken>} to the \texttt{Presentation} constructor.
A \texttt{Program} is just parse tree paired with a symbol table and a
\texttt{Presentation}.
\section{Presentation Blocks}
Since \texttt{Token}s in the parse tree and \texttt{NonTreeToken}s in
a program's \texttt{Presentation} have a lot in common, we will refer to
them collectively as ``presentation blocks.'' Not surprisingly, they
share a common superclass (interface, rather): \texttt{IPresentationBlock}.
JavaDoc removed, it looks like this:
\begin{verbatim}
public interface IPresentationBlock
{
public abstract String getFilename();
public abstract void setFilename(String value);
public abstract int getStartLine();
public abstract void setStartLine(int value);
public abstract int getStartCol();
public abstract void setStartCol(int value);
public abstract int getEndLine();
public abstract void setEndLine(int value);
public abstract int getEndCol();
public abstract void setEndCol(int value);
public abstract int getOffset();
public abstract void setOffset(int value);
public abstract int getLength();
public abstract void setLength(int value);
public abstract String getText();
public abstract void setText(String value);
}
\end{verbatim}
Intuitively, then, all presentation blocks know what file they originated from,
where they were in the file (both in terms of line/column and offset/length),
and exactly what their text looked like. (This is important since capitalization
does not matter in Fortran.)
Most importantly, this means that reproduce the source code of a program verbatim
from a parse tree and a \texttt{Presentation}. (The only difference will be the
use of spaces vs. tabs to make sure tokens appear in the correct column on a line.)
All comments and formatting will be retained.
\section{The \texttt{SourcePrinter}}
The job of the source printer (class \texttt{SourcePrinter}) is to take a
a parse tree and corresponding \texttt{Presentation}
and produce source code from it.
Since every \texttt{Token} in the parse tree and every \texttt{NonTreeToken}
in the \texttt{Presentation} knows what line and column it should appear on,
this is easy.
\section{The \texttt{ProgramEditor}}
Essentially, a refactoring needs to change the parse tree for a program. It
may change existing nodes, move them around, remove them altogether, or insert
new nodes.
As described above, though, source code is produced by looking at the line/column
offsets of the \texttt{Token}s in the parse tree and interleaving comments and
other non-tree tokens from a program's \texttt{Presentation}.
When we add, move, change, or delete a subtree of the parse tree, then,
we must do three things:
\begin{itemize}
\item adjust the positions of the \texttt{Token}s in that subtree,
\item adjust the positions of the related \texttt{NonTreeToken}s
(e.g., the comments describing a method and C preprocessor directives in its
definition)
\item adjust the positions of all of the presentation blocks that appear after
the modified subtree. For example, if you change an token's text from
``Hello'' to ``Goodbye,'' every presentation block after that one will have
its offset incremented by 2, and every presentation block to the right of
that token on the same line will also have its starting column number incremented
by 2.
\end{itemize}
The (static) methods in \texttt{ProgramEditor} are used to add, move, modify,
and delete subtrees.
This class will be described more as it stabilizes.