// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.naming.signature;

import com.android.tools.r8.naming.signature.GenericSignatureAction.ParserPosition;
import java.lang.reflect.GenericSignatureFormatError;
import java.nio.CharBuffer;

/**
 * Implements a parser for the generics signature attribute as defined by JVMS 7 $ 4.3.4.
 * Uses a top-down, recursive descent parsing approach for the following grammar:
 * <pre>
 * ClassSignature ::=
 *     OptFormalTypeParams SuperclassSignature {SuperinterfaceSignature}.
 * SuperclassSignature ::= ClassTypeSignature.
 * SuperinterfaceSignature ::= ClassTypeSignature.
 *
 * OptFormalTypeParams ::=
 *     ["<" FormalTypeParameter {FormalTypeParameter} ">"].
 *
 * FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
 * ClassBound ::= ":" [FieldTypeSignature].
 * InterfaceBound ::= ":" FieldTypeSignature.
 *
 * FieldTypeSignature ::=
 *     ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature.
 * ArrayTypeSignature ::= "[" TypSignature.
 *
 * ClassTypeSignature ::=
 *     "L" {Ident "/"} Ident OptTypeArguments {"." Ident OptTypeArguments} ";".
 *
 * OptTypeArguments ::= "<" TypeArgument {TypeArgument} ">".
 *
 * TypeArgument ::= ([WildcardIndicator] FieldTypeSignature) | "*".
 * WildcardIndicator ::= "+" | "-".
 *
 * TypeVariableSignature ::= "T" Ident ";".
 *
 * TypSignature ::= FieldTypeSignature | BaseType.
 * BaseType ::= "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z".
 *
 * MethodTypeSignature ::=
 *     OptFormalTypeParams "(" {TypeSignature} ")" ReturnType {ThrowsSignature}.
 * ThrowsSignature ::= ("^" ClassTypeSignature) | ("^" TypeVariableSignature).
 *
 * ReturnType ::= TypSignature | VoidDescriptor.
 * VoidDescriptor ::= "V".
 * </pre>
 */
public class GenericSignatureParser<T> {

  private GenericSignatureAction<T> actions;

  /*
   * Parser:
   */
  private char symbol; // 0: eof; else valid term symbol or first char of identifier.

  private String identifier;

  /*
   * Scanner:
   * eof is private to the scan methods
   * and it's set only when a scan is issued at the end of the buffer.
   */
  private boolean eof;

  private char[] buffer;

  private int pos;

  public GenericSignatureParser(GenericSignatureAction<T> actions) {
    this.actions = actions;
  }

  public void parseClassSignature(String signature) {
    try {
      actions.start();
      setInput(signature);
      parseClassSignature();
      actions.stop();
    } catch (GenericSignatureFormatError e) {
      throw e;
    } catch (Throwable t) {
      Error e = new GenericSignatureFormatError(
          "Unknown error parsing class signature: " + t.getMessage());
      e.addSuppressed(t);
      throw e;
    }
  }

  public void parseMethodSignature(String signature) {
    try {
      actions.start();
      setInput(signature);
      parseMethodTypeSignature();
      actions.stop();
    } catch (GenericSignatureFormatError e) {
      throw e;
    } catch (Throwable t) {
      Error e = new GenericSignatureFormatError(
          "Unknown error parsing method signature: " + t.getMessage());
      e.addSuppressed(t);
      throw e;
    }
  }

  public void parseFieldSignature(String signature) {
    try {
      actions.start();
      setInput(signature);
      parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION);
      actions.stop();
    } catch (GenericSignatureFormatError e) {
      throw e;
    } catch (Throwable t) {
      Error e = new GenericSignatureFormatError(
          "Unknown error parsing field signature: " + t.getMessage());
      e.addSuppressed(t);
      throw e;
    }
  }

  private void setInput(String input) {
    this.buffer = input.toCharArray();
    this.eof = false;
    pos = 0;
    symbol = 0;
    identifier = null;
    scanSymbol();
  }

  //
  // Parser:
  //

  void parseClassSignature() {
    // ClassSignature ::= OptFormalTypeParameters SuperclassSignature {SuperinterfaceSignature}.

    parseOptFormalTypeParameters();

    // SuperclassSignature ::= ClassTypeSignature.
    parseClassTypeSignature(ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION);

    while (symbol > 0) {
      // SuperinterfaceSignature ::= ClassTypeSignature.
      parseClassTypeSignature(ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION);
    }
  }

  void parseOptFormalTypeParameters() {
    // OptFormalTypeParameters ::= ["<" FormalTypeParameter {FormalTypeParameter} ">"].

    if (symbol == '<') {
      actions.parsedSymbol(symbol);
      scanSymbol();

      updateFormalTypeParameter();

      while ((symbol != '>') && (symbol > 0)) {
        updateFormalTypeParameter();
      }

      actions.parsedSymbol(symbol);
      expect('>');
    }
  }

  void updateFormalTypeParameter() {
    // FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
    scanIdentifier();
    assert identifier != null;
    actions.parsedIdentifier(identifier);

    // ClassBound ::= ":" [FieldTypeSignature].
    actions.parsedSymbol(symbol);
    expect(':');

    if (symbol == 'L' || symbol == '[' || symbol == 'T') {
      parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION);
    }

    while (symbol == ':') {
      // InterfaceBound ::= ":" FieldTypeSignature.
      actions.parsedSymbol(symbol);
      scanSymbol();
      parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION);
    }
  }

  private void parseFieldTypeSignature(ParserPosition parserPosition) {
    // FieldTypeSignature ::= ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature.
    switch (symbol) {
      case 'L':
        parseClassTypeSignature(parserPosition);
        break;
      case '[':
        // ArrayTypeSignature ::= "[" TypeSignature.
        actions.parsedSymbol(symbol);
        scanSymbol();
        updateTypeSignature(parserPosition);
        break;
      case 'T':
        updateTypeVariableSignature();
        break;
      default:
        parseError("Expected L, [ or T", pos);
    }
  }

  private void parseClassTypeSignature(ParserPosition parserPosition) {
    // ClassTypeSignature ::= "L" {Ident "/"} Ident OptTypeArguments {"." Ident OptTypeArguments}
    //  ";".
    actions.parsedSymbol(symbol);
    expect('L');

    StringBuilder qualIdent = new StringBuilder();
    scanIdentifier();
    assert identifier != null;
    while (symbol == '/') {
      qualIdent.append(identifier).append(symbol);
      scanSymbol();
      scanIdentifier();
      assert identifier != null;
    }

    qualIdent.append(this.identifier);
    T parsedEnclosingType = actions.parsedTypeName(qualIdent.toString(), parserPosition);

    updateOptTypeArguments();

    while (symbol == '.') {
      // Deal with Member Classes.
      actions.parsedSymbol(symbol);
      scanSymbol();
      scanIdentifier();
      assert identifier != null;
      parsedEnclosingType = actions.parsedInnerTypeName(parsedEnclosingType, identifier);
      updateOptTypeArguments();
    }

    actions.parsedSymbol(symbol);
    expect(';');
  }

  private void updateOptTypeArguments() {
    // OptTypeArguments ::= "<" TypeArgument {TypeArgument} ">".
    if (symbol == '<') {
      actions.parsedSymbol(symbol);
      scanSymbol();

      updateTypeArgument();
      while ((symbol != '>') && (symbol > 0)) {
        updateTypeArgument();
      }

      actions.parsedSymbol(symbol);
      expect('>');
    }
  }

  private void updateTypeArgument() {
    // TypeArgument ::= (["+" | "-"] FieldTypeSignature) | "*".
    if (symbol == '*') {
      actions.parsedSymbol(symbol);
      scanSymbol();
    } else if (symbol == '+') {
      actions.parsedSymbol(symbol);
      scanSymbol();
      parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION);
    } else if (symbol == '-') {
      actions.parsedSymbol(symbol);
      scanSymbol();
      parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION);
    } else {
      parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION);
    }
  }

 private  void updateTypeVariableSignature() {
    // TypeVariableSignature ::= "T" Ident ";".
    actions.parsedSymbol(symbol);
    expect('T');

    scanIdentifier();
    assert identifier != null;
    actions.parsedIdentifier(identifier);

    actions.parsedSymbol(symbol);
    expect(';');
  }

  private void updateTypeSignature(ParserPosition parserPosition) {
    switch (symbol) {
      case 'B':
      case 'C':
      case 'D':
      case 'F':
      case 'I':
      case 'J':
      case 'S':
      case 'Z':
        actions.parsedSymbol(symbol);
        scanSymbol();
        break;
      default:
        // Not an elementary type, but a FieldTypeSignature.
        parseFieldTypeSignature(parserPosition);
    }
  }

  private void parseMethodTypeSignature() {
    // MethodTypeSignature ::= [FormalTypeParameters] "(" {TypeSignature} ")" ReturnType
    //  {ThrowsSignature}.
    parseOptFormalTypeParameters();

    actions.parsedSymbol(symbol);
    expect('(');

    while (symbol != ')' && (symbol > 0)) {
      updateTypeSignature(ParserPosition.MEMBER_ANNOTATION);
    }

    actions.parsedSymbol(symbol);
    expect(')');

    updateReturnType();

    if (symbol == '^') {
      do {
        actions.parsedSymbol(symbol);
        scanSymbol();

        // ThrowsSignature ::= ("^" ClassTypeSignature) | ("^" TypeVariableSignature).
        if (symbol == 'T') {
          updateTypeVariableSignature();
        } else {
          parseClassTypeSignature(ParserPosition.MEMBER_ANNOTATION);
        }
      } while (symbol == '^');
    }
  }

  private void updateReturnType() {
    // ReturnType ::= TypeSignature | "V".
    if (symbol != 'V') {
      updateTypeSignature(ParserPosition.MEMBER_ANNOTATION);
    } else {
      actions.parsedSymbol(symbol);
      scanSymbol();
    }
  }


  //
  // Scanner:
  //

  private void scanSymbol() {
    if (!eof) {
      assert buffer != null;
      if (pos < buffer.length) {
        symbol = buffer[pos];
        pos++;
      } else {
        symbol = 0;
        eof = true;
      }
    } else {
      parseError("Unexpected end of signature", pos);
    }
  }

  private void expect(char c) {
    if (eof) {
      parseError("Unexpected end of signature", pos);
    }
    if (symbol == c) {
      scanSymbol();
    } else {
      parseError("Expected " + c, pos - 1);
    }
  }

 private  boolean isStopSymbol(char ch) {
    switch (ch) {
      case ':':
      case '/':
      case ';':
      case '<':
      case '.':
        return true;
      default:
        return false;
    }
  }

  // PRE: symbol is the first char of the identifier.
  // POST: symbol = the next symbol AFTER the identifier.
  private void scanIdentifier() {
    if (!eof && pos < buffer.length) {
      StringBuilder identBuf = new StringBuilder(32);
      if (!isStopSymbol(symbol)) {
        identBuf.append(symbol);

        // FINDBUGS
        char[] bufferLocal = buffer;
        assert bufferLocal != null;
        do {
          char ch = bufferLocal[pos];
          if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))
              || !isStopSymbol(ch)) {
            identBuf.append(bufferLocal[pos]);
            pos++;
          } else {
            identifier = identBuf.toString();
            scanSymbol();
            return;
          }
        } while (pos != bufferLocal.length);
        identifier = identBuf.toString();
        symbol = 0;
        eof = true;
      } else {
        // Ident starts with incorrect char.
        symbol = 0;
        eof = true;
        parseError();
      }
    } else {
      parseError("Unexpected end of signature", pos);
    }
  }

  private void parseError() {
    parseError("Unexpected", pos);
  }

  private void parseError(String message, int pos) {
    String arrow = CharBuffer.allocate(pos).toString().replace('\0', ' ') + '^';
    throw new GenericSignatureFormatError(
        message + " at position " + (pos + 1) + "\n" + String.valueOf(buffer) + "\n" + arrow);
  }
}
