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: 3701 $ 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 // This is a good point to call t.setSnippet(), 086 // but it bulks up the AST too much for production code. 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 }