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 **/
018
019 package org.codehaus.groovy.antlr;
020
021 /**
022 * Process to decorate antlr AST with ending line/col info, and if
023 * possible the snipppet of source from the start/end line/col for each node.
024 *
025 * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
026 * @version $Revision: 1.1 $
027 */
028
029 import antlr.collections.AST;
030 import java.util.*;
031
032 public class AntlrASTProcessSnippets implements AntlrASTProcessor{
033 private SourceBuffer sourceBuffer;
034
035 public AntlrASTProcessSnippets(SourceBuffer sourceBuffer) {
036 this.sourceBuffer = sourceBuffer;
037 }
038
039 /**
040 * decorate antlr AST with ending line/col info, and if
041 * possible the snipppet of source from the start/end line/col for each node.
042 * @param t the AST to decorate
043 * @return the decorated AST
044 */
045 public AST process(AST t) {
046 // first visit
047 List l = new ArrayList();
048 t = traverse((GroovySourceAST)t,l,null);
049
050 //System.out.println("l:" + l);
051 // second visit
052 Iterator itr = l.iterator();
053 if (itr.hasNext()) { itr.next(); /* discard first */ }
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) { return t; }
067
068 // first visit of node
069 if (l != null) {
070 l.add(new LineColumn(t.getLine(),t.getColumn()));
071 }
072
073 // second vist of node
074 if (itr != null && itr.hasNext()) {
075 LineColumn lc = (LineColumn)itr.next();
076 if (t.getLineLast() == 0) {
077 int nextLine = lc.getLine();
078 int nextColumn = lc.getColumn();
079 if (nextLine < t.getLine() || (nextLine == t.getLine() && nextColumn < t.getColumn())) {
080 nextLine = t.getLine();
081 nextColumn = t.getColumn();
082 }
083 t.setLineLast(nextLine);
084 t.setColumnLast(nextColumn);
085 t.setSnippet(sourceBuffer.getSnippet(new LineColumn(t.getLine(),t.getColumn()),
086 new LineColumn(t.getLineLast(),t.getColumnLast())));
087 }
088 }
089
090 GroovySourceAST child = (GroovySourceAST)t.getFirstChild();
091 if (child != null) {
092 traverse(child,l,itr);
093 }
094
095 GroovySourceAST sibling = (GroovySourceAST)t.getNextSibling();
096 if (sibling != null) {
097 traverse(sibling,l,itr);
098 }
099
100 return t;
101 }
102 }