f# – 模块的循环依赖

前端之家收集整理的这篇文章主要介绍了f# – 模块的循环依赖前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想在F#中编写一个解析器,因为我必须使用Antlr.这意味着我必须为每个要解析的AST节点定义一个Visitor类.现在我遇到的问题是存在一些循环依赖的规则,例如:
  1. boolExpr : boolTerm 'or' boolTerm ;
  2. boolTerm : boolAtom 'and' boolAtom ;
  3. boolAtom : '(' boolExpr ')'
  4. | ... ;

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

  1. //BoolExprVisitor.fs
  2. let boolExprVisitor = { new BaseVisitor<AST.BoolExpr>() with
  3. override __.VisitBoolExpr(context: BoolExprContext) =
  4. context.boolTerm() |> mapAccept boolTermVisitor |> AST.BoolExpr
  5. }
  6.  
  7. //BoolTermVisitor.fs
  8. let boolTermVisitor = { new BaseVisitor<AST.BoolTerm>() with
  9. override __.VisitBoolTerm(context: BoolTermContext) =
  10. context.boolAtom() |> mapAccept boolAtomVisitor |> AST.BoolTerm
  11. }
  12.  
  13. //BoolAtomVisitor.fs
  14. let boolAtomVisitor = { new BaseVisitor<AST.BoolAtom>() with
  15. override __.VisitBoolAtom(context: BoolAtomContext) =
  16. context.boolExpr() |> accept boolExprVisitor |> AST.BoolAtom
  17. }

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

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

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

  1. //AST.fs
  2. type BoolExpr =
  3. | BoolConjunctionExpr of BoolOp * BoolExpr list
  4. | ...
  5.  
  6. //ExpressionVisitors.fs
  7. let boolExprVisitor = { new BaseVisitor<AST.BoolExpr>() with
  8. override this.VisitBoolExpr(context: BoolExprContext) =
  9. context.boolTerm() |> mapAccept this |> AST.BoolConjunctionExpr AST.Or
  10.  
  11. override this.VisitBoolTerm(context: BoolTermContext) =
  12. context.boolAtom() |> mapAccept this |> AST.BoolConjunctionExpr AST.And
  13.  
  14. override this.VisitBoolAtom(context: BoolAtomContext) =
  15. context.boolExpr() |> accept this
  16. }

猜你在找的设计模式相关文章