001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2007 Robert Grimm
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public License
007: * version 2.1 as published by the Free Software Foundation.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.tree;
020:
021: /**
022: * Visitor to relocate an abstract syntax tree. This visitor strips
023: * all line markers from the abstract syntax tree, while also updating
024: * all nodes with locations to reflect the source location relative to
025: * the last line marker.
026: *
027: * @author Robert Grimm
028: * @version $Revision: 1.1 $
029: */
030: public class Relocator extends Visitor {
031:
032: /** The currently marked file. */
033: protected String markedFile;
034:
035: /** The currently marked line. */
036: protected int markedLine;
037:
038: /** The line of the last line marker. */
039: protected int baseLine;
040:
041: /** Create a new relocator. */
042: public Relocator() {
043: markedFile = null;
044: markedLine = -1;
045: baseLine = -1;
046: }
047:
048: /**
049: * Relocate the specified node.
050: *
051: * @param n The node.
052: */
053: protected void relocate(Node n) {
054: if ((null == markedFile) || (null == n.location))
055: return;
056:
057: final int line = n.location.line - baseLine - 1 + markedLine;
058: if ((line != n.location.line)
059: || (!n.location.file.equals(markedFile))) {
060: n.location = new Location(markedFile, line,
061: n.location.column);
062: }
063: }
064:
065: /** Process the specified node. */
066: public Node visit(Node n) {
067: relocate(n);
068:
069: for (int i = 0; i < n.size(); i++) {
070: Object o = n.get(i);
071: if (o instanceof Node)
072: n.set(i, dispatch((Node) o));
073: }
074:
075: return n;
076: }
077:
078: /** Process the specified annotation. */
079: public Annotation visit(Annotation a) {
080: relocate(a);
081:
082: a.node = (Node) dispatch(a.node);
083:
084: return a;
085: }
086:
087: /** Process the specified line marker. */
088: public Node visit(LineMarker m) {
089: if (null == m.location) {
090: throw new IllegalArgumentException(
091: "Line marker without location");
092: }
093:
094: markedFile = m.file;
095: markedLine = m.line;
096: baseLine = m.location.line;
097:
098: return (Node) dispatch(m.node);
099: }
100:
101: }
|