Package com.redhat.ceylon.compiler.typechecker.tree

Source Code of com.redhat.ceylon.compiler.typechecker.tree.Node

package com.redhat.ceylon.compiler.typechecker.tree;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.antlr.runtime.CommonToken;
import org.antlr.runtime.Token;

import com.redhat.ceylon.compiler.typechecker.analyzer.AnalysisError;
import com.redhat.ceylon.compiler.typechecker.analyzer.UnsupportedError;
import com.redhat.ceylon.compiler.typechecker.analyzer.UsageWarning;
import com.redhat.ceylon.compiler.typechecker.model.Scope;
import com.redhat.ceylon.compiler.typechecker.model.Unit;
import com.redhat.ceylon.compiler.typechecker.parser.LexError;
import com.redhat.ceylon.compiler.typechecker.parser.ParseError;
import com.redhat.ceylon.compiler.typechecker.util.PrintVisitor;

public abstract class Node {
   
    private String text;
    private Token token;
    private Token endToken;
    private Token firstChildToken;
    private Token lastChildToken;
    private Scope scope;
    private Unit unit;
    private List<Message> errors = null;
   
    protected Node(Token token) {
        this.token = token;
    }
   
    /**
     * The scope within which the node occurs.
     */
    public Scope getScope() {
        return scope;
    }

    public void setScope(Scope scope) {
        this.scope = scope;
    }
   
    /**
     * The compilation unit in which the node
     * occurs.
     */
    public Unit getUnit() {
        return unit;
    }
   
    public void setUnit(Unit unit) {
        this.unit = unit;
    }
   
    /**
     * The text of the corresponding ANTLR node.
     */
    public String getText() {
      if (text!=null) {
        return text;
      }
      else if (token==null) {
        return "";
      }
      else if (endToken==null) {
        return token.getText();
      }
      else {
        return token.getText() + endToken.getText();
      }
    }
   
    public void setText(String text) {
        this.text = text;
    }
   
    /**
     * The text of the corresponding ANTLR tree node. Never null,
     * since the two trees are isomorphic.
     */
    public Token getToken() {
      return getFirstChildToken();
    }
   
    public Token getMainToken() {
        return token;
    }
   
    public Token getMainEndToken() {
        return endToken;
    }
   
    public String getLocation() {
      Token token = getToken();
      Token endToken = getEndToken();
    if (token==null) {
        return "unknown location";
      }
      else if (endToken==null) {
        return toLocation(token);
      }
      else {
        return toLocation(token) + "-" +
            toEndLocation(endToken);
      }
    }
   
    public Integer getStartIndex() {
      Token token = getToken();
      if (token==null) {
        return null;
      }
      else {
        return ((CommonToken) token).getStartIndex();
      }
    }

    public Integer getStopIndex() {
      Token token = getEndToken();
      if (token==null) {
        token = getToken();
      }
      if (token==null) {
        return null;
      }
      else {
        return ((CommonToken) token).getStopIndex();
      }
    }

  private static String toLocation(Token token) {
    return token.getLine() + ":" +
        token.getCharPositionInLine();
  }
   
  private static String toEndLocation(Token token) {
    return token.getLine() + ":" +
        (token.getCharPositionInLine()
        + token.getText().length()-1);
  }
   
    private static boolean isMissingToken(Token t) {
        return t instanceof MissingToken;
    }

    public boolean isMissingToken() {
        return isMissingToken(token);
    }

    private Token getFirstChildToken() {
        Token token = this.token==null ||
                //the tokens ANTLR inserts to represent missing tokens
                //don't come with useful offset information
                isMissingToken(this.token) ?
                null : this.token;
        if (firstChildToken!=null &&
                (token==null ||
                firstChildToken.getTokenIndex()<token.getTokenIndex())) {
            token = firstChildToken;
        }
    return token;
    }

    private Token getLastChildToken() {
    Token token=this.endToken==null ||
            //the tokens ANTLR inserts to represent missing tokens
            //don't come with useful offset information
            isMissingToken(endToken) ?
        this.token : this.endToken;
        if (lastChildToken!=null &&
                (token==null ||
                lastChildToken.getTokenIndex()>token.getTokenIndex())) {
            token = lastChildToken;
        }
    return token;
    }
   
    public Token getEndToken() {
      return getLastChildToken();
  }
   
    public void setEndToken(Token endToken) {
        //the tokens ANTLR inserts to represent missing tokens
        //don't come with useful offset information
        if (endToken==null || !isMissingToken(endToken)) {
            this.endToken = endToken;
        }
  }
   
    /**
     * The compilation errors belonging to this node.
     */
    public List<Message> getErrors() {
        return errors != null ? errors : Collections.<Message>emptyList();
    }
   
    public void addError(Message error){
        if(errors == null)
            errors = new ArrayList<Message>(2);
        errors.add(error);
    }
   
    public void addError(String message) {
        addError( new AnalysisError(this, message) );
    }
   
    public void addError(String message, int code) {
        addError( new AnalysisError(this, message, code) );
    }
   
    public void addUnexpectedError(String message) {
        addError( new UnexpectedError(this, message) );
    }
   
    public void addUnsupportedError(String message) {
        addError( new UnsupportedError(this, message) );
    }
   
    public <E extends Enum<E>> void addUsageWarning(E warningName, String message) {
        addError( new UsageWarning(this, message, warningName.toString()) );
    }
   
    public void addParseError(ParseError error) {
        addError(error);
    }
   
    public void addLexError(LexError error) {
        addError(error);
    }
   
    public abstract void visit(Visitor visitor);
   
    public abstract void visitChildren(Visitor visitor);
   
    @Override
    public String toString() {
        StringWriter w = new StringWriter();
        PrintVisitor pv = new PrintVisitor(w);
        pv.visitAny(this);
        return w.toString();
        //return getClass().getSimpleName() + "(" + text + ")";
    }

    public String getNodeType() {
        return getClass().getSimpleName();
    }
   
    public void handleException(Exception e, Visitor visitor) {
      addError(getMessage(e, visitor));
    }

    public String getMessage(Exception e, Visitor visitor) {
    return visitor.getClass().getSimpleName() +
              " caused an exception visiting " + getNodeType() +
              " node: " + e + " at " + getLocationInfo(e);
  }

  private String getLocationInfo(Exception e) {
    return e.getStackTrace().length>0 ?
        e.getStackTrace()[0].toString() : "unknown";
  }
 
  public void connect(Node child) {
    if (child!=null) {
      Token childFirstChildToken = child.getFirstChildToken();
            if (childFirstChildToken!=null &&
                    (firstChildToken==null ||
              childFirstChildToken.getTokenIndex()<firstChildToken.getTokenIndex())) {
          firstChildToken = childFirstChildToken;
      }
            Token childLastChildToken = child.getLastChildToken();
            if (childLastChildToken!=null &&
                    (lastChildToken==null ||
                    childLastChildToken.getTokenIndex()>lastChildToken.getTokenIndex())) {
                lastChildToken = childLastChildToken;
            }
    }
  }

}
TOP

Related Classes of com.redhat.ceylon.compiler.typechecker.tree.Node

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.