2012-02-08 120 views
2

我正在將源文件拆分爲令牌,特別是掃描標識符。但是,要求標識符長達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 
+1

例外應僅用於「例外」情況。不要試圖用它們創建程序流。只需從您的方法中返回令牌。 – 2012-02-08 05:10:03

+0

這不是一個程序流程問題。我需要向正在使用該程序的人發出警告,說明他們的標識符太長,並且正在被截斷。我認爲一個例外將是這樣做的合理方法。什麼會是一個很好的選擇? – 2012-02-08 05:11:59

+0

讓我把它變成一個答案。 – 2012-02-08 05:28:02

回答

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,你應該使用類似RubyParserTreetop如果你解析別的東西。

+0

不幸的是,這是一個項目,我從頭開始編譯編譯器。如果我有選擇,我會使用lex和yacc來避免這部分編譯。另外,這種方法有什麼不好? (除了濫用異常) – 2012-02-08 05:19:49

+0

對於初學者來說,你的標記器可以短得多,因爲它的唯一作用是解析出標識符並忽略其他所有內容。只是分詞,並對每個超過30個字符的人發出警告:'好,壞= @ infile.read.split.partition {| word | word.length <30}'。 – 2012-02-08 05:21:58

+0

我抽象了其餘的標記器,它實際上標記了完整的輸入語言正確。除了我發佈的案例外。我解析的源文件可以包含任何可能在PL/0程序中的內容。 – 2012-02-08 05:24:26

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 

當你需要提醒你的東西,他們正在做的用戶在正常使用情況下,一般預料,只是輸出字符串到標準輸出或/和標準錯誤的情況下控制檯應用程序。