Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 在F中转换抽象语法树(AST)#_F#_Pattern Matching_Abstract Syntax Tree_Discriminated Union - Fatal编程技术网

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

F# 在F中转换抽象语法树(AST)#,f#,pattern-matching,abstract-syntax-tree,discriminated-union,F#,Pattern Matching,Abstract Syntax Tree,Discriminated Union,我正在尝试为决策逻辑表设计一个AST。对于代表AST的受歧视的联合,我希望能够做的一件事是出于不同的原因转换它的部分。为了清楚起见,我将给你举个例子 决策逻辑表 type expression = | Value of double | Variable of string | Equality of expression * expression type entry = | Entry of string type entries =

我正在尝试为决策逻辑表设计一个AST。对于代表AST的受歧视的联合,我希望能够做的一件事是出于不同的原因转换它的部分。为了清楚起见,我将给你举个例子

决策逻辑表

 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
@VAR=10;Y

上述内容可以理解为有一条规则,条件VAR=10以Y条目输入该规则

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

渲染(变换前)

渲染(变换后)

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

我想本质上我要做的是,每当我看到ConditionEntries节点时,我想为Entries列表中的每个字符串发出一个新规则,其中条件与条目相结合。这有什么意义吗

提前谢谢你的建议


p、 我还没有试着编译上面的例子,所以请原谅任何语法错误。

Hmm,根据您的AST,它被严重破坏了,这里有一个
transform
函数,它根据您想要的输入生成输出(虽然它不是递归的,但只使用带有一些模式匹配的
List.map
expression
是您唯一的递归类型,但看起来您不想递归地处理它。):


很抱歉AST被破坏了,为了简洁起见,我想我只会包括相关部分。谢谢你的回答,我稍后会尝试一下。不过还有一个问题:如果ConditionEntries和Condition位于另一个节点下,转换函数会有很大变化吗?(即,我只想更改“部分”)Hi Jeffrey,别担心,拆分的AST对我来说并不冒犯,我只是担心您建模语言的方式可能太复杂(AST中构建了太多语义?).关于你的后续问题,我不确定是否看不到大局,但一般来说,如果你只想变换一棵树的一部分,你可以有一个最终的全包匹配,它只返回树的分支不变,类似于
。|branch->branch
谢谢Stephen,我会测试它。
ConditionEntries(
    Equality(
        Variable("VAR"), 
        Value(10.0)), 
    Entries(["Y"]))
Rule(
    Condition(
        Equality(
            Variable("VAR"),
            Value(10.0)
        ),
        Entry("Y")
    )
)
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")]