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