引发异常后保留变量

时间:2012-02-08 05:07:23

标签: ruby lexical-analysis

我正在努力将源文件拆分为令牌,特别是扫描标识符。但是,要求标识符最长为30个字符。当标识符达到此长度时,我会使用以下消息引发异常:'Identifiers can only be 30 characters long, truncating..'

这应该是这样的,但是当我提出这个异常时,我跳出我的方法,在我能够存储它之前扫描标识符。我需要以某种方式提出异常并保留我到目前为止收集的标识符。关于如何做到这一点的任何想法?

# classify each character, and call approriate scan methods
def tokenize()
  @infile.each_char do |c|
    begin
      case c
      when /[a-zA-Z\$]/
        scan_identifier(c)
      when /\s/ 
        #ignore spaces
      else
        #do nothing
      end
    rescue TokenizerError => te
      puts "#{te.class}: #{te.message}"
    end
  end
end

# Reads an identifier from the source program
def scan_identifier(id)
  this_id = id #initialize this identifier with the character read above

  @infile.each_char do |c|
    if c =~ /[a-zA-Z0-9_]/
      this_id += c 
      # raising this exception leaves this function before collecting the 
      # truncated identifier
      raise TokenizerError, 'Identifiers can only be 30 characters long, truncating..' if this_id.length == 30
    else 
      puts "#{this_id}"
      break # not part of the identifier, or an error
    end
  end
end

2 个答案:

答案 0 :(得分:3)

这是对例外的滥用,IMO,因为这不是一个例外情况。相反,请考虑简单记录一下:

    if c =~ /[a-zA-Z0-9_]/
      warn "Identifer was too long and was truncated"
      this_id += c 

如果由于某种原因必须使用异常,那么最直接的方法就是将this_id放在实例变量中:

@this_identifier = id
# ...

然后,当你突破救援时,只需让最后一个表达式为@this_identifier即可返回该值(yuck)。


奖励评论:这是解析源文件的一种真正可怜的方法。如果你要解析Ruby,你应该使用像 RubyParser 这样的东西;如果你正在解析别的东西,你应该使用 Treetop

答案 1 :(得分:1)

例外情况只应用于“例外”案件。不要试图用它们创建程序流。只需从您的方法返回令牌即可。

沿着这些方向:

 def tokenize()
    @infile.each_char do |c|
      begin
        case c
        when /[a-zA-Z\$]/
          scan_identifier(c)
        when /\s/ 
          #ignore spaces
        else
          #do nothing
        end
      end
    end
  end

  #Reads an identifier from the source program
  def scan_identifier(id)
    this_id = id #initialize this identifier with the character read above

    @infile.each_char do |c|
        if c =~ /[a-zA-Z0-9_]/
          this_id += c 
          if this_id.length == 30
            puts 'Identifiers can only be 30 characters long, truncating..'
            break
          end
        else 
          break #not part of the identifier, or an error
        end
    end
    puts "#{this_id}"
  end

当您需要警告用户他们正在做的事情是正常的用例并且通常是预期的时,只需在控制台应用程序的情况下将字符串输出到stdout或/和stderr。