class CmdParse
# STANDALONE START
    def setup_parser(str, debug=false)
      @string = str
      @pos = 0
      @memoizations = Hash.new { |h,k| h[k] = {} }
      @result = nil
      @failed_rule = nil
      @failing_rule_offset = -1
    end

    # This is distinct from setup_parser so that a standalone parser
    # can redefine #initialize and still have access to the proper
    # parser setup code.
    #
    def initialize(str, debug=false)
      setup_parser(str, debug)
    end

    attr_reader :string
    attr_reader :result, :failing_rule_offset
    attr_accessor :pos

    # STANDALONE START
    def current_column(target=pos)
      if c = string.rindex("\n", target-1)
        return target - c - 1
      end

      target + 1
    end

    def current_line(target=pos)
      cur_offset = 0
      cur_line = 0

      string.each_line do |line|
        cur_line += 1
        cur_offset += line.size
        return cur_line if cur_offset >= target
      end

      -1
    end

    def lines
      lines = []
      string.each_line { |l| lines << l }
      lines
    end

    #

    def get_text(start)
      @string[start..@pos-1]
    end

    def show_pos
      width = 10
      if @pos < width
        "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
      else
        "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
      end
    end

    def failure_info
      l = current_line @failing_rule_offset
      c = current_column @failing_rule_offset
      info = self.class::Rules[@failed_rule]

      "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
    end

    def failure_caret
      l = current_line @failing_rule_offset
      c = current_column @failing_rule_offset

      line = lines[l-1]
      "#{line}\n#{' ' * (c - 1)}^"
    end

    def failure_character
      l = current_line @failing_rule_offset
      c = current_column @failing_rule_offset
      lines[l-1][c-1, 1]
    end

    def failure_oneline
      l = current_line @failing_rule_offset
      c = current_column @failing_rule_offset

      info = self.class::Rules[@failed_rule]
      char = lines[l-1][c-1, 1]

      "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
    end

    class ParseError < RuntimeError
    end

    def raise_error
      raise ParseError, failure_oneline
    end

    def show_error(io=STDOUT)
      error_pos = @failing_rule_offset
      line_no = current_line(error_pos)
      col_no = current_column(error_pos)

      info = self.class::Rules[@failed_rule]
      io.puts "On line #{line_no}, column #{col_no}:"
      io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
      io.puts "Got: #{string[error_pos,1].inspect}"
      line = lines[line_no-1]
      io.puts "=> #{line}"
      io.print(" " * (col_no + 3))
      io.puts "^"
    end

    def set_failed_rule(name)
      if @pos > @failing_rule_offset
        @failed_rule = name
        @failing_rule_offset = @pos
      end
    end

    attr_reader :failed_rule

    def match_string(str)
      len = str.size
      if @string[pos,len] == str
        @pos += len
        return str
      end

      return nil
    end

    def scan(reg)
      if m = reg.match(@string[@pos..-1])
        width = m.end(0)
        @pos += width
        return true
      end

      return nil
    end

    if "".respond_to? :getbyte
      def get_byte
        if @pos >= @string.size
          return nil
        end

        s = @string.getbyte @pos
        @pos += 1
        s
      end
    else
      def get_byte
        if @pos >= @string.size
          return nil
        end

        s = @string[@pos]
        @pos += 1
        s
      end
    end

    def parse
      _root ? true : false
    end

    class LeftRecursive
      def initialize(detected=false)
        @detected = detected
      end

      attr_accessor :detected
    end

    class MemoEntry
      def initialize(ans, pos)
        @ans = ans
        @pos = pos
        @uses = 1
        @result = nil
      end

      attr_reader :ans, :pos, :uses, :result

      def inc!
        @uses += 1
      end

      def move!(ans, pos, result)
        @ans = ans
        @pos = pos
        @result = result
      end
    end

    def apply(rule)
      if m = @memoizations[rule][@pos]
        m.inc!

        prev = @pos
        @pos = m.pos
        if m.ans.kind_of? LeftRecursive
          m.ans.detected = true
          return nil
        end

        @result = m.result

        return m.ans
      else
        lr = LeftRecursive.new(false)
        m = MemoEntry.new(lr, @pos)
        @memoizations[rule][@pos] = m
        start_pos = @pos

        ans = __send__ rule

        m.move! ans, @pos, @result

        # Don't bother trying to grow the left recursion
        # if it's failing straight away (thus there is no seed)
        if ans and lr.detected
          return grow_lr(rule, start_pos, m)
        else
          return ans
        end

        return ans
      end
    end

    def grow_lr(rule, start_pos, m)
      while true
        @pos = start_pos
        @result = m.result

        ans = __send__ rule
        return nil unless ans

        break if @pos <= m.pos

        m.move! ans, @pos, @result
      end

      @result = m.result
      @pos = m.pos
      return m.ans
    end

    class RuleInfo
      def initialize(name, rendered)
        @name = name
        @rendered = rendered
      end

      attr_reader :name, :rendered
    end

    def self.rule_info(name, rendered)
      RuleInfo.new(name, rendered)
    end

    #


##################################################### 
  # Structure to hold composite method names
unless defined? SymbolEntry
  SymbolEntry = Struct.new(:type, :name, :chain)


  # Structure to hold position information
  Position = Struct.new(:container_type, :container,
                       :position_type,  :position)

  # Structure to hold breakpoint information
  Breakpoint = Struct.new(:position, :negate, :condition)

  # Structure to hold list information
  List = Struct.new(:position, :num)

  DEFAULT_OPTS = {
    :debug=>false, 
    :file_exists_proc => Proc.new{|filename|
        File.readable?(filename) && !File.directory?(filename)
    }
  }
end

  def initialize(str, opts={})
    @opts = DEFAULT_OPTS.merge(opts)
    setup_parser(str, opts[:debug])
    @file_exists_proc = @opts[:file_exists_proc]
  end


   


  # upcase_letter = /[A-Z]/
  def _upcase_letter
    _tmp = scan(/\A(?-mix:[A-Z])/)
    set_failed_rule :_upcase_letter unless _tmp
    return _tmp
  end

  # downcase_letter = /[a-z]/
  def _downcase_letter
    _tmp = scan(/\A(?-mix:[a-z])/)
    set_failed_rule :_downcase_letter unless _tmp
    return _tmp
  end

  # suffix_letter = /[=!?]/
  def _suffix_letter
    _tmp = scan(/\A(?-mix:[=!?])/)
    set_failed_rule :_suffix_letter unless _tmp
    return _tmp
  end

  # letter = (upcase_letter | downcase_letter)
  def _letter

    _save = self.pos
    while true # choice
      _tmp = apply(:_upcase_letter)
      break if _tmp
      self.pos = _save
      _tmp = apply(:_downcase_letter)
      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_letter unless _tmp
    return _tmp
  end

  # id_symbol = (letter | "_" | [0-9])
  def _id_symbol

    _save = self.pos
    while true # choice
      _tmp = apply(:_letter)
      break if _tmp
      self.pos = _save
      _tmp = match_string("_")
      break if _tmp
      self.pos = _save
      _save1 = self.pos
      _tmp = get_byte
      if _tmp
        unless _tmp >= 48 and _tmp <= 57
          self.pos = _save1
          _tmp = nil
        end
      end
      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_id_symbol unless _tmp
    return _tmp
  end

  # vm_identifier = < (downcase_letter | "_") id_symbol* suffix_letter? > {        SymbolEntry.new(:variable, text)     }
  def _vm_identifier

    _save = self.pos
    while true # sequence
      _text_start = self.pos
  
    _save1 = self.pos
      while true # sequence
    
    _save2 = self.pos
        while true # choice
          _tmp = apply(:_downcase_letter)
          break if _tmp
          self.pos = _save2
          _tmp = match_string("_")
          break if _tmp
          self.pos = _save2
          break
        end # end choice

        unless _tmp
          self.pos = _save1
          break
        end
        while true
          _tmp = apply(:_id_symbol)
          break unless _tmp
        end
        _tmp = true
        unless _tmp
          self.pos = _save1
          break
        end
        _save4 = self.pos
        _tmp = apply(:_suffix_letter)
        unless _tmp
          _tmp = true
          self.pos = _save4
        end
        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin;    
      SymbolEntry.new(:variable, text)
    ; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_vm_identifier unless _tmp
    return _tmp
  end

  # variable_identifier = < (downcase_letter | "_") id_symbol* > {        SymbolEntry.new(:variable, text)     }
  def _variable_identifier

    _save = self.pos
    while true # sequence
      _text_start = self.pos
  
    _save1 = self.pos
      while true # sequence
    
    _save2 = self.pos
        while true # choice
          _tmp = apply(:_downcase_letter)
          break if _tmp
          self.pos = _save2
          _tmp = match_string("_")
          break if _tmp
          self.pos = _save2
          break
        end # end choice

        unless _tmp
          self.pos = _save1
          break
        end
        while true
          _tmp = apply(:_id_symbol)
          break unless _tmp
        end
        _tmp = true
        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin;    
      SymbolEntry.new(:variable, text)
    ; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_variable_identifier unless _tmp
    return _tmp
  end

  # constant_identifier = < upcase_letter id_symbol* > {        SymbolEntry.new(:constant, text)     }
  def _constant_identifier

    _save = self.pos
    while true # sequence
      _text_start = self.pos
  
    _save1 = self.pos
      while true # sequence
        _tmp = apply(:_upcase_letter)
        unless _tmp
          self.pos = _save1
          break
        end
        while true
          _tmp = apply(:_id_symbol)
          break unless _tmp
        end
        _tmp = true
        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin;    
      SymbolEntry.new(:constant, text)
    ; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_constant_identifier unless _tmp
    return _tmp
  end

  # global_identifier = < "$" (constant_identifier | variable_identifier) > {       SymbolEntry.new(:global, text)     }
  def _global_identifier

    _save = self.pos
    while true # sequence
      _text_start = self.pos
  
    _save1 = self.pos
      while true # sequence
        _tmp = match_string("$")
        unless _tmp
          self.pos = _save1
          break
        end
    
    _save2 = self.pos
        while true # choice
          _tmp = apply(:_constant_identifier)
          break if _tmp
          self.pos = _save2
          _tmp = apply(:_variable_identifier)
          break if _tmp
          self.pos = _save2
          break
        end # end choice

        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin;   
      SymbolEntry.new(:global, text)
    ; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_global_identifier unless _tmp
    return _tmp
  end

  # local_internal_identifier = (constant_identifier | variable_identifier)
  def _local_internal_identifier

    _save = self.pos
    while true # choice
      _tmp = apply(:_constant_identifier)
      break if _tmp
      self.pos = _save
      _tmp = apply(:_variable_identifier)
      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_local_internal_identifier unless _tmp
    return _tmp
  end

  # local_identifier = (constant_identifier | vm_identifier)
  def _local_identifier

    _save = self.pos
    while true # choice
      _tmp = apply(:_constant_identifier)
      break if _tmp
      self.pos = _save
      _tmp = apply(:_vm_identifier)
      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_local_identifier unless _tmp
    return _tmp
  end

  # instance_identifier = < "@" local_identifier > {       SymbolEntry.new(:instance, text)     }
  def _instance_identifier

    _save = self.pos
    while true # sequence
      _text_start = self.pos
  
    _save1 = self.pos
      while true # sequence
        _tmp = match_string("@")
        unless _tmp
          self.pos = _save1
          break
        end
        _tmp = apply(:_local_identifier)
        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin;   
      SymbolEntry.new(:instance, text)
    ; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_instance_identifier unless _tmp
    return _tmp
  end

  # classvar_identifier = "@@" local_identifier:id {      SymbolEntry.new(:classvar, id)     }
  def _classvar_identifier

    _save = self.pos
    while true # sequence
      _tmp = match_string("@@")
      unless _tmp
        self.pos = _save
        break
      end
      _tmp = apply(:_local_identifier)
      id = @result
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin;   
     SymbolEntry.new(:classvar, id)
    ; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_classvar_identifier unless _tmp
    return _tmp
  end

  # identifier = (global_identifier | instance_identifier | classvar_identifier | local_identifier)
  def _identifier

    _save = self.pos
    while true # choice
      _tmp = apply(:_global_identifier)
      break if _tmp
      self.pos = _save
      _tmp = apply(:_instance_identifier)
      break if _tmp
      self.pos = _save
      _tmp = apply(:_classvar_identifier)
      break if _tmp
      self.pos = _save
      _tmp = apply(:_local_identifier)
      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_identifier unless _tmp
    return _tmp
  end

  # id_separator = < ("::" | ".") > { text }
  def _id_separator

    _save = self.pos
    while true # sequence
      _text_start = self.pos
  
    _save1 = self.pos
      while true # choice
        _tmp = match_string("::")
        break if _tmp
        self.pos = _save1
        _tmp = match_string(".")
        break if _tmp
        self.pos = _save1
        break
      end # end choice

      if _tmp
        text = get_text(_text_start)
      end
      unless _tmp
        self.pos = _save
        break
      end
      @result = begin;    text ; end
      _tmp = true
      unless _tmp
        self.pos = _save
      end
      break
    end # end sequence

    set_failed_rule :_id_separator unless _tmp
    return _tmp
  end

  # internal_class_module_chain = (< local_internal_identifier:parent id_separator:sep internal_class_module_chain:child > {          SymbolEntry.new(parent.type, text, [parent, child, sep])       } | local_identifier)
  def _internal_class_module_chain

    _save = self.pos
    while true # choice
  
    _save1 = self.pos
      while true # sequence
        _text_start = self.pos
    
    _save2 = self.pos
        while true # sequence
          _tmp = apply(:_local_internal_identifier)
          parent = @result
          unless _tmp
            self.pos = _save2
            break
          end
          _tmp = apply(:_id_separator)
          sep = @result
          unless _tmp
            self.pos = _save2
            break
          end
          _tmp = apply(:_internal_class_module_chain)
          child = @result
          unless _tmp
            self.pos = _save2
          end
          break
        end # end sequence

        if _tmp
          text = get_text(_text_start)
        end
        unless _tmp
          self.pos = _save1
          break
        end
        @result = begin;     
         SymbolEntry.new(parent.type, text, [parent, child, sep])
      ; end
        _tmp = true
        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      break if _tmp
      self.pos = _save
      _tmp = apply(:_local_identifier)
      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_internal_class_module_chain unless _tmp
    return _tmp
  end

  # class_module_chain = (< identifier:parent id_separator:sep internal_class_module_chain:child > {          SymbolEntry.new(parent.type, text, [parent, child, sep])       } | identifier)
  def _class_module_chain

    _save = self.pos
    while true # choice
  
    _save1 = self.pos
      while true # sequence
        _text_start = self.pos
    
    _save2 = self.pos
        while true # sequence
          _tmp = apply(:_identifier)
          parent = @result
          unless _tmp
            self.pos = _save2
            break
          end
          _tmp = apply(:_id_separator)
          sep = @result
          unless _tmp
            self.pos = _save2
            break
          end
          _tmp = apply(:_internal_class_module_chain)
          child = @result
          unless _tmp
            self.pos = _save2
          end
          break
        end # end sequence

        if _tmp
          text = get_text(_text_start)
        end
        unless _tmp
          self.pos = _save1
          break
        end
        @result = begin;     
         SymbolEntry.new(parent.type, text, [parent, child, sep])
      ; end
        _tmp = true
        unless _tmp
          self.pos = _save1
        end
        break
      end # end sequence

      break if _tmp
      self.pos = _save
      _tmp = apply(:_identifier)
      break if _tmp
      self.pos = _save
      break
    end # end choice

    set_failed_rule :_class_module_chain unless _tmp
    return _tmp
  end

  # sp = /[ \t]/
  def _sp
    _tmp = scan(/\A(?-mix:[ \t])/)
    set_failed_rule :_sp unless _tmp
    return _tmp
  end

  # - = sp+
  def __hyphen_
    _save = self.pos
    _tmp = apply(:_sp)
    if _tmp
      while true
        _tmp = apply(:_sp)
        break unless _tmp
      end
      _tmp = true
    else
      self.pos = _save
    end
    set_failed_rule :__hyphen_ unless _tmp
    return _tmp
  end

  # dbl_escapes = ("\\\"" { '"' } | "\\n" { "\n" } | "\\t" { "\t" } | "\\\\" { "\\" })
  def _dbl_escapes
  
    _save = self.pos
      while true # choice
    
    _save1 = self.pos
        while true # sequence
          _tmp = match_string("\\\"")
          unless _tmp
            self.pos = _save1
            break
          end
          @result = begin;        '"' ; end
          _tmp = true
          unless _tmp
            self.pos = _save1
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
    
    _save2 = self.pos
        while true # sequence
          _tmp = match_string("\\n")
          unless _tmp
            self.pos = _save2
            break
          end
          @result = begin;        "\n" ; end
          _tmp = true
          unless _tmp
            self.pos = _save2
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
    
    _save3 = self.pos
        while true # sequence
          _tmp = match_string("\\t")
          unless _tmp
            self.pos = _save3
            break
          end
          @result = begin;        "\t" ; end
          _tmp = true
          unless _tmp
            self.pos = _save3
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
    
    _save4 = self.pos
        while true # sequence
          _tmp = match_string("\\\\")
          unless _tmp
            self.pos = _save4
            break
          end
          @result = begin;        "\\" ; end
          _tmp = true
          unless _tmp
            self.pos = _save4
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
        break
      end # end choice

    set_failed_rule :_dbl_escapes unless _tmp
    return _tmp
  end

  # escapes = ("\\\"" { '"' } | "\\n" { "\n" } | "\\t" { "\t" } | "\\ " { " " } | "\\:" { ":" } | "\\\\" { "\\" })
  def _escapes
  
    _save = self.pos
      while true # choice
    
    _save1 = self.pos
        while true # sequence
          _tmp = match_string("\\\"")
          unless _tmp
            self.pos = _save1
            break
          end
          @result = begin;        '"' ; end
          _tmp = true
          unless _tmp
            self.pos = _save1
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
    
    _save2 = self.pos
        while true # sequence
          _tmp = match_string("\\n")
          unless _tmp
            self.pos = _save2
            break
          end
          @result = begin;        "\n" ; end
          _tmp = true
          unless _tmp
            self.pos = _save2
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
    
    _save3 = self.pos
        while true # sequence
          _tmp = match_string("\\t")
          unless _tmp
            self.pos = _save3
            break
          end
          @result = begin;        "\t" ; end
          _tmp = true
          unless _tmp
            self.pos = _save3
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
    
    _save4 = self.pos
        while true # sequence
          _tmp = match_string("\\ ")
          unless _tmp
            self.pos = _save4
            break
          end
          @result = begin;        " " ; end
          _tmp = true
          unless _tmp
            self.pos = _save4
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
    
    _save5 = self.pos
        while true # sequence
          _tmp = match_string("\\:")
          unless _tmp
            self.pos = _save5
            break
          end
          @result = begin;        ":" ; end
          _tmp = true
          unless _tmp
            self.pos = _save5
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
    
    _save6 = self.pos
        while true # sequence
          _tmp = match_string("\\\\")
          unless _tmp
            self.pos = _save6
            break
          end
          @result = begin;        "\\" ; end
          _tmp = true
          unless _tmp
            self.pos = _save6
          end
          break
        end # end sequence

        break if _tmp
        self.pos = _save
        break
      end # end choice

    set_failed_rule :_escapes unless _tmp
    return _tmp
  end

  # dbl_seq = < /[^\\"]+/ > { text }
  def _dbl_seq
  
    _save = self.pos
      while true # sequence
        _text_start = self.pos
        _tmp = scan(/\A(?-mix:[^\\"]+)/)
        if _tmp
          text = get_text(_text_start)
        end
        unless _tmp
          self.pos = _save
          break
        end
        @result = begin;      text ; end
        _tmp = true
        unless _tmp
          self.pos = _save
        end
        break
      end # end sequence

    set_failed_rule :_dbl_seq unless _tmp
    return _tmp
  end

  # dbl_not_quote = (dbl_escapes | dbl_seq)+:ary { ary }
  def _dbl_not_quote
  
    _save = self.pos
      while true # sequence
        _save1 = self.pos
        _ary = []
    
    _save2 = self.pos
        while true # choice
          _tmp = apply(:_dbl_escapes)
          break if _tmp
          self.pos = _save2
          _tmp = apply(:_dbl_seq)
          break if _tmp
          self.pos = _save2
          break
        end # end choice

        if _tmp
            _ary << @result
          while true
        
    _save3 = self.pos
            while true # choice
              _tmp = apply(:_dbl_escapes)
              break if _tmp
              self.pos = _save3
              _tmp = apply(:_dbl_seq)
              break if _tmp
              self.pos = _save3
              break
            end # end choice

            _ary << @result if _tmp
            break unless _tmp
          end
          _tmp = true
        @result = _ary
        else
          self.pos = _save1
        end
          ary = @result
          unless _tmp
            self.pos = _save
            break
          end
          @result = begin;        ary ; end
          _tmp = true
          unless _tmp
            self.pos = _save
          end
          break
        end # end sequence

    set_failed_rule :_dbl_not_quote unless _tmp
    return _tmp
  end

  # dbl_string = "\"" dbl_not_quote:ary "\"" { ary.join }
  def _dbl_string
    
    _save = self.pos
        while true # sequence
          _tmp = match_string("\"")
          unless _tmp
            self.pos = _save
            break
          end
          _tmp = apply(:_dbl_not_quote)
          ary = @result
          unless _tmp
            self.pos = _save
            break
          end
          _tmp = match_string("\"")
          unless _tmp
            self.pos = _save
            break
          end
          @result = begin;        ary.join ; end
          _tmp = true
          unless _tmp
            self.pos = _save
          end
          break
        end # end sequence

    set_failed_rule :_dbl_string unless _tmp
    return _tmp
  end

  # not_space_colon = (escapes | < /[^ \t\n:]/ > { text })
  def _not_space_colon
    
    _save = self.pos
        while true # choice
          _tmp = apply(:_escapes)
          break if _tmp
          self.pos = _save
      
    _save1 = self.pos
          while true # sequence
            _text_start = self.pos
            _tmp = scan(/\A(?-mix:[^ \t\n:])/)
            if _tmp
              text = get_text(_text_start)
            end
            unless _tmp
              self.pos = _save1
              break
            end
            @result = begin;          text ; end
            _tmp = true
            unless _tmp
              self.pos = _save1
            end
            break
          end # end sequence

          break if _tmp
          self.pos = _save
          break
        end # end choice

    set_failed_rule :_not_space_colon unless _tmp
    return _tmp
  end

  # not_space_colons = not_space_colon+:ary { ary.join }
  def _not_space_colons
    
    _save = self.pos
        while true # sequence
          _save1 = self.pos
          _ary = []
          _tmp = apply(:_not_space_colon)
          if _tmp
              _ary << @result
            while true
              _tmp = apply(:_not_space_colon)
              _ary << @result if _tmp
              break unless _tmp
            end
            _tmp = true
          @result = _ary
          else
            self.pos = _save1
          end
            ary = @result
            unless _tmp
              self.pos = _save
              break
            end
            @result = begin;          ary.join ; end
            _tmp = true
            unless _tmp
              self.pos = _save
            end
            break
          end # end sequence

    set_failed_rule :_not_space_colons unless _tmp
    return _tmp
  end

  # filename = (dbl_string | not_space_colons)
  def _filename
      
    _save = self.pos
          while true # choice
            _tmp = apply(:_dbl_string)
            break if _tmp
            self.pos = _save
            _tmp = apply(:_not_space_colons)
            break if _tmp
            self.pos = _save
            break
          end # end choice

    set_failed_rule :_filename unless _tmp
    return _tmp
  end

  # file_pos_sep = (sp+ | ":")
  def _file_pos_sep
      
    _save = self.pos
          while true # choice
            _save1 = self.pos
            _tmp = apply(:_sp)
            if _tmp
              while true
                _tmp = apply(:_sp)
                break unless _tmp
              end
              _tmp = true
            else
              self.pos = _save1
            end
              break if _tmp
              self.pos = _save
              _tmp = match_string(":")
              break if _tmp
              self.pos = _save
              break
            end # end choice

    set_failed_rule :_file_pos_sep unless _tmp
    return _tmp
  end

  # integer = < /[0-9]+/ > { text.to_i }
  def _integer
        
    _save = self.pos
            while true # sequence
              _text_start = self.pos
              _tmp = scan(/\A(?-mix:[0-9]+)/)
              if _tmp
                text = get_text(_text_start)
              end
              unless _tmp
                self.pos = _save
                break
              end
              @result = begin;            text.to_i ; end
              _tmp = true
              unless _tmp
                self.pos = _save
              end
              break
            end # end sequence

    set_failed_rule :_integer unless _tmp
    return _tmp
  end

  # sinteger = < /[+-]?[0-9]+/ > { text.to_i }
  def _sinteger
        
    _save = self.pos
            while true # sequence
              _text_start = self.pos
              _tmp = scan(/\A(?-mix:[+-]?[0-9]+)/)
              if _tmp
                text = get_text(_text_start)
              end
              unless _tmp
                self.pos = _save
                break
              end
              @result = begin;            text.to_i ; end
              _tmp = true
              unless _tmp
                self.pos = _save
              end
              break
            end # end sequence

    set_failed_rule :_sinteger unless _tmp
    return _tmp
  end

  # line_number = integer
  def _line_number
            _tmp = apply(:_integer)
    set_failed_rule :_line_number unless _tmp
    return _tmp
  end

  # vm_offset = "@" integer:int {     Position.new(nil, nil, :offset, int)   }
  def _vm_offset
        
    _save = self.pos
            while true # sequence
              _tmp = match_string("@")
              unless _tmp
                self.pos = _save
                break
              end
              _tmp = apply(:_integer)
              int = @result
              unless _tmp
                self.pos = _save
                break
              end
              @result = begin;           
    Position.new(nil, nil, :offset, int)
  ; end
              _tmp = true
              unless _tmp
                self.pos = _save
              end
              break
            end # end sequence

    set_failed_rule :_vm_offset unless _tmp
    return _tmp
  end

  # position = (vm_offset | line_number:l {    Position.new(nil, nil, :line, l)  })
  def _position
        
    _save = self.pos
            while true # choice
              _tmp = apply(:_vm_offset)
              break if _tmp
              self.pos = _save
          
    _save1 = self.pos
              while true # sequence
                _tmp = apply(:_line_number)
                l = @result
                unless _tmp
                  self.pos = _save1
                  break
                end
                @result = begin;              
  Position.new(nil, nil, :line, l) 
; end
                _tmp = true
                unless _tmp
                  self.pos = _save1
                end
                break
              end # end sequence

              break if _tmp
              self.pos = _save
              break
            end # end choice

    set_failed_rule :_position unless _tmp
    return _tmp
  end

  # location = (position | < filename >:file &{ @file_exists_proc.call(file) } file_pos_sep position:pos {       Position.new(:file, file, pos.position_type, pos.position)     } | < filename >:file &{ @file_exists_proc.call(file) } {       Position.new(:file, file, nil, nil)     } | class_module_chain?:fn file_pos_sep position:pos {       Position.new(:fn, fn, pos.position_type, pos.position)     } | class_module_chain?:fn {       Position.new(:fn, fn, nil, nil)     })
  def _location
        
    _save = self.pos
            while true # choice
              _tmp = apply(:_position)
              break if _tmp
              self.pos = _save
          
    _save1 = self.pos
              while true # sequence
                _text_start = self.pos
                _tmp = apply(:_filename)
                if _tmp
                  text = get_text(_text_start)
                end
                file = @result
                unless _tmp
                  self.pos = _save1
                  break
                end
                _save2 = self.pos
                _tmp = begin;  @file_exists_proc.call(file) ; end
                self.pos = _save2
                unless _tmp
                  self.pos = _save1
                  break
                end
                _tmp = apply(:_file_pos_sep)
                unless _tmp
                  self.pos = _save1
                  break
                end
                _tmp = apply(:_position)
                pos = @result
                unless _tmp
                  self.pos = _save1
                  break
                end
                @result = begin;             
      Position.new(:file, file, pos.position_type, pos.position)
    ; end
                _tmp = true
                unless _tmp
                  self.pos = _save1
                end
                break
              end # end sequence

              break if _tmp
              self.pos = _save
          
    _save3 = self.pos
              while true # sequence
                _text_start = self.pos
                _tmp = apply(:_filename)
                if _tmp
                  text = get_text(_text_start)
                end
                file = @result
                unless _tmp
                  self.pos = _save3
                  break
                end
                _save4 = self.pos
                _tmp = begin;  @file_exists_proc.call(file) ; end
                self.pos = _save4
                unless _tmp
                  self.pos = _save3
                  break
                end
                @result = begin;             
      Position.new(:file, file, nil, nil)
    ; end
                _tmp = true
                unless _tmp
                  self.pos = _save3
                end
                break
              end # end sequence

              break if _tmp
              self.pos = _save
          
    _save5 = self.pos
              while true # sequence
                _save6 = self.pos
                _tmp = apply(:_class_module_chain)
                @result = nil unless _tmp
                unless _tmp
                  _tmp = true
                  self.pos = _save6
                end
                fn = @result
                unless _tmp
                  self.pos = _save5
                  break
                end
                _tmp = apply(:_file_pos_sep)
                unless _tmp
                  self.pos = _save5
                  break
                end
                _tmp = apply(:_position)
                pos = @result
                unless _tmp
                  self.pos = _save5
                  break
                end
                @result = begin;             
      Position.new(:fn, fn, pos.position_type, pos.position)
    ; end
                _tmp = true
                unless _tmp
                  self.pos = _save5
                end
                break
              end # end sequence

              break if _tmp
              self.pos = _save
          
    _save7 = self.pos
              while true # sequence
                _save8 = self.pos
                _tmp = apply(:_class_module_chain)
                @result = nil unless _tmp
                unless _tmp
                  _tmp = true
                  self.pos = _save8
                end
                fn = @result
                unless _tmp
                  self.pos = _save7
                  break
                end
                @result = begin;             
      Position.new(:fn, fn, nil, nil)
    ; end
                _tmp = true
                unless _tmp
                  self.pos = _save7
                end
                break
              end # end sequence

              break if _tmp
              self.pos = _save
              break
            end # end choice

    set_failed_rule :_location unless _tmp
    return _tmp
  end

  # if_unless = < ("if" | "unless") > { text }
  def _if_unless
        
    _save = self.pos
            while true # sequence
              _text_start = self.pos
          
    _save1 = self.pos
              while true # choice
                _tmp = match_string("if")
                break if _tmp
                self.pos = _save1
                _tmp = match_string("unless")
                break if _tmp
                self.pos = _save1
                break
              end # end choice

              if _tmp
                text = get_text(_text_start)
              end
              unless _tmp
                self.pos = _save
                break
              end
              @result = begin;            text ; end
              _tmp = true
              unless _tmp
                self.pos = _save
              end
              break
            end # end sequence

    set_failed_rule :_if_unless unless _tmp
    return _tmp
  end

  # condition = < /.+/ > { text}
  def _condition
        
    _save = self.pos
            while true # sequence
              _text_start = self.pos
              _tmp = scan(/\A(?-mix:.+)/)
              if _tmp
                text = get_text(_text_start)
              end
              unless _tmp
                self.pos = _save
                break
              end
              @result = begin;            text; end
              _tmp = true
              unless _tmp
                self.pos = _save
              end
              break
            end # end sequence

    set_failed_rule :_condition unless _tmp
    return _tmp
  end

  # breakpoint_stmt_no_condition = location:loc {   Breakpoint.new(loc, false, 'true') }
  def _breakpoint_stmt_no_condition
        
    _save = self.pos
            while true # sequence
              _tmp = apply(:_location)
              loc = @result
              unless _tmp
                self.pos = _save
                break
              end
              @result = begin;           
  Breakpoint.new(loc, false, 'true')
; end
              _tmp = true
              unless _tmp
                self.pos = _save
              end
              break
            end # end sequence

    set_failed_rule :_breakpoint_stmt_no_condition unless _tmp
    return _tmp
  end

  # breakpoint_stmt = (location:loc - if_unless:iu - condition:cond {      Breakpoint.new(loc, iu == 'unless', cond) } | breakpoint_stmt_no_condition)
  def _breakpoint_stmt
        
    _save = self.pos
            while true # choice
          
    _save1 = self.pos
              while true # sequence
                _tmp = apply(:_location)
                loc = @result
                unless _tmp
                  self.pos = _save1
                  break
                end
                _tmp = apply(:__hyphen_)
                unless _tmp
                  self.pos = _save1
                  break
                end
                _tmp = apply(:_if_unless)
                iu = @result
                unless _tmp
                  self.pos = _save1
                  break
                end
                _tmp = apply(:__hyphen_)
                unless _tmp
                  self.pos = _save1
                  break
                end
                _tmp = apply(:_condition)
                cond = @result
                unless _tmp
                  self.pos = _save1
                  break
                end
                @result = begin;             
     Breakpoint.new(loc, iu == 'unless', cond)
; end
                _tmp = true
                unless _tmp
                  self.pos = _save1
                end
                break
              end # end sequence

              break if _tmp
              self.pos = _save
              _tmp = apply(:_breakpoint_stmt_no_condition)
              break if _tmp
              self.pos = _save
              break
            end # end choice

    set_failed_rule :_breakpoint_stmt unless _tmp
    return _tmp
  end

  # list_special_targets = < ("." | "-") > { text }
  def _list_special_targets
        
    _save = self.pos
            while true # sequence
              _text_start = self.pos
          
    _save1 = self.pos
              while true # choice
                _tmp = match_string(".")
                break if _tmp
                self.pos = _save1
                _tmp = match_string("-")
                break if _tmp
                self.pos = _save1
                break
              end # end choice

              if _tmp
                text = get_text(_text_start)
              end
              unless _tmp
                self.pos = _save
                break
              end
              @result = begin;            text ; end
              _tmp = true
              unless _tmp
                self.pos = _save
              end
              break
            end # end sequence

    set_failed_rule :_list_special_targets unless _tmp
    return _tmp
  end

  # list_stmt = ((list_special_targets | location):loc - sinteger:int? {   List.new(loc, int) } | (list_special_targets | location):loc {   List.new(loc, nil) })
  def _list_stmt
        
    _save = self.pos
            while true # choice
          
    _save1 = self.pos
              while true # sequence
            
    _save2 = self.pos
                while true # choice
                  _tmp = apply(:_list_special_targets)
                  break if _tmp
                  self.pos = _save2
                  _tmp = apply(:_location)
                  break if _tmp
                  self.pos = _save2
                  break
                end # end choice

                loc = @result
                unless _tmp
                  self.pos = _save1
                  break
                end
                _tmp = apply(:__hyphen_)
                unless _tmp
                  self.pos = _save1
                  break
                end
                _save3 = self.pos
                _tmp = apply(:_sinteger)
                int = @result
                unless _tmp
                  _tmp = true
                  self.pos = _save3
                end
                unless _tmp
                  self.pos = _save1
                  break
                end
                @result = begin;             
  List.new(loc, int)
; end
                _tmp = true
                unless _tmp
                  self.pos = _save1
                end
                break
              end # end sequence

              break if _tmp
              self.pos = _save
          
    _save4 = self.pos
              while true # sequence
            
    _save5 = self.pos
                while true # choice
                  _tmp = apply(:_list_special_targets)
                  break if _tmp
                  self.pos = _save5
                  _tmp = apply(:_location)
                  break if _tmp
                  self.pos = _save5
                  break
                end # end choice

                loc = @result
                unless _tmp
                  self.pos = _save4
                  break
                end
                @result = begin;             
  List.new(loc, nil)
; end
                _tmp = true
                unless _tmp
                  self.pos = _save4
                end
                break
              end # end sequence

              break if _tmp
              self.pos = _save
              break
            end # end choice

    set_failed_rule :_list_stmt unless _tmp
    return _tmp
  end

  Rules = {}
  Rules[:_upcase_letter] = rule_info("upcase_letter", "/[A-Z]/")
  Rules[:_downcase_letter] = rule_info("downcase_letter", "/[a-z]/")
  Rules[:_suffix_letter] = rule_info("suffix_letter", "/[=!?]/")
  Rules[:_letter] = rule_info("letter", "(upcase_letter | downcase_letter)")
  Rules[:_id_symbol] = rule_info("id_symbol", "(letter | \"_\" | [0-9])")
  Rules[:_vm_identifier] = rule_info("vm_identifier", "< (downcase_letter | \"_\") id_symbol* suffix_letter? > {        SymbolEntry.new(:variable, text)     }")
  Rules[:_variable_identifier] = rule_info("variable_identifier", "< (downcase_letter | \"_\") id_symbol* > {        SymbolEntry.new(:variable, text)     }")
  Rules[:_constant_identifier] = rule_info("constant_identifier", "< upcase_letter id_symbol* > {        SymbolEntry.new(:constant, text)     }")
  Rules[:_global_identifier] = rule_info("global_identifier", "< \"$\" (constant_identifier | variable_identifier) > {       SymbolEntry.new(:global, text)     }")
  Rules[:_local_internal_identifier] = rule_info("local_internal_identifier", "(constant_identifier | variable_identifier)")
  Rules[:_local_identifier] = rule_info("local_identifier", "(constant_identifier | vm_identifier)")
  Rules[:_instance_identifier] = rule_info("instance_identifier", "< \"@\" local_identifier > {       SymbolEntry.new(:instance, text)     }")
  Rules[:_classvar_identifier] = rule_info("classvar_identifier", "\"@@\" local_identifier:id {      SymbolEntry.new(:classvar, id)     }")
  Rules[:_identifier] = rule_info("identifier", "(global_identifier | instance_identifier | classvar_identifier | local_identifier)")
  Rules[:_id_separator] = rule_info("id_separator", "< (\"::\" | \".\") > { text }")
  Rules[:_internal_class_module_chain] = rule_info("internal_class_module_chain", "(< local_internal_identifier:parent id_separator:sep internal_class_module_chain:child > {          SymbolEntry.new(parent.type, text, [parent, child, sep])       } | local_identifier)")
  Rules[:_class_module_chain] = rule_info("class_module_chain", "(< identifier:parent id_separator:sep internal_class_module_chain:child > {          SymbolEntry.new(parent.type, text, [parent, child, sep])       } | identifier)")
  Rules[:_sp] = rule_info("sp", "/[ \\t]/")
  Rules[:__hyphen_] = rule_info("-", "sp+")
  Rules[:_dbl_escapes] = rule_info("dbl_escapes", "(\"\\\\\\\"\" { '\"' } | \"\\\\n\" { \"\\n\" } | \"\\\\t\" { \"\\t\" } | \"\\\\\\\\\" { \"\\\\\" })")
  Rules[:_escapes] = rule_info("escapes", "(\"\\\\\\\"\" { '\"' } | \"\\\\n\" { \"\\n\" } | \"\\\\t\" { \"\\t\" } | \"\\\\ \" { \" \" } | \"\\\\:\" { \":\" } | \"\\\\\\\\\" { \"\\\\\" })")
  Rules[:_dbl_seq] = rule_info("dbl_seq", "< /[^\\\\\"]+/ > { text }")
  Rules[:_dbl_not_quote] = rule_info("dbl_not_quote", "(dbl_escapes | dbl_seq)+:ary { ary }")
  Rules[:_dbl_string] = rule_info("dbl_string", "\"\\\"\" dbl_not_quote:ary \"\\\"\" { ary.join }")
  Rules[:_not_space_colon] = rule_info("not_space_colon", "(escapes | < /[^ \\t\\n:]/ > { text })")
  Rules[:_not_space_colons] = rule_info("not_space_colons", "not_space_colon+:ary { ary.join }")
  Rules[:_filename] = rule_info("filename", "(dbl_string | not_space_colons)")
  Rules[:_file_pos_sep] = rule_info("file_pos_sep", "(sp+ | \":\")")
  Rules[:_integer] = rule_info("integer", "< /[0-9]+/ > { text.to_i }")
  Rules[:_sinteger] = rule_info("sinteger", "< /[+-]?[0-9]+/ > { text.to_i }")
  Rules[:_line_number] = rule_info("line_number", "integer")
  Rules[:_vm_offset] = rule_info("vm_offset", "\"@\" integer:int {     Position.new(nil, nil, :offset, int)   }")
  Rules[:_position] = rule_info("position", "(vm_offset | line_number:l {    Position.new(nil, nil, :line, l)  })")
  Rules[:_location] = rule_info("location", "(position | < filename >:file &{ @file_exists_proc.call(file) } file_pos_sep position:pos {       Position.new(:file, file, pos.position_type, pos.position)     } | < filename >:file &{ @file_exists_proc.call(file) } {       Position.new(:file, file, nil, nil)     } | class_module_chain?:fn file_pos_sep position:pos {       Position.new(:fn, fn, pos.position_type, pos.position)     } | class_module_chain?:fn {       Position.new(:fn, fn, nil, nil)     })")
  Rules[:_if_unless] = rule_info("if_unless", "< (\"if\" | \"unless\") > { text }")
  Rules[:_condition] = rule_info("condition", "< /.+/ > { text}")
  Rules[:_breakpoint_stmt_no_condition] = rule_info("breakpoint_stmt_no_condition", "location:loc {   Breakpoint.new(loc, false, 'true') }")
  Rules[:_breakpoint_stmt] = rule_info("breakpoint_stmt", "(location:loc - if_unless:iu - condition:cond {      Breakpoint.new(loc, iu == 'unless', cond) } | breakpoint_stmt_no_condition)")
  Rules[:_list_special_targets] = rule_info("list_special_targets", "< (\".\" | \"-\") > { text }")
  Rules[:_list_stmt] = rule_info("list_stmt", "((list_special_targets | location):loc - sinteger:int? {   List.new(loc, int) } | (list_special_targets | location):loc {   List.new(loc, nil) })")
end
if __FILE__ == $0
  # require 'rubygems'; require_relative '../lib/trepanning';
  
  cp = CmdParse.new('', :debug=>true)
  %w(A::B @@classvar abc01! @ivar @ivar.meth
    Object A::B::C A::B::C::D A::B.c A.b.c.d).each do |name|
    cp.setup_parser(name, true)
    # debugger if name == '@ivar.meth'
    res = cp._class_module_chain
    p res
    p cp.string
    p cp.result
  end
  %w(A::B:5 A::B:@5 @@classvar abc01!:10 @ivar).each do |name|
    cp.setup_parser(name, true)
    res = cp._location
    p res
    p cp.string
    p cp.result
  end
  # require 'trepanning'; 
  ["#{__FILE__}:10", 'A::B  5',
   "#{__FILE__} 20"].each do |name|
    cp.setup_parser(name, true)
    res = cp._location
    p res
    p cp.string
    p cp.result
  end

  ['filename', '"this is a filename"',
   'this\ is\ another\ filename',
   'C\:filename'
   ].each do |name|
    puts '-' * 10
    cp.setup_parser(name, true)
    res = cp._filename
    p res
    puts cp.string
    p cp.result
  end
  ['.', '-', 'filename', '"this is a filename"',
   'this\ is\ another\ filename',
   'C\:filename', '5', '. 5', '5 10'
   ].each do |name|
    puts '-' * 10
    cp.setup_parser(name, {:debug=>true})
    res = cp._list_stmt
    p res
    puts cp.string
    p cp.result
  end
end
