001: /**
002: *
003: * Copyright 2005 Jeremy Rayner
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: **/package org.codehaus.groovy.antlr;
018:
019: /**
020: * Process to decorate antlr AST with ending line/col info, and if
021: * possible the snipppet of source from the start/end line/col for each node.
022: *
023: * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
024: * @version $Revision: 3701 $
025: */
026:
027: import antlr.collections.AST;
028: import java.util.*;
029:
030: public class AntlrASTProcessSnippets implements AntlrASTProcessor {
031: private SourceBuffer sourceBuffer;
032:
033: public AntlrASTProcessSnippets(SourceBuffer sourceBuffer) {
034: this .sourceBuffer = sourceBuffer;
035: }
036:
037: /**
038: * decorate antlr AST with ending line/col info, and if
039: * possible the snipppet of source from the start/end line/col for each node.
040: * @param t the AST to decorate
041: * @return the decorated AST
042: */
043: public AST process(AST t) {
044: // first visit
045: List l = new ArrayList();
046: t = traverse((GroovySourceAST) t, l, null);
047:
048: //System.out.println("l:" + l);
049: // second visit
050: Iterator itr = l.iterator();
051: if (itr.hasNext()) {
052: itr.next(); /* discard first */
053: }
054: t = traverse((GroovySourceAST) t, null, itr);
055: return t;
056: }
057:
058: /**
059: * traverse an AST node
060: * @param t the AST node to traverse
061: * @param l A list to add line/col info to
062: * @param itr An iterator over a list of line/col
063: * @return A decorated AST node
064: */
065: private AST traverse(GroovySourceAST t, List l, Iterator itr) {
066: if (t == null) {
067: return t;
068: }
069:
070: // first visit of node
071: if (l != null) {
072: l.add(new LineColumn(t.getLine(), t.getColumn()));
073: }
074:
075: // second vist of node
076: if (itr != null && itr.hasNext()) {
077: LineColumn lc = (LineColumn) itr.next();
078: if (t.getLineLast() == 0) {
079: int nextLine = lc.getLine();
080: int nextColumn = lc.getColumn();
081: if (nextLine < t.getLine()
082: || (nextLine == t.getLine() && nextColumn < t
083: .getColumn())) {
084: nextLine = t.getLine();
085: nextColumn = t.getColumn();
086: }
087: t.setLineLast(nextLine);
088: t.setColumnLast(nextColumn);
089: // This is a good point to call t.setSnippet(),
090: // but it bulks up the AST too much for production code.
091: }
092: }
093:
094: GroovySourceAST child = (GroovySourceAST) t.getFirstChild();
095: if (child != null) {
096: traverse(child, l, itr);
097: }
098:
099: GroovySourceAST sibling = (GroovySourceAST) t.getNextSibling();
100: if (sibling != null) {
101: traverse(sibling, l, itr);
102: }
103:
104: return t;
105: }
106: }
|