我正在努力将源文件拆分为令牌,特别是扫描标识符。但是,要求标识符最长为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
答案 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。