# Autogenerated from a Treetop grammar. Edits may be lost.


module Laser
  module Parsers
    module Annotation
      include Treetop::Runtime

      def root
        @root ||= :named_annotation
      end

      include Class

      include Structural

      include Overload

      include GeneralPurpose

      def _nt_named_annotation
        start_index = index
        if node_cache[:named_annotation].has_key?(index)
          cached = node_cache[:named_annotation][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        i0 = index
        r1 = _nt_named_type_annotation
        if r1
          r0 = r1
        else
          r2 = _nt_named_literal_annotation
          if r2
            r0 = r2
          else
            @index = i0
            r0 = nil
          end
        end

        node_cache[:named_annotation][start_index] = r0

        r0
      end

      module NamedTypeAnnotation0
        def annotation_name
          elements[1]
        end

        def type
          elements[4]
        end

      end

      module NamedTypeAnnotation1
        def literal?
          false
        end

        def literal
          raise TypeError.new('This annotation is not a literal. Call #literal? first.')
        end

        def type?
          true
        end

        def type
          super.type
        end
      
        def name
          annotation_name.text_value
        end
      end

      def _nt_named_type_annotation
        start_index = index
        if node_cache[:named_type_annotation].has_key?(index)
          cached = node_cache[:named_type_annotation][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        i0, s0 = index, []
        s1, i1 = [], index
        loop do
          r2 = _nt_space
          if r2
            s1 << r2
          else
            break
          end
        end
        r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
        s0 << r1
        if r1
          r3 = _nt_annotation_name
          s0 << r3
          if r3
            if has_terminal?(':', false, index)
              r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
              @index += 1
            else
              terminal_parse_failure(':')
              r4 = nil
            end
            s0 << r4
            if r4
              s5, i5 = [], index
              loop do
                r6 = _nt_space
                if r6
                  s5 << r6
                else
                  break
                end
              end
              r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
              s0 << r5
              if r5
                r7 = _nt_type
                s0 << r7
                if r7
                  s8, i8 = [], index
                  loop do
                    r9 = _nt_space
                    if r9
                      s8 << r9
                    else
                      break
                    end
                  end
                  r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
                  s0 << r8
                end
              end
            end
          end
        end
        if s0.last
          r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
          r0.extend(NamedTypeAnnotation0)
          r0.extend(NamedTypeAnnotation1)
        else
          @index = i0
          r0 = nil
        end

        node_cache[:named_type_annotation][start_index] = r0

        r0
      end

      module NamedLiteralAnnotation0
        def annotation_name
          elements[1]
        end

        def literal
          elements[4]
        end

      end

      module NamedLiteralAnnotation1
        def literal?
          true
        end
        
        def literal
          super.literal
        end

        def type?
          false
        end

        def type
          raise TypeError.new('This annotation is not a type. Call #type? first.')
        end

        def name
          annotation_name.text_value
        end
      end

      def _nt_named_literal_annotation
        start_index = index
        if node_cache[:named_literal_annotation].has_key?(index)
          cached = node_cache[:named_literal_annotation][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        i0, s0 = index, []
        s1, i1 = [], index
        loop do
          r2 = _nt_space
          if r2
            s1 << r2
          else
            break
          end
        end
        r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
        s0 << r1
        if r1
          r3 = _nt_annotation_name
          s0 << r3
          if r3
            if has_terminal?(':', false, index)
              r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
              @index += 1
            else
              terminal_parse_failure(':')
              r4 = nil
            end
            s0 << r4
            if r4
              s5, i5 = [], index
              loop do
                r6 = _nt_space
                if r6
                  s5 << r6
                else
                  break
                end
              end
              r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
              s0 << r5
              if r5
                r7 = _nt_literal
                s0 << r7
                if r7
                  s8, i8 = [], index
                  loop do
                    r9 = _nt_space
                    if r9
                      s8 << r9
                    else
                      break
                    end
                  end
                  r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
                  s0 << r8
                end
              end
            end
          end
        end
        if s0.last
          r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
          r0.extend(NamedLiteralAnnotation0)
          r0.extend(NamedLiteralAnnotation1)
        else
          @index = i0
          r0 = nil
        end

        node_cache[:named_literal_annotation][start_index] = r0

        r0
      end

      module Literal0

        def literal
          false
        end
      end

      module Literal1
        def literal
          true
        end
      end

      module Literal2
        def literal
          nil
        end
      end

      module Literal3
        def literal
          text_value.to_sym
        end
      end

      def _nt_literal
        start_index = index
        if node_cache[:literal].has_key?(index)
          cached = node_cache[:literal][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        i0 = index
        if has_terminal?('false', false, index)
          r1 = instantiate_node(SyntaxNode,input, index...(index + 5))
          r1.extend(Literal0)
          @index += 5
        else
          terminal_parse_failure('false')
          r1 = nil
        end
        if r1
          r0 = r1
        else
          if has_terminal?('true', false, index)
            r2 = instantiate_node(SyntaxNode,input, index...(index + 4))
            r2.extend(Literal1)
            @index += 4
          else
            terminal_parse_failure('true')
            r2 = nil
          end
          if r2
            r0 = r2
          else
            if has_terminal?('nil', false, index)
              r3 = instantiate_node(SyntaxNode,input, index...(index + 3))
              r3.extend(Literal2)
              @index += 3
            else
              terminal_parse_failure('nil')
              r3 = nil
            end
            if r3
              r0 = r3
            else
              i4 = index
              if has_terminal?('never', false, index)
                r5 = instantiate_node(SyntaxNode,input, index...(index + 5))
                @index += 5
              else
                terminal_parse_failure('never')
                r5 = nil
              end
              if r5
                r4 = r5
                r4.extend(Literal3)
              else
                if has_terminal?('maybe', false, index)
                  r6 = instantiate_node(SyntaxNode,input, index...(index + 5))
                  @index += 5
                else
                  terminal_parse_failure('maybe')
                  r6 = nil
                end
                if r6
                  r4 = r6
                  r4.extend(Literal3)
                else
                  if has_terminal?('always', false, index)
                    r7 = instantiate_node(SyntaxNode,input, index...(index + 6))
                    @index += 6
                  else
                    terminal_parse_failure('always')
                    r7 = nil
                  end
                  if r7
                    r4 = r7
                    r4.extend(Literal3)
                  else
                    if has_terminal?('required', false, index)
                      r8 = instantiate_node(SyntaxNode,input, index...(index + 8))
                      @index += 8
                    else
                      terminal_parse_failure('required')
                      r8 = nil
                    end
                    if r8
                      r4 = r8
                      r4.extend(Literal3)
                    else
                      if has_terminal?('optional', false, index)
                        r9 = instantiate_node(SyntaxNode,input, index...(index + 8))
                        @index += 8
                      else
                        terminal_parse_failure('optional')
                        r9 = nil
                      end
                      if r9
                        r4 = r9
                        r4.extend(Literal3)
                      else
                        if has_terminal?('foolish', false, index)
                          r10 = instantiate_node(SyntaxNode,input, index...(index + 7))
                          @index += 7
                        else
                          terminal_parse_failure('foolish')
                          r10 = nil
                        end
                        if r10
                          r4 = r10
                          r4.extend(Literal3)
                        else
                          if has_terminal?('ignored', false, index)
                            r11 = instantiate_node(SyntaxNode,input, index...(index + 7))
                            @index += 7
                          else
                            terminal_parse_failure('ignored')
                            r11 = nil
                          end
                          if r11
                            r4 = r11
                            r4.extend(Literal3)
                          else
                            @index = i4
                            r4 = nil
                          end
                        end
                      end
                    end
                  end
                end
              end
              if r4
                r0 = r4
              else
                @index = i0
                r0 = nil
              end
            end
          end
        end

        node_cache[:literal][start_index] = r0

        r0
      end

      def _nt_type
        start_index = index
        if node_cache[:type].has_key?(index)
          cached = node_cache[:type][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        i0 = index
        r1 = _nt_union_type
        if r1
          r0 = r1
        else
          r2 = _nt_non_union_type
          if r2
            r0 = r2
          else
            r3 = _nt_empty_type
            if r3
              r0 = r3
            else
              @index = i0
              r0 = nil
            end
          end
        end

        node_cache[:type][start_index] = r0

        r0
      end

      module UnionType0
        def non_union_type
          elements[3]
        end
      end

      module UnionType1
        def non_union_type
          elements[0]
        end

        def rest_members
          elements[1]
        end
      end

      module UnionType2
        def type
          Types::UnionType.new([non_union_type, *rest_members].map(&:type))
        end
        
        def rest_members
          super.elements.map(&:non_union_type)
        end
      end

      def _nt_union_type
        start_index = index
        if node_cache[:union_type].has_key?(index)
          cached = node_cache[:union_type][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        i0, s0 = index, []
        r1 = _nt_non_union_type
        s0 << r1
        if r1
          s2, i2 = [], index
          loop do
            i3, s3 = index, []
            s4, i4 = [], index
            loop do
              r5 = _nt_space
              if r5
                s4 << r5
              else
                break
              end
            end
            r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
            s3 << r4
            if r4
              if has_terminal?('|', false, index)
                r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
                @index += 1
              else
                terminal_parse_failure('|')
                r6 = nil
              end
              s3 << r6
              if r6
                s7, i7 = [], index
                loop do
                  r8 = _nt_space
                  if r8
                    s7 << r8
                  else
                    break
                  end
                end
                r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
                s3 << r7
                if r7
                  r9 = _nt_non_union_type
                  s3 << r9
                end
              end
            end
            if s3.last
              r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
              r3.extend(UnionType0)
            else
              @index = i3
              r3 = nil
            end
            if r3
              s2 << r3
            else
              break
            end
          end
          if s2.empty?
            @index = i2
            r2 = nil
          else
            r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
          end
          s0 << r2
        end
        if s0.last
          r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
          r0.extend(UnionType1)
          r0.extend(UnionType2)
        else
          @index = i0
          r0 = nil
        end

        node_cache[:union_type][start_index] = r0

        r0
      end

      def _nt_non_union_type
        start_index = index
        if node_cache[:non_union_type].has_key?(index)
          cached = node_cache[:non_union_type][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        i0 = index
        r1 = _nt_top
        if r1
          r0 = r1
        else
          r2 = _nt_self_type
          if r2
            r0 = r2
          else
            r3 = _nt_function_type
            if r3
              r0 = r3
            else
              r4 = _nt_class_based_constraint
              if r4
                r0 = r4
              else
                r5 = _nt_structural_constraint
                if r5
                  r0 = r5
                else
                  @index = i0
                  r0 = nil
                end
              end
            end
          end
        end

        node_cache[:non_union_type][start_index] = r0

        r0
      end

      module EmptyType0
        def type
          Types::EMPTY
        end
      end

      def _nt_empty_type
        start_index = index
        if node_cache[:empty_type].has_key?(index)
          cached = node_cache[:empty_type][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        if has_terminal?('empty', false, index)
          r0 = instantiate_node(SyntaxNode,input, index...(index + 5))
          r0.extend(EmptyType0)
          @index += 5
        else
          terminal_parse_failure('empty')
          r0 = nil
        end

        node_cache[:empty_type][start_index] = r0

        r0
      end

      module Top0
        def type
          []
        end
      end

      def _nt_top
        start_index = index
        if node_cache[:top].has_key?(index)
          cached = node_cache[:top][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        if has_terminal?("Top", false, index)
          r0 = instantiate_node(SyntaxNode,input, index...(index + 3))
          r0.extend(Top0)
          @index += 3
        else
          terminal_parse_failure("Top")
          r0 = nil
        end

        node_cache[:top][start_index] = r0

        r0
      end

      module SelfType0
        def type
          Types::SelfType.new
        end
      end

      def _nt_self_type
        start_index = index
        if node_cache[:self_type].has_key?(index)
          cached = node_cache[:self_type][index]
          if cached
            cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
            @index = cached.interval.end
          end
          return cached
        end

        if has_terminal?("self", false, index)
          r0 = instantiate_node(SyntaxNode,input, index...(index + 4))
          r0.extend(SelfType0)
          @index += 4
        else
          terminal_parse_failure("self")
          r0 = nil
        end

        node_cache[:self_type][start_index] = r0

        r0
      end

    end

    class AnnotationParser < Treetop::Runtime::CompiledParser
      include Annotation
    end

  end
end
