模块的循环依赖

dan*_*iol 8 f#

我想在F#中编写一个解析器,因为我必须使用Antlr.这意味着我必须Visitor为每个要解析的AST节点定义一个类.现在我遇到了一些问题,即存在一些循环依赖的规则,例如:

boolExpr : boolTerm 'or' boolTerm ;
boolTerm : boolAtom 'and' boolAtom ;
boolAtom : '(' boolExpr ')' 
         | ... ;
Run Code Online (Sandbox Code Playgroud)

这意味着我需要3个具有相同循环依赖关系的访问者类,并且我希望将每个访问者类放在他们自己的文件中

//BoolExprVisitor.fs
let boolExprVisitor = { new BaseVisitor<AST.BoolExpr>() with
    override __.VisitBoolExpr(context: BoolExprContext) =
        context.boolTerm() |> mapAccept boolTermVisitor |> AST.BoolExpr
}

//BoolTermVisitor.fs
let boolTermVisitor = { new BaseVisitor<AST.BoolTerm>() with
    override __.VisitBoolTerm(context: BoolTermContext) =
        context.boolAtom() |> mapAccept boolAtomVisitor |> AST.BoolTerm
}

//BoolAtomVisitor.fs
let boolAtomVisitor = { new BaseVisitor<AST.BoolAtom>() with
    override __.VisitBoolAtom(context: BoolAtomContext) =
        context.boolExpr() |> accept boolExprVisitor |> AST.BoolAtom
}
Run Code Online (Sandbox Code Playgroud)

但是F#并不喜欢这些循环依赖.如何使F#接受它们或重构我的访问者以不需要cyclid依赖?

dan*_*iol 1

对于将来遇到这个问题的任何人:
正如 rmunn 所说,我想要不同文件中的类这一事实根本就不是好的设计。另外,我不需要不同的 AST 节点BoolTermBoolAtom因为BoolExpr它们都可以被描述为同一个节点BoolExpr

我的解决方案是将所有布尔表达式访问者合并到同一个类中(并将表达式访问者的所有文件合并到一个文件中):

//AST.fs
type BoolExpr = 
    | BoolConjunctionExpr of BoolOp * BoolExpr list
    | ...

//ExpressionVisitors.fs
let boolExprVisitor = { new BaseVisitor<AST.BoolExpr>() with
    override this.VisitBoolExpr(context: BoolExprContext) =
        context.boolTerm() |> mapAccept this |> AST.BoolConjunctionExpr AST.Or

    override this.VisitBoolTerm(context: BoolTermContext) =
        context.boolAtom() |> mapAccept this |> AST.BoolConjunctionExpr AST.And

    override this.VisitBoolAtom(context: BoolAtomContext) =
        context.boolExpr() |> accept this
}
Run Code Online (Sandbox Code Playgroud)