module RBS
  class Parser
    # Result of `Parser.lex`
    class LexResult
      attr_reader buffer: Buffer
      attr_reader value: Array[Token]

      def initialize: (buffer: Buffer, value: Array[Token]) -> void
    end

    # Represents a token per result of `Parser.lex`.
    class Token
      attr_reader type: Symbol
      attr_reader location: Location[untyped, untyped]

      def initialize: (type: Symbol, location: Location[untyped, untyped]) -> void
      def value: () -> String
      def comment?: () -> bool
    end

    # Parse a method type and return it
    #
    # When `range` keyword is specified, it starts parsing from the `begin` to the `end` of the range.
    #
    # ```ruby
    # RBS::Parser.parse_method_type("() -> void")                                # => `() -> void`
    # RBS::Parser.parse_method_type("() -> void", range: 0...)                   # => `() -> void`
    # RBS::Parser.parse_method_type("() -> void () -> String", range: 11...)     # => `() -> String`
    # RBS::Parser.parse_method_type("() -> void () -> String", range: 23...)     # => nil
    # ```
    #
    # When `require_eof` is `true`, an error is raised if more tokens are left in the input.
    # (Defaults to `false`.)
    #
    # ```ruby
    # RBS::Parser.parse_method_type("() -> void () -> String", require_eof: false)    # => `() -> void`
    # RBS::Parser.parse_method_type("() -> void () -> String", require_eof: true)     # => Raises an error
    #
    # RBS::Parser.parse_method_type("", require_eof: true)                            # => nil
    # ```
    #
    def self.parse_method_type: (Buffer | String, ?range: Range[Integer?], ?variables: Array[Symbol], ?require_eof: bool) -> MethodType?

    # Parse a type and return it
    #
    # When `range` keyword is specified, it starts parsing from the `begin` to the `end` of the range.
    #
    # ```ruby
    # RBS::Parser.parse_type("String")                          # => `String`
    # RBS::Parser.parse_type("String", range: 0...)             # => `String`
    # RBS::Parser.parse_type("String Integer", pos: 7...)       # => `Integer`
    # RBS::Parser.parse_type("String Integer", pos: 14...)      # => nil
    # ```
    #
    # When `require_eof` is `true`, an error is raised if more tokens are left in the input.
    # (Defaults to `false`.)
    #
    # ```ruby
    # RBS::Parser.parse_type("String untyped", require_eof: false)    # => `String`
    # RBS::Parser.parse_type("String untyped", require_eof: true)     # => Raises an error
    #
    # RBS::Parser.parse_type("", require_eof: true)                   # => nil
    # ```
    #
    def self.parse_type: (Buffer | String, ?range: Range[Integer?], ?variables: Array[Symbol], ?require_eof: bool) -> Types::t?

    # Parse whole RBS file and return an array of declarations
    #
    def self.parse_signature: (Buffer | String) -> [Buffer, Array[AST::Directives::t], Array[AST::Declarations::t]]

    # Parse a list of type parameters and return it
    #
    # ```ruby
    # RBS::Parser.parse_type_params("")                          # => nil
    # RBS::Parser.parse_type_params("[U, V]")                    # => `[:U, :V]`
    # RBS::Parser.parse_type_params("[in U, V < Integer]")       # => `[:U, :V]`
    # ```
    #
    # When `module_type_params` is `false`, an error is raised if `unchecked`, `in` or `out` are used.
    #
    # ```ruby
    # RBS::Parser.parse_type_params("[unchecked U]", module_type_params: false)   # => Raises an error
    # RBS::Parser.parse_type_params("[out U]", module_type_params: false)         # => Raises an error
    # RBS::Parser.parse_type_params("[in U]", module_type_params: false)          # => Raises an error
    # ```
    #
    def self.parse_type_params: (Buffer | String, ?module_type_params: bool) -> Array[AST::TypeParam]

    # Returns the magic comment from the buffer
    #
    def self.magic_comment: (Buffer) -> AST::Directives::ResolveTypeNames?

    # Parse whole RBS file and return result.
    #
    # ```ruby
    # RBS::Parser.lex("# Comment\nmodule A\nend\n").value.map(&:type)
    # # => [:tLINECOMMENT, :kMODULE, :tUIDENT, :kEND, :pEOF]
    # ```
    def self.lex: (Buffer | String) -> LexResult

    KEYWORDS: Hash[String, bot]

    private

    def self.buffer: (String | Buffer source) -> Buffer

    def self._parse_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof) -> Types::t?

    def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof) -> MethodType?

    def self._parse_signature: (Buffer, Integer start_pos, Integer end_pos) -> [Array[AST::Directives::t], Array[AST::Declarations::t]]

    def self._parse_type_params: (Buffer, Integer start_pos, Integer end_pos, bool module_type_params) -> Array[AST::TypeParam]

    def self._lex: (Buffer, Integer end_pos) -> Array[[Symbol, Location[untyped, untyped]]]

    class LocatedValue
    end
  end
end
