2009-10-20 92 views
0

我寫在Haskell詞法分析器。這裏是代碼:哈斯克爾詞法問題

lexer :: String -> [Token] 
lexer s 
    | s =~ whitespace :: Bool = 
     let token = s =~ whitespace :: String in 
      lex (drop (length token) s) 
    | s =~ number :: Bool = 
     let token = s =~ number :: String in 
      Val (read token) : lex (drop (length token) s) 
    | s =~ operator :: Bool = 
     let token = s =~ operator :: String in 
      Oper token : lex (drop (length token) s) 
    | otherwise = error "unrecognized character" 
    where 
     whitespace = "^[ \t\n]" 
     number = "^[0-9]*(\.[0-9]+)?" 
     operator = "^[+-*/()]" 

data Token = Val Int | Oper String 

我有兩個問題。一,數量正則表達式"^[0-9]*(\.[0-9]+)?"拋出這個錯誤:

lexical error in string/character literal at character '['

當我註釋掉包含它和使用它的功能的一部分行,我得到這個錯誤:

Couldn't match expected type `Token' 
      against inferred type `(String, String)' 
     Expected type: [Token] 
     Inferred type: [(String, String)] 
    In the expression: lex (drop (length token) s) 
    In the expression: 
     let token = s =~ whitespace :: String 
     in lex (drop (length token) s)

我有不知道爲什麼我得到這些錯誤。有人能幫我嗎?

回答

7

反斜槓用作轉義字符在字符串,象在"\n"用於容納一個新行的字符串。如果你想有一個反斜槓需要轉義爲"\\"。 這就是問題的正則表達式"^[0-9]*(\.[0-9]+)?",Haskell的解析器試圖解釋"\."作爲一個正常的字符串轉義扼流圈和它(可能是因爲有這樣的轉義)。如果您將正則表達式編寫爲"^[0-9]*(\\.[0-9]+)?",則錯誤消失。

的原因類型問題是,你從lex (drop (length token) s)標準的前奏,其類型爲String -> [(String, String)]調用lex。也許你想做一個遞歸調用自己的函數lexer,而不是...

+0

感謝。 :D在解析器上! – Micah 2009-10-20 01:40:46

2

另外,注意"^[0-9]*(\\.[0-9]+)?"一個空字符串或者號碼,如0.12(而非0.12),你可能不希望匹配。這是一個嚴重的問題,因爲它會導致你的函數無限調用它自己。要解決該問題,請將*更改爲+。