- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这里我想到的一个可能的配置是一个规范树,每个规范都有一个相应的关键字(字符串)和类型。像这样的事情:
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 是该关键字的相应解析器可以处理的内容;但它们可以采用任何顺序,并且只需匹配树的一个可能的“有效子集”,其中有效子集是包含顶部节点的任何子集,该子集包含它所包含的“和”节点的所有子节点,并且确切地说它是“或”节点的一个子节点包含。)
我不知道如何开始构建这样的解析器。任何人都可以提供一些有关如何继续的提示,或者一种将上述 ConfigTree 数据类型完全重构为更易于解析的数据的方法吗?
最佳答案
为此构建解析器的问题是您的输入格式与您的数据类型根本不匹配。输入格式是简单、易于解析的键值对列表,而数据类型是树。例如。要确定 And
节点中的所有子树是否有效,您必须知道完整的输入。
因此,不要直接在解析器中验证键值对列表,而是稍后再验证。
我整理了一个小例子来说明我的意思:
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)]
]
我不认为这是一个特别有用的示例,因为它所做的只是检查您的配置数据是否有效,它不会提取它们,但我希望它能证明我的意思。
关于haskell - 使用 Parsec 解析配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9145087/
Haskell Parsec 的 indents 包提供了一种解析缩进式语言(如 Haskell 和 Python)的方法。它重新定义了 Parser类型,那么如何使用 Parsec 的 Text.P
我有一个用 Text 编写的解析器作为流类型,而默认为 Text.Parsec.String模块使用 String除此以外。 如何在 Parsec Text b c 的上下文中使用自定义编写的解析器
Text Text.Parsec Text.Parsec.ByteString Text.Parsec.ByteString.Lazy
我在弄清楚如何使用 Text.Parsec.Indent 中的任何功能时遇到问题 indents 提供的模块Haskell 的包,它是 Parsec 的一种附加组件。 所有这些功能有什么作用?它们将如
Text Text.Parsec Text.Parsec.ByteString Text.Parsec.ByteString.Lazy
我目前正在尝试使用现实世界 Haskell 中提供的完整 CSV 解析器。为了我尝试修改代码以使用 ByteString 而不是 String,但是有一个 string 组合器仅适用于 字符串。 是否
我正在尝试解析嵌套的类 C block 注释 import Text.ParserCombinators.Parsec import Control.Monad (liftM) flat :: Mon
如果违反语义规则,使用 Parsec 如何在特定位置指示错误。我知道通常我们不想做这样的事情,但考虑一下示例语法。 ::= | ... ::= a positive integer power
我目前正在尝试使用 Parsec 在 Haskell 中设计一个解析器。声明类型的语法应如下所示: Fruit is a Apple 类型也应该能够有参数: Fruit a b is a Apple
我写了这样的排列解析例子: data Entry = Entry { first_name :: String , last_name :: String , date_of_birt
我正在尝试解析(目前)Dot 语言的一个子集。 语法是here我的代码如下 import System.Environment import System.IO import qualified Te
我有一个列表,我需要解析除最后一个元素之外的所有元素都需要由一个解析器解析,最后一个元素需要由另一个解析器解析。 a = "p1 p1b ... p2" or a = "p2" 原来我试过 parse
我需要为一种编程语言创建一个解析器。到目前为止,它已经完成了 95%,我想说,除了一个小细节。 用这种语言编写的程序具有以下结构: outputs inputs expressions 要求是输出不能
在我的工作中,我遇到了很多粗糙的 sql,我有一个聪明的想法,那就是编写一个程序来解析 sql 并整齐地打印出来。我很快就完成了大部分工作,但遇到了一个我不知道如何解决的问题。 所以让我们假设 sql
我正在编写一种使用 Parsec 进行解析的编程语言。为了报告错误消息,我使用 getPosition 将语法树的每个元素都标记了其源位置。函数来自 the Pos module 秒差距。 但是,它只
我正在尝试使用 parsec 解析如下表达式: f a b c => (Appl (Appl (Appl f a) b) c) 我尝试使用以下内容: appl :: Parser Expr appl
是否有可能以某种方式获得某些自定义类型的解析错误?例如,从错误中获取更多关于解析上下文的信息会很酷。而且仅以短信的形式提供错误信息似乎不太方便。 最佳答案 正如 Rhymoid 所观察到的,不幸的是,
我对 Parsec 的一个常见问题是,如果无效输入出现在“正确”的位置,它往往会忽略它。 作为一个具体的例子,假设我们有 integer :: Parser Int ,我写 expression =
我正在使用 Parsec 解析表达式,并且我想使用 Parsec 中的用户状态来跟踪这些表达式中的变量。不幸的是,我真的不知道该怎么做。 给定以下代码: import Data.Set as Set
我正在尝试编写一个 Haksell Parsec Parser,它将文件中的输入数据解析为 LogLine 数据类型,如下所示: --Final parser that holds the indvi
我是一名优秀的程序员,十分优秀!