Package org.eclipse.php.internal.core.compiler.ast.parser

Source Code of org.eclipse.php.internal.core.compiler.ast.parser.AbstractASTParser

/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.core.compiler.ast.parser;

import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

import java_cup.runtime.Scanner;
import java_cup.runtime.Symbol;
import java_cup.runtime.lr_parser;

import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.ast.statements.Block;
import org.eclipse.dltk.ast.statements.Statement;
import org.eclipse.dltk.compiler.problem.DefaultProblem;
import org.eclipse.dltk.compiler.problem.IProblem;
import org.eclipse.dltk.compiler.problem.IProblemReporter;
import org.eclipse.dltk.compiler.problem.ProblemSeverities;
import org.eclipse.php.internal.core.ast.scanner.AstLexer;
import org.eclipse.php.internal.core.compiler.ast.nodes.*;

abstract public class AbstractASTParser extends lr_parser {

  private PHPModuleDeclaration program = new PHPModuleDeclaration(0, 0,
      new LinkedList<Statement>(), new LinkedList<ASTError>(),
      new LinkedList<VarComment>());
  private IProblemReporter problemReporter;
  private String fileName;

  /**
   * This is a place holder for statements that were found after unclosed
   * classes
   */
  public Statement pendingStatement = null;

  /** This is a latest non-bracketed namespace declaration */
  public NamespaceDeclaration currentNamespace = null;

  /** Whether we've met the unbracketed namespace declaration in this file */
  public boolean metUnbracketedNSDecl;

  /** Whether we've met the bracketed namespace declaration in this file */
  public boolean metBracketedNSDecl;

  /** Top declarations stack */
  public Stack<Statement> declarations = new Stack<Statement>();

  public AbstractASTParser() {
    super();
  }

  public AbstractASTParser(Scanner s) {
    super(s);
  }

  public void setProblemReporter(IProblemReporter problemReporter) {
    this.problemReporter = problemReporter;
  }

  public IProblemReporter getProblemReporter() {
    return problemReporter;
  }

  public void setFileName(String fileName) {
    this.fileName = fileName;
  }

  public String getFileName() {
    return fileName;
  }

  protected List<ASTError> getErrors() {
    return program.getErrors();
  }

  protected void reportError(IProblemReporter problemReporter,
      String fileName, int start, int end, int lineNumber, String message) {
    DefaultProblem problem = new DefaultProblem(fileName, message,
        IProblem.Syntax, new String[0], ProblemSeverities.Error, start,
        end, lineNumber);
    problemReporter.reportProblem(problem);
  }

  /**
   * Report on errors that will be added to the AST as statements
   */
  public void reportError() {
    program.setHasErrors(true);
  }

  public void reportError(ASTError error) {
    reportError(error, null);
  }

  /**
   * Reporting an error that cannot be added as a statement and has to be in a
   * separated list.
   *
   * @param error
   */
  public void reportError(ASTError error, String message) {
    getErrors().add(error);
    reportError();

    if (message != null && problemReporter != null && fileName != null) {
      int lineNumber = ((AstLexer) getScanner()).getCurrentLine();
      reportError(problemReporter, fileName, error.sourceStart(),
          error.sourceEnd(), lineNumber, message);
    }
  }

  public void addStatement(Statement s) {
    int kind = s.getKind();
    if (kind != ASTNodeKinds.EMPTY_STATEMENT
        && kind != ASTNodeKinds.DECLARE_STATEMENT
        && kind != ASTNodeKinds.NAMESPACE_DECLARATION
        && metBracketedNSDecl) {
      reportError(new ASTError(s.sourceStart(), s.sourceEnd()),
          Messages.AbstractASTParser_0);
    }

    if (currentNamespace != null && currentNamespace != s) {
      currentNamespace.addStatement(s);
    } else {
      program.addStatement(s);
    }
  }

  public PHPModuleDeclaration getModuleDeclaration() {
    return program;
  }

  public void report_error(String message, Object info) {
    if (info instanceof Symbol) {
      if (((Symbol) info).left != -1) {
        ASTError error = new ASTError(((Symbol) info).left,
            ((Symbol) info).right);
        reportError(error);
      } else {
        reportError(new ASTError(0, 1));
      }
    }
  }

  @SuppressWarnings("unchecked")
  public void unrecovered_syntax_error(Symbol cur_token)
      throws java.lang.Exception {
    // in case
    int start = 0;
    int end = 0;
    Object value = cur_token.value;
    PHPModuleDeclaration program = getModuleDeclaration();
    List<Statement> statements = program.getStatements();
    if (value instanceof List) {
      statements.addAll((List) value);
    }

    if (!declarations.isEmpty()) {
      statements.add(declarations.remove(0));
    }
    if (!statements.isEmpty()) {
      Statement s1 = (Statement) statements.get(0);
      Statement s2 = (Statement) statements.get(statements.size() - 1);
      start = s1.sourceStart();
      end = s2.sourceEnd();
    }
    List<ASTError> errors = getErrors();
    if (!errors.isEmpty()) {
      ASTError lastError = errors.get(errors.size() - 1);
      end = (end > lastError.sourceEnd()) ? end : lastError.sourceEnd();
    }
    program.setStart(start);
    program.setEnd(end);

    // Set end offset of recovered class/interface node to the end of file
    if (statements.size() > 0) {
      Statement lastStatement = statements.get(statements.size() - 1);
      if (lastStatement instanceof IRecoverable) {
        IRecoverable recoverable = (IRecoverable) lastStatement;
        if (recoverable.isRecovered()) {
          lastStatement.setEnd(end);
        }
      }
    }

    super.unrecovered_syntax_error(cur_token);
  }

  public void syntax_error(Symbol cur_token) {
    super.syntax_error(cur_token);

    if (fileName == null || problemReporter == null) {
      return;
    }

    int state = ((Symbol) stack.peek()).parse_state;

    short[] rowOfProbe = action_tab[state];
    int startPosition = cur_token.left;
    int endPosition = cur_token.right;
    int lineNumber = ((AstLexer) getScanner()).getCurrentLine();

    StringBuilder errorMessage = new StringBuilder(
        Messages.AbstractASTParser_1);

    // current token can be either null, string or phpdoc - according to
    // this resolve:
    String currentText = cur_token.value instanceof String ? (String) cur_token.value
        : null;
    if (currentText == null || currentText.length() == 0) {
      currentText = getTokenName(cur_token.sym);
    }
    if (currentText != null && currentText.length() > 0) {
      if (currentText.equals(";")) { // This means EOF, since it's //$NON-NLS-1$
        // substituted by the lexer
        // explicitly.
        currentText = "EOF"; //$NON-NLS-1$
      }
      endPosition = startPosition + currentText.length();
      errorMessage.append(Messages.AbstractASTParser_4)
          .append(currentText).append('\'');
    }

    if (rowOfProbe.length <= 6) {
      errorMessage.append(Messages.AbstractASTParser_5);
      boolean first = true;
      for (int probe = 0; probe < rowOfProbe.length; probe += 2) {
        String tokenName = getTokenName(rowOfProbe[probe]);
        if (tokenName != null) {
          if (!first) {
            errorMessage.append(Messages.AbstractASTParser_6);
          }
          errorMessage.append('\'').append(tokenName).append('\'');
          first = false;
        }
      }
    }

    reportError(problemReporter, fileName, startPosition, endPosition,
        lineNumber, errorMessage.toString());
  }

  protected abstract String getTokenName(int token);

  public void report_fatal_error(String message, Object info)
      throws java.lang.Exception {
    /* stop parsing (not really necessary since we throw an exception, but) */
    done_parsing();

    /* use the normal error message reporting to put out the message */
    // report_error(message, info);

    // throw new Exception("Can't recover from previous error(s)");
  }

  public void addDeclarationStatement(Statement s) {
    if (declarations.isEmpty()) {
      if (s.getKind() == ASTNodeKinds.NAMESPACE_DECLARATION) {
        if (program.getStatements().size() > 0 && !metBracketedNSDecl
            && !metUnbracketedNSDecl) {
          boolean justDeclarationNodes = true;
          for (Object statement : program.getStatements()) {
            if (((Statement) statement).getKind() != ASTNodeKinds.DECLARE_STATEMENT) {
              justDeclarationNodes = false;
              break;
            }
          }
          if (!justDeclarationNodes) {
            reportError(
                new ASTError(s.sourceStart(), s.sourceEnd()),
                Messages.AbstractASTParser_7);
          }
        }
      }

      // we don't add top level statements to the program node this way
      return;
    }
    Statement node = declarations.peek();
    Block block = null;
    if (node instanceof TypeDeclaration) {
      block = ((TypeDeclaration) node).getBody();
    } else if (node instanceof MethodDeclaration) {
      block = ((MethodDeclaration) node).getBody();
    } else if (node instanceof Block) {
      block = (Block) node;
    }
    if (block == null) {
      return;
    }
    block.addStatement(s);
    block.setEnd(s.sourceEnd());
  }
}
TOP

Related Classes of org.eclipse.php.internal.core.compiler.ast.parser.AbstractASTParser

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.