# File lib/cgikit/project/converter.rb, line 133
    def parse(string, filename = '')
      scanner = StringScanner.new( string, false )

      # The way to use these local variables is bad.      
      definitions     = []
      in_attrs        = false
      line_num        = 1      
      current_element = nil
      element_name    = nil
      element_type    = nil
      term            = "(;|\n)"

      # in the future, we may have to change this Proc object.
      pos_proc = proc do 
        "#{filename}:#{line_num}: "
      end
      
      while scanner.rest?
        # line break
        if scanner.skip(/(\r)?\n/) then
          line_num += 1
          next
        end

        # skip commnet or space
        if scanner.skip(/(?:#.*$|[ \r\f\t]+)/) then
          next
        end

        if in_attrs then
          # attribute
          if scanner.skip(/([a-zA-Z0-9_]+[\!\?]?)[ \r\f\t]*=[ \r\f\t]*/)
            key = scanner[1]

            # array and hash literal
            if scanner.skip(/^([^"'][^"';\n]*)\[/) then
              list   = nil
              object = scanner[1]

              if scanner.match?(/^(["'])/) then
                # string literal
                close = scanner[1]
                if     close == '"' and scanner.skip(/"(.*?)"\]/)
                elsif  close == "'" and scanner.skip(/'(.*?)'\]/)
                else
                  raise CKDParseError, \
                  pos_proc.call << scanner.peek(60).inspect << \
                  "\nString literal error. Or, \";\" doesn't exist."
                end
                list = "\"#{scanner[1]}\""
              else
                if scanner.skip(/([a-zA-Z0-9_\.\!\^^?]+)\][ \r\t\f]*#{term}/)
                  list = scanner[1]
                else
                  raise CKDParseError, pos_proc.call << \
                  scanner.peek(60).inspect << \
                  "\nArray or Hash literal error. Or, \";\" doesn't exist.\n"
                end
              end
              value = "#{object}[#{list}]"
              line_num += value.count("\n")

              # value of attribute
            elsif scanner.match?(/^([\"\'])/) then
              # string lietral
              close = scanner[1]
              if     close == '"' and scanner.skip(/"(.*?)"[ \r\f\t]*#{term}/m)
              elsif  close == "'" and scanner.skip(/'(.*?)'[ \r\f\t]*#{term}/m)
              else
                raise CKDParseError, \
                pos_proc.call << scanner.peek(60).inspect << \
                "\nString literal error. Or, \";\" doesn't exist."
              end

              value = "\"#{scanner[1]}\""
              line_num += value.count("\n")
            else
              # others
              #
              # This regexp is not accurate.
              if scanner.skip(/([a-zA-Z0-9_\.\!\^^?]+)[ \r\t\f]*#{term}/)
                value = ":\"#{scanner[1]}\""
              else
                raise CKDParseError, pos_proc.call << \
                scanner.peek(60).inspect << \
                "\nMethod name error. Or, \";\" doesn't exist." "\n" 
              end
            end

            current_element[key] = value      
            next
          end

          # end of definition
          if scanner.skip(/\s*\}/)
            definitions << current_element
            current_element = nil
            in_attrs = false
            next
          end

          # skips space and separator.
          #
          # (ex.)
          # foo : CKString{;}
          if scanner.skip(/[ \r\t\f]*#{term}/)
            next
          end
        else
          # extracts name of the element and its class
          # class's regexp is not precise.
          if scanner.skip(/([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_]+)\s*\{/)
            element_name = scanner[1]
            element_type = scanner[2]
            current_element = {}
            current_element['oid'] = element_name
            current_element['element'] = element_type

            definitions.each do |definition|
              if definition['oid'] == element_name then
                raise CKDParseError, pos_proc.call << \
                scanner.peek(60).inspect << \
                "\n'#{element_name}' definition is already existed." "\n" 
              end
            end
            
            in_attrs = true
            next
          end
        end

        def_str = _pretty_print(definitions)
        raise CKDParseError, pos_proc.call << scanner.peek(60).inspect << \
        "\nNot match any rule.\n\n" << def_str << "\n" 
      end

      # Now, there is no data to be parsed.      
      if in_attrs 
        raise CKDParseError, pos_proc.call << \
        "The last element is not enclosed.\n\n"
      end
      
      definitions
    end