Package com.googlecode.goclipse.go.lang.parser

Source Code of com.googlecode.goclipse.go.lang.parser.FunctionParser

package com.googlecode.goclipse.go.lang.parser;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import com.googlecode.goclipse.Activator;
import com.googlecode.goclipse.go.lang.lexer.Lexer;
import com.googlecode.goclipse.go.lang.lexer.TokenListener;
import com.googlecode.goclipse.go.lang.lexer.TokenType;
import com.googlecode.goclipse.go.lang.lexer.Tokenizer;
import com.googlecode.goclipse.go.lang.model.Function;
import com.googlecode.goclipse.go.lang.model.Method;

/**
*
* @author steel
*
*/
public class FunctionParser implements TokenListener {

  private enum State {
    START, DETERMINE_TYPE, CONSUME_FUNCTION_HEADER, CONSUME_METHOD_HEADER, FINISHED, ERROR
  }

  private File                              file             = null;
  private State                 state        = State.START;
  private ScopeParser             scopeParser      = null;
  private ArrayList<FunctionParserListener> funcListeners    = new ArrayList<FunctionParserListener>();
  private ArrayList<Function>               funcs        = new ArrayList<Function>();
  private ArrayList<Method>                 methods        = new ArrayList<Method>();
  private Function                         func          = new Function();
  private Method                           method        = new Method();
  private StringBuffer                      comment        = new StringBuffer();
  private StringBuffer                      text          = new StringBuffer();
  private int                           lastCommentLine  = 0;
  private int                           tokenOnLineCount = 0;
  private int                           afterReceiver    = 0;
  private boolean                         exportsOnly      = true;
  private int                           scope_tracker    = 0;

  /**
   *
   * @param tokenizer
   */
  public FunctionParser(boolean parseExportsOnly, Tokenizer tokenizer, File file) {
    tokenizer.addTokenListener(this);
    exportsOnly = parseExportsOnly;
    this.file = file;
    func.setFile(file);
    method.setFile(file);
  }
 
  /**
   * @param scopeParser
   */
  public void setScopeParser(ScopeParser scopeParser){
    this.scopeParser = scopeParser;
  }
 
  /**
   * @param listener
   */
  public void addFuncListeners(FunctionParserListener listener ){
    if(!funcListeners.contains(listener)){
      funcListeners.add(listener);
    }
  }
 
  /**
   *
   */
  public void onFunctionEnter(){
    for(FunctionParserListener listener: funcListeners){
      listener.onEnterFunction(func);
    }
  }
 
  /**
   *
   */
  public void onFunctionExit(){
    for(FunctionParserListener listener: funcListeners){
      listener.onExitFunction(func);
    }
  }

  @Override
  public void tokenFound(TokenType type, String value, boolean inComment,
      int linenumber, int start, int end) {
    try {
      if (inComment) {
        if (!TokenType.COMMENT.equals(type)
            && !TokenType.BLOCK_COMMENT_START.equals(type)
            && !TokenType.BLOCK_COMMENT_END.equals(type)) {
         
          if (linenumber - lastCommentLine > 1) {
            comment = new StringBuffer();
          }

          if (linenumber > lastCommentLine
              && TokenType.DIVIDE.equals(type)) {
            lastCommentLine = linenumber;
          } else {
            comment.append(value);
            lastCommentLine = linenumber;
          }
        }
        return;
      }

      // Parsing top level functions only
      if (TokenType.LBRACE.equals(type)) {
        scope_tracker++;
      }

      if (TokenType.RBRACE.equals(type)) {
        scope_tracker--;
      }

      // guard against identifiers named 'func'
      if (!(type.isWhiteSpace())) {
        tokenOnLineCount++;
      }

      if (TokenType.NEWLINE.equals(type)) {
        tokenOnLineCount = 0;
      }

      switch (state) {

      case START:
        if (TokenType.FUNC.equals(type) && scope_tracker == 0
            && tokenOnLineCount == 1) {

          if (linenumber - lastCommentLine > 1) {
            comment = new StringBuffer();
          }

          state = State.DETERMINE_TYPE;
        }
        break;

       
      case CONSUME_METHOD_HEADER:
       
        if (TokenType.IDENTIFIER.equals(type)) {
         
          text.append(value);
         
          if (afterReceiver == 1) {
            method.setInsertionText(value + "()");
            afterReceiver++;
          }
         
        } else if (TokenType.RPAREN.equals(type)) {
         
          text.append(value);
          afterReceiver++;
         
          // break apart and determine type
          String t = text.toString().replace("(", "").replace(")", "");
          String[] r = t.split(" ");
         
          if (method.getType() == null) {
            if (r.length > 0) {
              t = r[r.length-1].replace("*", "");
            }
           
            method.setType(t);
          }
         
        } else if (TokenType.NEWLINE.equals(type)) {
         
          if (text.toString().lastIndexOf('{') != -1) {
         
            method.setName(text.toString().substring(0,
                text.toString().lastIndexOf('{')));
           
          } else {
           
            method.setName(text.toString());
           
          }
         
          method.setLine(linenumber);
          method.setDocumentation(comment.toString());
          text = new StringBuffer();

          // sometimes we only wanted exported methods
          if (method != null && method.getInsertionText() != null) {
           
            if ((exportsOnly && Character.isUpperCase(method.getInsertionText().charAt(0))) || !exportsOnly) {
              methods.add(method);
            }
          }
         
          // add it to current scope
          if (scopeParser!=null){
            scopeParser.addMethod(method);
          }

          method  = new Method();
          method.setFile(file);
         
          comment       = new StringBuffer();
          state         = State.START;
          afterReceiver = 0;
         
        }
        else {
          text.append(value);
        }
        break;
       
       
      case CONSUME_FUNCTION_HEADER:
       
        if (TokenType.IDENTIFIER.equals(type)) {
          text.append(value);

          if (func.getInsertionText() == null) {
            func.setInsertionText(value + "()");
          }
        }
        else if (TokenType.NEWLINE.equals(type)) {

          if (text.toString().lastIndexOf('{') != -1) {
            func.setName(text.toString().substring(0,
                text.toString().lastIndexOf('{')));
          }
          else {
            func.setName(text.toString());
          }
         
          func.setDocumentation(comment.toString());
          text = new StringBuffer();

          // sometimes we only wanted exported functions
          if (func != null && func.getInsertionText() != null) {
            if ((exportsOnly && Character.isUpperCase(func
                .getInsertionText().charAt(0))) || !exportsOnly) {
              funcs.add(func);
            }
          }

          // add it to current scope
          if (scopeParser!=null){
            scopeParser.addFunction(func);
          }
         
          func = new Function();
          func.setFile(file);
          comment = new StringBuffer();
          state = State.START;
        }
        else {
          text.append(value);
        }
        break;
       
       
      case DETERMINE_TYPE:
        if (TokenType.LPAREN.equals(type)) {
          state = State.CONSUME_METHOD_HEADER;
          text.append(value);
        }
        else if (TokenType.IDENTIFIER.equals(type)) {
          state = State.CONSUME_FUNCTION_HEADER;

          text.append(value);
          func.setLine(linenumber);

          if (func.getInsertionText() == null) {
            func.setInsertionText(value + "()");
          }
        }
        break;
       
       
      case FINISHED:
        break;
       
      }
    } catch (RuntimeException e) {
      Activator.logError(e);
    }
  }

  public static void main(String[] args) {

    Lexer lexer = new Lexer();
    Tokenizer tokenizer = new Tokenizer(lexer);
    FunctionParser fparser = new FunctionParser(false, tokenizer, null);

    try {
      lexer.scan(new File("test_go/import_test.go"));
      for (Function func : fparser.funcs) {
        Activator.logInfo("=================================================");
        Activator.logInfo(func.getDocumentation());
        Activator.logInfo("-------------------------------------------------");
        Activator.logInfo(func.getName());
        Activator.logInfo(func.getInsertionText());
        Activator.logInfo("-------------------------------------------------");
      }

      Activator.logInfo("\n");
      Activator.logInfo("=================================================");
      Activator.logInfo("[METHODS]");

      for (Method method : fparser.methods) {
        Activator.logInfo("=================================================");
        Activator.logInfo(method.getDocumentation());
        Activator.logInfo("-------------------------------------------------");
        Activator.logInfo(method.getName());
        Activator.logInfo(method.getInsertionText());
        Activator.logInfo("-------------------------------------------------");
      }

    } catch (IOException e) {
      Activator.logError(e);
    }
  }

  @Override
  public boolean isWhitespaceParser() {
    return true;
  }

  /**
   * @return
   */
  public ArrayList<Method> getMethods() {
    return methods;
  }

  /**
   * @return
   */
  public ArrayList<Function> getFunctions() {
    return funcs;
  }
}
TOP

Related Classes of com.googlecode.goclipse.go.lang.parser.FunctionParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.