2013-11-24 4 views
5

私はハスケルのC言語のパーサーを書く初めです。私はASTのデータ型をダウンしています。私は物事のパーサー側を掘り下げる前に、AST自体に簡単なクエリを書くことでそれを試しています。2レベルツリー型のUniplateの使用

私のASTはステートメント(if/elseのような値なし)と式(リテラルまたはバイナリ操作のような値を持つ)の2つのタイプを中心にしています。だから、それは(もちろん大幅に単純化され、)次のようになります。

data Statement 
    = Return Expession 
    | If Expression Expression 

data Expression 
    = Literal Int 
    | Variable String 
    | Binary Expression Op Expression 

は、私が式で使用されるすべての変数の名前を取得したいとします。

varsInExpression exp = concat [s | Variable s <- universe exp] 

しかし、文の変数のリストを探したいのですが? Statementの各コンストラクターには、を適用するネストされたExpressionがあります。だから、現時点では、私はすべてのStatementコンストラクタに対してパターンマッチする必要があるように見えます。これは、ユニプレートが避けるべきものです。私はドキュメントを十分にgrokkingしていないのですか?これはuniplateの制限ですか(それとも間違っていますか?)

答えて

7

これは、バイプレートの場合によく似ています。私は遅いData.Dataメソッドに頼っていますが、このコードはかなり簡単です。

{-# LANGUAGE DeriveDataTypeable #-} 
import Data.Data 
import Data.Typeable 
import Data.Generics.Uniplate.Data 
data Statement 
    = Return Expression 
    | If Expression Expression 
    deriving(Data, Typeable) 

data Expression 
    = Literal Int 
    | Variable String 
    | Binary Expression Int Expression 
    deriving(Data, Typeable) 

vars :: Statement -> [String] 
vars stmt = [ s | Variable s <- universeBi stmt] 

基本的にバイプレートは、ターゲット・タイプは、必ずしもソースと同じではありませんuniplatesの一般概念があり、例えば

biplate :: from -> (Str to, Str to -> from) 
+1

ああ!それは素晴らしいです。私はバイプレートに何か関係があるかもしれないと思ったが、 'universeBi'のために生成されたHaddockのドキュメントもなく、Googleが私を助けたこともなかった。感謝のヒープ:)。 –