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

4
我正在设计一种决策逻辑表的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节点时,我希望针对Entries列表中的每个字符串发出一个新的Rule,其中Condition与Entry结合。这有意义吗?
提前感谢任何建议。
附言:我还没有尝试编译上面的示例,请原谅任何语法错误。
1个回答

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")]

抱歉关于AST的破碎,我认为为了简洁起见,只包含相关部分。感谢您的答案,稍后我会尝试一下。还有一个问题:如果ConditionEntries和Condition在另一个节点下面,转换函数会发生很大变化吗?(即我只想更改树的“部分”,而不是全部) - Jeffrey Cameron
嗨,杰弗里,不用担心,你分解的AST对我来说并不冒犯,我只是表达了一些担忧,你建模语言的方式可能过于复杂(AST中嵌入了太多语义?)。 - Stephen Swensen
关于您的后续问题,如果没有看到整个情况,我不确定,但通常如果您只想转换树的一部分,您可以有一个最终的捕获所有匹配,它只返回树的分支而不改变,类似于 ... | branch -> branch - Stephen Swensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接