2012-10-17 21 views
14

我正在用Parsec寫我的第一個程序。我想解析MySQL模式轉儲,並希望提出一種很好的方式來解析代表某些關鍵字的字符串,以不區分大小寫的方式。這裏有一些代碼展示了我用來解析「CREATE」或「create」的方法。有一個更好的方法嗎?不會求助於buildExpressionParser的答案是最好的。我在這裏採取嬰兒的步驟。用Text.Combinators.Parsec做不區分大小寫的分析的最乾淨的方法是什麼?

p_create_t :: GenParser Char st Statement 
    p_create_t = do 
     x <- (string "CREATE" <|> string "create") 
     xs <- manyTill anyChar (char ';') 
     return $ CreateTable (x ++ xs) [] -- refine later 
+5

我假設即使運行解析器之前,輸入映射toLower'不是一個選項嗎?此外,我希望「不區分大小寫」也可以匹配「創建」,「CrEaTe」,「CREATe」或您的示例拒絕的任何其他變體。你要哪個? –

+0

這確實有用。謝謝。我沒有想到這一點! – dan

+1

@dan只要注意,如果你的輸入包含字符串,它們也會被小寫。例如,如果您的任何列包含默認的字符串值。 –

回答

17

您可以使用字符解析器構建不區分大小寫的解析器。

-- Match the lowercase or uppercase form of 'c' 
caseInsensitiveChar c = char (toLower c) <|> char (toUpper c) 

-- Match the string 's', accepting either lowercase or uppercase form of each character 
caseInsensitiveString s = try (mapM caseInsensitiveChar s) <?> "\"" ++ s ++ "\"" 
8

重複我在評論說,這顯然是有幫助的:

這裏簡單大錘的解決方案是在運行解析器之前簡單地映射toLower在整個輸入,然後把你所有的關鍵字匹配小寫。

如果您要解析某些地方需要區分大小寫且其他地區區分大小寫的情況,或者出於美觀原因考慮保留案例,則會帶來明顯的困難。例如,雖然HTML標記不區分大小寫,但在分析整個網頁時將其轉換爲小寫可能不合需要。即使在編譯不區分大小寫的編程語言時,轉換標識符也可能很煩人,因爲任何結果錯誤消息都不會與程序員編寫的內容相匹配。

0

代替具有toLower映射整個輸入的,可以考慮使用caseStringText.ParserCombinators.Parsec.Rfc2234(從hsemail包)

Text.ParsecCombinators.Parsec.Rfc2234

p_create_t :: GenParser Char st Statement 
p_create_t = do 
    x <- (caseString "create") 
    xs <- manyTill anyChar (char ';') 
    return $ CreateTable (x ++ xs) [] -- refine later 

所以現在x將任何情況下,變體是本在輸入中不改變你的輸入。

PS:我知道這是一個古老的問題,我只是想,我想補充一點,因爲這問題就來了,而我正在尋找類似的問題

+0

這不是來自Text.ParsecCombinators.Parsec。它來自Text.ParsecCombinators.Parsec.Rfc2234。你的鏈接是正確的,但你的標題是錯誤的。還值得注意的是,這是hsemail軟件包的一部分,有人可能還沒有安裝該軟件包。 – Sean

2

沒有,秒差距不能做到這一點清潔方式string在 原始tokens原始tokens之上實現,該組合子被硬編碼以使用相等性測試 (==)。分析大小寫不敏感的字符會稍微簡單一些,但是您可能需要更多其他信息。

然而,有秒差距的現代叉子,叫 Megaparsec擁有的一切,你可能想 內置的解決方案:

λ> parseTest (char' 'a') "b" 
parse error at line 1, column 1: 
unexpected 'b' 
expecting 'A' or 'a' 
λ> parseTest (string' "foo") "Foo" 
"Foo" 
λ> parseTest (string' "foo") "FOO" 
"FOO" 
λ> parseTest (string' "foo") "fo!" 
parse error at line 1, column 1: 
unexpected "fo!" 
expecting "foo" 

注意最後一條錯誤信息,它比你可以得到更好的解析 字符一個接一個(在你的特定情況下特別有用)。 string' 與Parsec的string類似,但使用不區分大小寫的 比較來比較字符。也有oneOf'noneOf', 在某些情況下可能會有所幫助。


披露:我是百萬秒差距的作者之一。

+0

令人驚訝的是,'tokens'不允許比較函數傳遞給它來執行原始Parsec中的比較。 – MicroVirus

相關問題