/*
* xtc - The eXTensible Compiler
* Copyright (C) 2007 Robert Grimm
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package xtc.tree;
/**
* Visitor to relocate an abstract syntax tree. This visitor strips
* all line markers from the abstract syntax tree, while also updating
* all nodes with locations to reflect the source location relative to
* the last line marker.
*
* @author Robert Grimm
* @version $Revision: 1.1 $
*/
public class Relocator extends Visitor {
/** The currently marked file. */
protected String markedFile;
/** The currently marked line. */
protected int markedLine;
/** The line of the last line marker. */
protected int baseLine;
/** Create a new relocator. */
public Relocator() {
markedFile = null;
markedLine = -1;
baseLine = -1;
}
/**
* Relocate the specified node.
*
* @param n The node.
*/
protected void relocate(Node n) {
if ((null == markedFile) || (null == n.location)) return;
final int line = n.location.line - baseLine - 1 + markedLine;
if ((line != n.location.line) || (! n.location.file.equals(markedFile))) {
n.location = new Location(markedFile, line, n.location.column);
}
}
/** Process the specified node. */
public Node visit(Node n) {
relocate(n);
for (int i=0; i<n.size(); i++) {
Object o = n.get(i);
if (o instanceof Node) n.set(i, dispatch((Node)o));
}
return n;
}
/** Process the specified annotation. */
public Annotation visit(Annotation a) {
relocate(a);
a.node = (Node)dispatch(a.node);
return a;
}
/** Process the specified line marker. */
public Node visit(LineMarker m) {
if (null == m.location) {
throw new IllegalArgumentException("Line marker without location");
}
markedFile = m.file;
markedLine = m.line;
baseLine = m.location.line;
return (Node)dispatch(m.node);
}
}