以编程方式访问fslex和fsyacc

时间:2013-10-05 03:01:11

标签: f#

fslex和fsyacc工具目前需要两阶段编译,生成随后由fsc编译的文件。在我看来,如果源文件是嵌入式资源,以编程方式提供给fslex和fsyacc,并且使用CodeDom即时编译生成的代码,这些工具将更容易使用。

这是否可行,如果是,那么实现这一目标需要什么?

2 个答案:

答案 0 :(得分:4)

乔恩,这是一个很好的问题;实际上,我对fsharp-tools(F#的新词法分析器和解析器 - 生成器实现)的设计目标之一就是可以嵌入它们,特别是为了启用这样的场景。

到目前为止,我还没有实现(还)可以让你在 fsharplex 中轻松 的功能,但是不要让它阻止你;我已经用或多或少的纯功能样式编写了 fsharplex (以及 fsharp-tools 中的其他工具),所以不应该有任何问题全球状态或类似的东西。破解编译器代码应该相对简单,这样你就可以使用一些组合器构建一个正则表达式AST,运行编译器来获取编译的DFA,然后将状态机的IL发送到动态程序集(然后你可以“烘焙”并执行)。

fsharpyacc 目前使用的方法是将大部分编译逻辑放入纯函数库中, Graham ;我的想法是语法分析/操作和解析器DFA编译算法应该是通用的,可重用的,并且易于测试,因此任何想要使用F#构建语言工具的人都将拥有构建它们的通用框架。同样, Graham 的贡献/改进可以轻松地回流到 fsharpyacc 。最后,我将修改 fsharplex 以使用相同的方法,这将允许您只需引用NuGet包就可以将regex编译器嵌入到您自己的代码中(您只需要编写代码来生成来自DFA的IL。

fsharplex fsharpyacc 使用MEF允许插入各种后端;目前,出于兼容性原因,它们仅针对fslexfsyacc,但我希望实现基于代码的后端(与当前基于表的后端相反)以获得更好的性能未来。

更新 - 我只是重新阅读了您的问题,并注意到您希望自己嵌入*.fsl*.fsy文件,并在运行时调用相应的编译器。您可以通过编译工具并从您自己的项目中引用程序集来实现此目的。 IIRC,我在两个编译器中都暴露了一个入口点,因此可以从外部代码调用它们;主要入口点(例如,从控制台调用工具时执行的操作)只需解析命令行参数,然后将它们传递到此“外部”入口点。

直接嵌入*.fsl*.fsy文件存在一个问题;如果嵌入它们,则在运行时通过 fsharplex fsharpyacc 运行它们,用户定义的操作(例如,匹配词法分析器或解析器规则时执行的代码) )仍将被指定为F#源代码 - 您需要决定如何将它们编译为可执行代码。

答案 1 :(得分:2)

提供类似于解析器组合的接口应该是可行的,后端使用表达式树(F#的LISP“eval”)或类似的东西,以便与语言完全集成。或者是TypeProvider。有很多选择。如果表生成是一项昂贵的计算,则可以通过提供Cache来缓存它,例如磁盘缓存。

我认为除了缺乏时间,奉献精神和专业知识之外,什么都没有阻止我们使用具有(非monadic)解析器类似组合器的接口的工具,而是有效的编译实现。

有时我会回到我的这个宠物项目中,使用代数方法来优化使用组合器在源中指定的正则表达式(和词法分析器),然后编译到状态机。它仍然缺乏一些关键的效率,但它是:

https://github.com/toyvo/ocaml-regex-algebraic