首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Haskell在引号之间进行解析

用Haskell在引号之间进行解析
EN

Stack Overflow用户
提问于 2018-09-13 18:31:30
回答 1查看 777关注 0票数 4

这些需求来自点语言规范,更准确地说,我试图解析[ID]属性,例如,

任何双引号字符串(“.”)可能包含转义引号(\")1;

以下应该是一个最小的例子。

代码语言:javascript
复制
{-# LANGUAGE OverloadedStrings #-}
module Main where

import           Text.Megaparsec
import           Text.Megaparsec.Char
import           Data.Void
import           Data.Char
import           Data.Text               hiding ( map
                                        , all
                                        , concat
                                        )

type Parser = Parsec Void Text

escape :: Parser String
escape = do
    d <- char '\\'
    c <- oneOf ['\\', '\"', '0', 'n', 'r', 'v', 't', 'b', 'f']
    return [d, c]

nonEscape :: Parser Char
nonEscape = noneOf ['\\', '\"', '\0', '\n', '\r', '\v', '\t', '\b', '\f']

identPQuoted :: Parser String
identPQuoted =
    let inner = fmap return (try nonEscape) <|> escape
    in  do
      char '"'
      strings <- many inner
      char '"'
      return $ concat strings

identP :: Parser Text
identP = identPQuoted >>= return . pack

main = parseTest identP "\"foo \"bar\""

上面的代码在返回"foo "的第二个代码上失败,尽管我想要foo "bar

我不明白为什么。我认为megaparsec会反复应用inner,直到它解析最终的"为止。但是它只重复应用nonEscape解析器,并且在第一次失败时,它使用了escape,然后它似乎跳过了内部字符串的其余部分,然后移到最后的引号。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-13 19:35:17

您的输入文本是"foo "bar",它不包含任何转义引号。它被解析为"foo "的完整ID (后面是bar",被忽略)。

如果要确保解析器使用所有可用的输入,则可以使用

代码语言:javascript
复制
parseTest (identP <* eof) "..."

如果您想向解析器提供一个带有转义引号的ID,如下所示.

代码语言:javascript
复制
"foo \"bar"

..。然后,您需要转义所有特殊字符以将它们嵌入Haskell源代码中:

代码语言:javascript
复制
main = parseTest identP "\"foo \\\"bar\""

\"表示文字"\\表示文字\

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52319817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档