[英]Parsing escape characters when creating parser from scratch in Haskell
我創建了下面的代碼,它是從頭開始構建解析器的一部分。 然而,當使用類似於此處描述的轉義字符時,我確實遇到了意外的 output,盡管我的 output 在使用 ghci 時如下所示不同:
ghci> parseString "'\\\\'"
[(Const (StringVal "\\"),"")]
ghci> parseString "'\\'"
[]
ghci> parseString "'\\\'"
[]
ghci> parseString "\\\"
<interactive>:50:18: error:
lexical error in string/character literal at end of input
ghci> parseString "\\"
[]
ghci> parseString "\\\\"
[]
如所見,我在解析'\\\\'
時得到了預期的 output,但在僅解析'\\'
時卻沒有(如上面引用的鏈接),我本以為[(Const (StringVal "\"),"")]
結果。這是我的代碼中的錯誤還是由於 ghci,如果是后者,我該如何克服它?
import Data.Char
import Text.ParserCombinators.ReadP
import Control.Applicative ((<|>))
type ParseError = String
type Parser a = ReadP a
space :: Parser Char
space = satisfy isSpace
spaces :: Parser String
spaces = many space
token :: Parser a -> Parser a
token combinator = spaces >> combinator
parseString input = readP_to_S (do
e <- pExp
token eof
return e) input
pExp :: Parser Exp
pExp = (do
pv <- stringConst
return pv)
pStr :: Parser String
pStr =
(do
string "'"
str <- many rightChar
string "'"
return str)
rightChar :: Parser Char
rightChar = (do
nextChar <- get
case nextChar of
'\\' -> (do ch <- (rightChar'); return ch)
_ -> return 'O' --nextChar
)
rightChar' :: Parser Char
rightChar' = (do
nextChar <- get
case nextChar of
'\\' -> return nextChar
'n' -> return '\n'
_ -> return 'N')
stringConst :: Parser Exp
stringConst =
(do
str <- pStr
return (Const (StringVal str)))
您需要記住,字符串的內部表示不同於 GHCi(甚至只是 GHC)從源代碼中的字符串文字讀取的字符,以及當您show
(或print
)字符串時 GHCi 打印為 output 的字符。
當 GHC 解析和讀取 Haskell 程序文本中的字符串文字"\\"
時,會創建一個由單個字符(反斜杠)組成的字符串。 當您打印此字符串時,它在控制台上顯示為"\\"
,但它仍然是一個由單個反斜杠字符組成的字符串。 當您說您希望 GHCi 提示符下的 output 包含字符串文字"\"
時,那是胡說八道。 沒有這樣的字符串。 沒有字符串的內部表示,當 GHCi 顯示時,會導致屏幕上顯示三個字符"
、 \
和"
,這與沒有字符串會打印為"hello
with no結束雙引號。
在您的第一個測試用例中:
ghci> parseString "'\\\\'"
您正在為解析器提供一個四字符的字符串——單引號、反斜杠、反斜杠、單引號。 如果這個字符串是從文件中讀取的,而不是在 GHCi 提示符下輸入的,那么它應該是文字的四字符程序文本:
'\\'
據推測,您希望解析器將其解析為由反斜杠組成的單字符字符串。 解析中的 output:
[(Const (StringVal "\\"),"")]
顯示您的解析器有效。 屏幕上顯示的字符串"\\"
代表一個由反斜杠組成的單字符字符串,這就是你想要的。
對於您的下一個案例:
ghci> parseString "'\\'"
您正在為解析器提供三個字符串:
'\'
據推測,這是一個解析錯誤,因為您似乎已經轉義了結束單引號,這意味着該字符串未終止。 您的解析器正確地無法解析它。
對於您的第三個測試用例:
ghci> parseString "'\\\'"
您已將相同的三個字符串傳遞給解析器:
'\'
字符串文字中的第三個反斜杠由 GHCi 處理為 escaping 結束單引號。 這是不必要的,但完全合法。
您的最終測試用例:
ghci> parseString "\\\"
在語法上無效 Haskell。第三個反斜杠轉義結束雙引號,使其成為字符串的一部分,現在您的字符串未終止,就好像您寫的一樣:
ghci> parseString "ab
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.