3

ここで考えられる構成は仕様のツリーであり、各仕様には対応するキーワード (文字列) と型があることを念頭に置いています。このようなもの:

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 は、そのキーワードに対応するパーサーが処理できるものです。ただし、それらは任意の順序である可能性があり、1 つと一致する必要があります。ツリーの可能な「有効なサブセット」。有効なサブセットとは、最上位ノードを含む任意のサブセットであり、それが含む「and」ノードのすべての子を含み、「or」ノードの子を 1 つだけ含みます。)

そのようなパーサーの構築を開始する方法さえわかりません。続行する方法、または上記の ConfigTree データ型をより解析しやすいものに完全に再構築する方法について、誰かがいくつかのヒントを与えることができますか?

4

1 に答える 1

2

このためのパーサーを作成する際の問題は、入力形式がデータ型とまったく一致しないことです。入力形式は単純で簡単に解析できるキーと値のペアのリストですが、データ型はツリーです。たとえば、ノード内のすべてのサブツリー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)]
                   ]

構成データが有効かどうかを確認するだけで、それらを抽出するわけではないため、これは特に有用な例ではないと思いますが、私の意図を示してくれることを願っています。

于 2012-02-04T23:42:58.910 に答える