在F#中转换抽象语法树(AST)

时间:2011-09-19 00:53:38

标签: f# pattern-matching abstract-syntax-tree discriminated-union

我正在尝试为决策逻辑表设计AST。我希望能够用代表我的AST的区别联合做的事情之一是由于不同的原因而改变它的一部分。为清楚起见,我将举一个例子

决策逻辑表

  

@ VAR = 10; Y; ​​

以上内容可以理解,因为有一条规则,条件VAR = 10用Y条目输入此规则。

抽象语法树定义(本例简化)

 type expression = 
     | Value of double
     | Variable of string 
     | Equality of expression * expression

type entry =
    | Entry of string

type entries =
    | Entries of entry list

type conditional =
    | ConditionEntries of expression * entries

type condition
    | Condition of expression * string

type rule = 
    | Rule of condition list

呈现(转化前)

ConditionEntries(
    Equality(
        Variable("VAR"), 
        Value(10.0)), 
    Entries(["Y"]))

呈现(转化后)

Rule(
    Condition(
        Equality(
            Variable("VAR"),
            Value(10.0)
        ),
        Entry("Y")
    )
)

现在我想要做的是转换上面的树以扩展条目中表示的规则。我的想法是我可以使用递归函数和模式匹配来做到这一点,但我现在正在绕着它缠绕一点点麻烦。

我想我想要做的就是每当我看到一个ConditionEntries节点时,我想为条目列表中的条目与条目组合的每个字符串发出一个新规则。这有什么意义吗?

提前感谢任何建议。

P.S。我还没有完全尝试编译上面的例子,所以请原谅任何语法错误。

1 个答案:

答案 0 :(得分:2)

嗯,基于你的AST,这是一个非常分散的,这里是一个tranform函数,它产生你想要的输入的输出(虽然它不是递归的,只是使用List.map和一些模式匹配。expression是你唯一的递归类型,但看起来你不想递归处理它?):

let ex1 =
    ConditionEntries(
        Equality(
            Variable("VAR"), 
            Value(10.0)), 
        Entries([Entry("Y")]))

let ex2 =
    ConditionEntries(
        Equality(
            Variable("VAR"), 
            Value(10.0)), 
        Entries([Entry("X");Entry("Y");Entry("Z")]))

let transform ces =
    match ces with
    | ConditionEntries(x, Entries(entries)) ->
        entries
        |> List.map (function Entry(entry) -> Condition(x, entry))


//FSI output:
> transform ex1;;
val it : condition list =
  [Condition (Equality (Variable "VAR",Value 10.0),"Y")]
> transform ex2;;
val it : condition list =
  [Condition (Equality (Variable "VAR",Value 10.0),"X");
   Condition (Equality (Variable "VAR",Value 10.0),"Y");
   Condition (Equality (Variable "VAR",Value 10.0),"Z")]