/*
 * Copyright 2000-2015 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.lexer;

import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * Interface for breaking a file into a sequence of tokens.
 *
 * @see LexerBase for certain methods' implementation
 */
public abstract class Lexer {

  /**
   * Prepare for lexing character data from {@code buffer} passed. Internal lexer state is supposed to be {@code initialState}. It is guaranteed
   * that the value of initialState is the same as returned by {@link #getState()} method of this lexer at condition {@code startOffset=getTokenStart()}.
   * This method is used to incrementally re-lex changed characters using lexing data acquired from this particular lexer sometime in the past.
   *
   * @param buffer       character data for lexing.
   * @param startOffset  offset to start lexing from
   * @param endOffset    offset to stop lexing at
   * @param initialState the initial state of the lexer.
   * @since IDEA 7
   */
  public abstract void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int initialState);

  public final void start(@NotNull CharSequence buf, int start, int end) {
    start(buf, start, end, 0);
  }

  public final void start(@NotNull CharSequence buf) {
    start(buf, 0, buf.length(), 0);
  }

  @NotNull
  public CharSequence getTokenSequence() {
    return getBufferSequence().subSequence(getTokenStart(), getTokenEnd());
  }

  @NotNull
  public String getTokenText() {
    return getTokenSequence().toString();
  }

  /**
   * Returns the current state of the lexer.
   *
   * @return the lexer state.
   */
  public abstract int getState();

  /**
   * Returns the token at the current position of the lexer or {@code null} if lexing is finished.
   *
   * @return the current token.
   */
  @Nullable
  public abstract IElementType getTokenType();

  /**
   * Returns the start offset of the current token.
   *
   * @return the current token start offset.
   */
  public abstract int getTokenStart();

  /**
   * Returns the end offset of the current token.
   *
   * @return the current token end offset.
   */

  public abstract int getTokenEnd();

  /**
   * Advances the lexer to the next token.
   */
  public abstract void advance();

  /**
   * Returns the current position and state of the lexer.
   *
   * @return the lexer position and state.
   */
  @NotNull
  public abstract LexerPosition getCurrentPosition();

  /**
   * Restores the lexer to the specified state and position.
   *
   * @param position the state and position to restore to.
   */
  public abstract void restore(@NotNull LexerPosition position);

  /**
   * Returns the buffer sequence over which the lexer is running. This method should return the
   * same buffer instance which was passed to the {@code start()} method.
   *
   * @return the lexer buffer.
   * @since IDEA 7
   */
  @NotNull
  public abstract CharSequence getBufferSequence();

  /**
   * Returns the offset at which the lexer will stop lexing. This method should return
   * the length of the buffer or the value passed in the {@code endOffset} parameter
   * to the {@code start()} method.
   *
   * @return the lexing end offset
   */
  public abstract int getBufferEnd();
}
