簡體   English   中英

在 Haskell 從頭創建解析器時解析轉義字符

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM