Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 使用Parsec解析配置_Haskell_Parsec - Fatal编程技术网

Haskell 使用Parsec解析配置

Haskell 使用Parsec解析配置,haskell,parsec,Haskell,Parsec,这里我记住一个可能的配置是一个规范树,每个规范都有相应的关键字(字符串)和类型。大概是这样的: data Select = And | Or data ConfigTree = Node Select [ConfigTree] | Leaf (String, *) 我不知道如何正确地写这篇文章,因为没有“类型的类型”,但暂时不要这样 现在,给定这样一个树,我想构建一个解析器,它可以读取可能的有效配置;我假设我已经有了可以解析关键字/类型对的子解析器 例如,可能的配置树是: Node And [

这里我记住一个可能的配置是一个规范树,每个规范都有相应的关键字(字符串)和类型。大概是这样的:

data Select = And | Or
data ConfigTree = Node Select [ConfigTree] | Leaf (String, *)
我不知道如何正确地写这篇文章,因为没有“类型的类型”,但暂时不要这样

现在,给定这样一个树,我想构建一个解析器,它可以读取可能的有效配置;我假设我已经有了可以解析关键字/类型对的子解析器

例如,可能的配置树是:

Node And [ Leaf ("width", Double)
         , Node Or [ Leaf ("height", Double) , Leaf ("aspectratio", Double)
         ]
它可以指定矩形的大小。可能的配置文件如下所示:

aspectratio = 2
width = 10
(假设一个配置文件只是一个换行分隔对的列表,keyword=blah,其中blah是该关键字的相应解析器可以处理的;但它们可以是任意顺序的,只需与一个可能的“有效子集”匹配即可。)其中有效子集是包含顶部节点的任何子集,该子集包含其包含的“and”节点的所有子节点,也就是它包含的“or”节点的一个子节点。)


我甚至不知道如何开始构建这样一个解析器。有没有人能给出一些关于如何继续的提示,或者一种将上述ConfigTree数据类型完全重新构造为更易于解析的数据类型的方法?

为此构建解析器的问题是,您的输入格式与您的数据类型根本不匹配。输入格式是一个简单、易于解析的键值对列表,而数据类型是树。例如,要确定
节点中的所有子树是否有效,您必须知道完整的输入

因此,与其直接在解析器中验证键值对列表,不如事后再验证

我用一个小例子来说明我的意思:

data Type = TDouble | TString 
data Select = And | Or 
data ConfigTree = Node Select [ConfigTree] | Leaf (String, Type)

-- matches a list of key-value pairs against a tree
match :: [(String, String)] -> ConfigTree -> Bool
match sts (Leaf (s, t)) = case filter ((== s) . fst) sts of
                            -- we don't want multiple occurences of a key
                            [(_, v)] -> if valid v t then True else False 
                            _        -> False
match sts (Node And cfgs) = and . map (match sts) $ cfgs
-- not completely what you described, because it will match 1 or more
match sts (Node Or cfgs)  = or  . map (match sts) $ cfgs

-- validates a string against a type
valid :: String -> Type -> Bool
valid s TDouble = case reads s :: [(Double, String)] of
                    [(_, "")] -> True
                    _         -> False
valid _ TString = True

-- this is what you actually parsed
config = [ ("aspectratio", "2")
         , ("width", "123")
         , ("name", "Sam")
         ]

-- the example tree
cfgTree = Node And [ Leaf ("width", TDouble)
                   , Node Or [ Leaf ("height", TDouble), Leaf ("aspectratio", TDouble)]
                   ]

我不认为这是一个特别有用的例子,因为它所做的只是检查您的配置数据是否有效,它不会提取它们,但我希望它能证明我的意思。

非常感谢。我刚刚用这个答案做了一些事情,将输入转换成填充的配置树,如果生成的树无效,则会给出一个错误。我还没有使错误消息尽可能有用(这是我考虑改为使用Parsec的原因之一),但现在它似乎可以正常工作。谢谢好的,我现在唯一真正的问题是:除了列出所有可能起作用的类型之外,还有没有一种很好的方法来正确处理这些类型?(对不起,我意识到这并不是问题的真正内容。)也许
数据。动态
是你想要的?但我不认为列出所有类型是个坏主意。将会有多少种不同的类型?也许是3-Int,双精度和字符串?顺便说一句:你有没有看过是否有适合你需要的黑客软件包?