View Javadoc

1   /***
2    *
3    * Copyright 2005 Jeremy Rayner
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   **/
18  
19  package org.codehaus.groovy.antlr;
20  
21  /***
22   * Process to decorate antlr AST with ending line/col info, and if
23   * possible the snipppet of source from the start/end line/col for each node.
24   *
25   * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
26   * @version $Revision: 1.1 $
27   */
28  
29  import antlr.collections.AST;
30  import java.util.*;
31  
32  public class AntlrASTProcessSnippets implements AntlrASTProcessor{
33      private SourceBuffer sourceBuffer;
34  
35      public AntlrASTProcessSnippets(SourceBuffer sourceBuffer) {
36          this.sourceBuffer = sourceBuffer;
37      }
38  
39      /***
40       * decorate antlr AST with ending line/col info, and if
41       * possible the snipppet of source from the start/end line/col for each node.
42       * @param t the AST to decorate
43       * @return the decorated AST
44       */
45      public AST process(AST t) {
46          // first visit
47          List l = new ArrayList();
48          t = traverse((GroovySourceAST)t,l,null);
49  
50          //System.out.println("l:" + l);
51          // second visit
52          Iterator itr = l.iterator();
53          if (itr.hasNext()) { itr.next(); /* discard first */ }
54          t = traverse((GroovySourceAST)t,null,itr);
55          return t;
56      }
57  
58      /***
59       * traverse an AST node
60       * @param t the AST node to traverse
61       * @param l A list to add line/col info to
62       * @param itr An iterator over a list of line/col
63       * @return A decorated AST node
64       */
65      private AST traverse(GroovySourceAST t,List l,Iterator itr) {
66          if (t == null) { return t; }
67  
68          // first visit of node
69          if (l != null) {
70              l.add(new LineColumn(t.getLine(),t.getColumn()));
71          }
72  
73          // second vist of node
74          if (itr != null && itr.hasNext()) {
75              LineColumn lc = (LineColumn)itr.next();
76              if (t.getLineLast() == 0) {
77                  int nextLine = lc.getLine();
78                  int nextColumn = lc.getColumn();
79                  if (nextLine < t.getLine() || (nextLine == t.getLine() && nextColumn < t.getColumn())) {
80                      nextLine = t.getLine();
81                      nextColumn = t.getColumn();
82                  }
83                  t.setLineLast(nextLine);
84                  t.setColumnLast(nextColumn);
85                  t.setSnippet(sourceBuffer.getSnippet(new LineColumn(t.getLine(),t.getColumn()),
86                                  new LineColumn(t.getLineLast(),t.getColumnLast())));
87              }
88          }
89  
90          GroovySourceAST child = (GroovySourceAST)t.getFirstChild();
91          if (child != null) {
92              traverse(child,l,itr);
93          }
94  
95          GroovySourceAST sibling = (GroovySourceAST)t.getNextSibling();
96          if (sibling != null) {
97              traverse(sibling,l,itr);
98          }
99  
100         return t;
101     }
102 }