模块的循环依赖 [英] Cyclic dependency of modules

查看:69
本文介绍了模块的循环依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用F#编写解析器,由于某些原因,我不得不使用Antlr.这意味着我必须为要解析的每个AST节点定义一个 Visitor 类.现在我遇到的问题是,有些规则具有循环依赖性,例如:

I want to write a parser in F# and because of reasons I have to use Antlr. This means I have to define a Visitor class for every AST node I want to parse. Now I have the problem that there are some rules with cyclic dependencies like:

boolExpr : boolTerm 'or' boolTerm ;
boolTerm : boolAtom 'and' boolAtom ;
boolAtom : '(' boolExpr ')' 
         | ... ;

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

which means I need 3 visitor classes that have the same cyclic dependency and I want to have each of them in their own file

//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
}

但是F#不喜欢这些循环依赖项.我该如何使F#接受它们或重组访问者以不需要摆线依赖关系?

But F# doesn't like these cyclic dependencies. How can I make F# accept them or restructure my visitors to not need cyclid dependencies?

推荐答案

对于以后遇到此问题的任何人:
正如rmunn所说,我想要不同文件中的类的事实根本不是一个好设计.另外,我不需要为 BoolTerm BoolAtom BoolExpr 使用不同的AST节点,因为它们都可以描述为同一节点 BoolExpr .

For anyone coming across this problem in the future:
As rmunn said, the fact that I wanted the classes in different files was simply not good design. Also I did not need different AST nodes for BoolTerm, BoolAtom and BoolExpr as they could all be described as the same node BoolExpr.

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

My solution was to merge all of the boolean expression visitors into the same class (and merge all files for expression visitors into a single file):

//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
}

这篇关于模块的循环依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆