F#类型提供程序是否可以设计为生成AST类型和解析器?

F#类型提供程序是否可以设计为生成AST类型和解析器?,f#,type-providers,F#,Type Providers,我对F#类型提供程序的理解是,它们实际上是从字符串到类型的编译时函数。该类型还可以附加静态方法,因此它们也可以用于代码生成 在高层,这与ANTLR等解析器生成器工具相同,后者获取语法文件并生成目标语言的代码 因此,我想象一个F#type提供程序,它接受一个语法字符串,并为AST和解析函数提供一个类型作为静态成员 可能是这样的: [] 让语法=” 程序 :声明+ ; 陈述 :“if”paren_expr语句 |'如果'paren_expr语句'else'语句 |“while”paren_expr语

我对F#类型提供程序的理解是,它们实际上是从字符串到类型的编译时函数。该类型还可以附加静态方法,因此它们也可以用于代码生成

在高层,这与ANTLR等解析器生成器工具相同,后者获取语法文件并生成目标语言的代码

因此,我想象一个F#type提供程序,它接受一个语法字符串,并为AST和解析函数提供一个类型作为静态成员

可能是这样的:

[]
让语法=”
程序
:声明+
;
陈述
:“if”paren_expr语句
|'如果'paren_expr语句'else'语句
|“while”paren_expr语句
|“执行”语句“而“执行”
|“{”语句*“}”
|expr';'
| ';'
;
巴黎大学
:“('expr')”
;
expr
:测试
|id“=”表达式
;
测试
:sum

|sum'这当然是可以构建的,因为您所需要做的就是根据SDK的工作方式“填充类型”。类型提供程序本身将为您的语法实现解析器,就像FSharp.Data Type提供程序为JSON、XML等实现解析器一样


非常有趣(而且有趣!)例如,它接受F#source作为输入,生成一个程序集,读取该程序集,并使用类型提供程序基础结构读取程序集,并从生成的代码中提供类型。因此,您确实可以做很多事情,尽管我不能说我建议遵循Mixin类型提供程序的功能。

I4年前建了这样一个图书馆,你可以在

这是相当广泛和完整的,包括教程、示例、API参考等。如果您对解析器感兴趣,请参阅,其中通过与FParsec的比较进行了演示

该库还可以通过定义转换子树的函数对生成的AST进行转换

打开FSharp.Text.Experimental.Transform
//指定语法
[]
让语法=”“
节目:迎接“世界”;
问候语:“欢迎”|“你好”;
""" 
//将语法传递给类型提供程序
HW类型=语法提供程序
让我们来问候一下(输入:HW.问候语)=
将inp.TryMatch()与
|Some->HW.Greeting.Construct()
|无->输入
HW.ParseString“欢迎世界”//parse输入字符串
|>HW.Program.ApplyOnePass welcomeToHello//apply转换函数
|>HW.Pretty//解析为字符串
|>printfn“%s”//prints“hello world”
但是如果你只是对解析器感兴趣,那么你可以忽略库中的转换部分。提取解析字符串的不同AST元素仍然很容易

请注意,我很久没有接触过这个项目了

open FSharp.Text.Experimental.Transform

// specify the grammar
[<Literal>]
let grammar = """
    Program     :   Greeting 'world';
    Greeting    :   'welcome' | 'hello';
    """ 

// pass the grammar to the type provider
type HW = GrammarProvider<grammar>

let welcomeToHello (inp: HW.Greeting) =
    match inp.TryMatch<"welcome">() with
    | Some _ -> HW.Greeting.Construct<"hello">()
    | None   -> inp

HW.ParseString "welcome world"                  // parse input string
|> HW.Program.ApplyOnePass welcomeToHello       // apply transformation function
|> HW.Pretty                                    // unparse to a string
|> printfn "%s"                                 // prints "hello world"