Ruby 在引发异常后保留变量
我正在将源文件拆分为令牌,特别是扫描标识符。但是,有一项要求是标识符的长度不得超过30个字符。当标识符达到此长度时,我会发出一条异常消息:Ruby 在引发异常后保留变量,ruby,lexical-analysis,Ruby,Lexical Analysis,我正在将源文件拆分为令牌,特别是扫描标识符。但是,有一项要求是标识符的长度不得超过30个字符。当标识符达到此长度时,我会发出一条异常消息:“标识符长度只能为30个字符,正在截断…” 应该是这样的,但是当我提出这个异常时,我跳出了我的方法,在我能够存储它之前扫描标识符。我需要以某种方式引发异常并保留到目前为止收集的标识符。关于如何做到这一点,有什么想法吗 # classify each character, and call approriate scan methods def tokenize
“标识符长度只能为30个字符,正在截断…”
应该是这样的,但是当我提出这个异常时,我跳出了我的方法,在我能够存储它之前扫描标识符。我需要以某种方式引发异常并保留到目前为止收集的标识符。关于如何做到这一点,有什么想法吗
# 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
海事组织,这是滥用例外,因为这不是例外情况。相反,考虑简单地记录一些东西:
if c =~ /[a-zA-Z0-9_]/
warn "Identifer was too long and was truncated"
this_id += c
如果出于某种原因必须使用异常,那么最简单的方法就是将此\u id
放在实例变量中:
@this_identifier = id
# ...
然后,当您中断救援时,只需将最后一个表达式设为@this\u identifier
即可返回该值(糟糕)
额外评论:这是一种解析源文件的非常糟糕的方法。如果你在解析Ruby,你应该使用类似于的东西,或者如果你在解析其他东西,你应该使用类似于的东西。我认为这是对异常的滥用,因为这不是一个例外情况。相反,考虑简单地记录一些东西:
if c =~ /[a-zA-Z0-9_]/
warn "Identifer was too long and was truncated"
this_id += c
如果出于某种原因必须使用异常,那么最简单的方法就是将此\u id
放在实例变量中:
@this_identifier = id
# ...
然后,当您中断救援时,只需将最后一个表达式设为@this\u identifier
即可返回该值(糟糕)
额外评论:这是一种解析源文件的非常糟糕的方法。如果您正在解析Ruby,则应该使用类似于的内容,如果您正在解析其他内容,则应该使用类似于的内容。异常只应在“异常”情况下使用。不要试图用它们创建程序流。只需从方法返回令牌 大致如下:
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输出一个字符串。只有在“异常”情况下才应使用异常。不要试图用它们创建程序流。只需从方法返回令牌 大致如下:
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输出一个字符串。异常只应在“异常”情况下使用。不要试图用它们创建程序流。只需从您的方法返回令牌。这不是程序流问题。我需要向使用该程序的人发出警告,警告他们的标识符太长,并且正在被截断。我认为一个例外是这样做的合乎逻辑的方式。什么是一个好的选择?让我把这变成一个答案。例外应该只在“例外”情况下使用。不要试图用它们创建程序流。只需从您的方法返回令牌。这不是程序流问题。我需要向使用该程序的人发出警告,警告他们的标识符太长,并且正在被截断。我认为一个例外是这样做的合乎逻辑的方式。什么是一个好的选择?让我把它变成一个答案。不幸的是,这是一个项目,我正在从头开始构建一个编译器。如果我有选择的话,我会使用lex和yacc来避免编译的这一部分。此外,这种方法有什么不好的地方?(除了异常滥用之外)对于初学者来说,您的标记器可以短得多,因为它唯一的作用是解析出标识符并忽略其他所有内容。只需对超过30个字符的单词进行拆分并发出警告:
good,bad=@infie.read.split.partition{| word | word.length<30}
。我提取了标记器的其余部分,它实际上正确地标记了完整的输入语言。除了我贴出的那个案子。我分析的源文件可以包含PL/0程序中的任何内容。@HunterMcMillen:Alrighty。我仍然认为Treetop更好,因为它是一种更好、更高级的词法分析方法。我同意Treetop更好,但作业要求我从头开始创建它。不幸的是,这是一个我正在从头开始构建编译器的项目。如果我有选择的话,我会使用lex和yacc来避免编译的这一部分。此外,这种方法有什么不好的地方?(除了异常滥用之外)对于初学者来说,您的标记器可以短得多,因为它唯一的作用是解析出标识符并忽略其他所有内容。只需对超过30个字符的单词进行拆分并发出警告:good,bad=@infie.read.split.partition{| word | word.length<30}
。我提取了标记器的其余部分,它实际上正确地标记了完整的输入语言。除了我贴出的那个案子。我分析的源文件可以包含PL/0程序中的任何内容。@HunterMcMillen:Alrighty。我仍然认为Treetop更好,因为它是一种更好、更高级的词法分析方法。我同意Treetop更好,但作业要求我从头开始创建它。