首页 > 解决方案 > 是否可以将 F# 类型提供程序设计为生成 AST 类型和解析器?

问题描述

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

在高层次上,这与 ANTLR 等解析器生成器工具相同,后者采用语法文件并为目标语言生成代码。

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

它可能看起来像这样:

[<Literal>]
let Grammar = "
program
   : statement +
   ;

statement
   : 'if' paren_expr statement
   | 'if' paren_expr statement 'else' statement
   | 'while' paren_expr statement
   | 'do' statement 'while' paren_expr ';'
   | '{' statement* '}'
   | expr ';'
   | ';'
   ;

paren_expr
   : '(' expr ')'
   ;

expr
   : test
   | id '=' expr
   ;

test
   : sum
   | sum '<' sum
   ;

sum
   : term
   | sum '+' term
   | sum '-' term
   ;

term
   : id
   | integer
   | paren_expr
   ;

id
   : STRING
   ;

integer
   : INT
   ;


STRING
   : [a-z]+
   ;


INT
   : [0-9] +
   ;

WS
   : [ \r\n\t] -> skip
   ;
"

type MyAst = AstProvider<Grammar>

let myAst = MyAst.TryParse("int x = 1;")

问题:

  1. 这对于现在的类型提供者来说真的可行吗?
  2. 有没有实施的例子?

标签: f#type-providers

解决方案


我在 4 年前建立了这样一个库,您可以在https://github.com/aastevenson/FSharp.Text.Experimental.Transform仔细阅读

文档相当广泛和完整,包括教程、示例、API 参考等。如果您只是对解析器感兴趣,请参阅Parsing with FSharp.Text.Experimental.Transform,它通过与 FParsec 的比较进行演示。

该库还可以通过定义转换子树的函数对生成的 AST 进行转换。这是文档中一个非常简单的 Hello World 示例

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"

但是,如果您只是对解析器感兴趣,那么您可以忽略库的转换部分。提取已解析字符串的不同 AST 元素仍然非常容易。

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


推荐阅读