假设我正在实现一个非常简单的玩具语言解析器。我正在决定是使用 DU 还是记录类型(也许两者混合?)。该语言的结构如下:
a Namespace consists of a name and a list of classes
a Class consists of a name and a list of methods
Method consists of a name, return type and a list of Arguments
Argument consists of a type and a name
使用这种简单语言的程序示例:
namespace ns {
class cls1 {
void m1() {}
}
class cls2 {
void m2(int i, string j) {}
}
}
您将如何对此进行建模?为什么?
最佳答案
您几乎肯定想要使用 DU 来实现交替,其中代码结构的任何部分都可能是多种可能性之一。混合可能是理想的,尽管您可以使用元组代替记录 - 这可能会使使用更简单,但可能更难以阅读和维护,因为元组中没有命名项。
我会把它建模成这样
type CompilationUnit = | Namespace list
and Namespace = { Name : String
Body : NamespaceBody }
and NamespaceBody = | Classes of Class list
and Class = { Name : String
Body : ClassBody }
and ClassBody = | Members of Member list
and Member = | Method of Method
and Method = { Name : String
Parameters : Parameter list option
ReturnType : TypeName option
Body : MethodBody }
and Parameter = { Name : String
Type : TypeName }
and MethodBody = ...
and TypeName = ...
使用您的示例语言时,对 DU 的需求可能并不明显,但一旦您在代码中有任何可能是一项或多项的项目,就会变得清楚。举例来说,如果您向类中添加字段 - 您只需向 Member
添加新的 Field
区分即可。
如果您使用语法来解析您的语言(LL/LALR 或类似语言),您可能需要为语法中的每个交替规则匹配一个 DU。
关于.net - 选择是否对 F# 中的小型 AST 使用可区分联合或记录类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7183577/